[PHP] Benchmark: opzoeken van woord x in een zin

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • OkkE
  • Registratie: Oktober 2000
  • Laatst online: 04-09 08:16

OkkE

CSS influencer :+

Modbreak:Dit topic is afgesplitst van [rml][ PHP ] weet niet met welke stringfunctie dit kan[/rml].
Kaastosti schreef op woensdag 04 mei 2005 @ 11:28:
Er is helaas geen functie
getStringBeforeNumberOfChars(' ', 10)
ik denk dat de manier die Simon je geeft toch wel de meest gebruikte is voor het probleem. Wel zo makkelijk ook eigenlijk, want hoe vaak komt dit voor :)
Combineren! :) Zelf die functie maken met het idee van Simon. :P Nee maar ik geloof inderdaad niet dat er zo'n functie is, maar is ook niet moeilijk te doen met explode();

// Edit

Verveelde me, dus dit even snel in elkaar gegooid. :)
PHP:
1
2
3
4
5
6
7
8
9
function getStrBeforeChar( $char="", $place=1, $str="" )
{
    $arr = explode( $char, $str );
    return implode( " ", array_slice($arr, 0, $place) );
}

$s = "Sed vel urna vitae justo viverra vulputate.";
echo "<b>Origineel:</b> ".$s;
echo "<br><b>4 woorden:</b> ".getStrBeforeChar( " ", 4, $s );

[ Voor 42% gewijzigd door NMe op 06-05-2005 00:09 ]

“The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer.”
QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers.


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
met regex kan het alsvolgt:
preg_match("/((.*?)\s){10}/", $strn, $matches);
$eersteTienWoorden = $matches[0];

de vraag is alleen of explode() niet sneller werkt

//edit
ook een benchmark:
http://download.bleq.nl/bench_php.phps

[ Voor 45% gewijzigd door Fl4sh3r op 04-05-2005 12:39 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Wat dacht je van:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$afterSpace = 10;
$offset = 0;
$string = "Reageer ontopic, plaats geen onzinnige berichten en ga niet flamen of uitlokken (trollen).";

while ($offset !== false && $i++ < $afterSpace)
  $offset = strpos($string, " ", $offset + 1);

if ($offset === false)
    echo "not found";
else
    echo substr($string, 0, $offset);

?>
(niet getest)

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 21:04

MBV

dat gaat echt langer duren, Emiel. Combinatie van explode en implode lijkt mij wel sneller dan dat for-loopje van mij. Maar de basis blijft echt hetzelfde. Maar doe eens een benchmark: hoelang doet hij erover als je 1000x de eerste 500 woorden wilt vinden met explode en implode? Wordt dat echt onacceptabel? In het ergste geval zou je een CGI-script zelf kunnen schrijven in C++, dat is veel sneller.

[ Voor 18% gewijzigd door MBV op 04-05-2005 11:51 ]


Acties:
  • 0 Henk 'm!

Verwijderd

MBV schreef op woensdag 04 mei 2005 @ 11:50:
dat gaat echt langer duren, Emiel. Combinatie van explode en implode lijkt mij wel sneller dan dat for-loopje van mij. Maar de basis blijft echt hetzelfde. Maar doe eens een benchmark: hoelang doet hij erover als je 1000x de eerste 500 woorden wilt vinden met explode en implode? Wordt dat echt onacceptabel? In het ergste geval zou je een CGI-script zelf kunnen schrijven in C++, dat is veel sneller.
Het ligt er natuurlijk aan hoe groot de gemiddelde $afterSpace is die je gebruikt, maar ik weet bijna zeker dat mijn manier sneller is dan het gebruik van een explode (indien 500 woorden: array met 500 items vullen). Benchmarks laat ik graag aan de TS over :).

Goed, ik verveelde me:

Zie http://public.emielmols.info/benchmark.phps

Resultaat:
code:
1
2
3
Icarus ~ # php benchmark.php
Emiel: 0.017609
MBV: 0.144588

Conclusie: explode is traaaag (zelfs bij ~15 woorden), zoals verwacht. Ik verwacht niet dat implode veel sneller is.

[ Voor 17% gewijzigd door Verwijderd op 04-05-2005 12:08 . Reden: +benchmark ]


Acties:
  • 0 Henk 'm!

  • OkkE
  • Registratie: Oktober 2000
  • Laatst online: 04-09 08:16

OkkE

CSS influencer :+

Ik heb mijn manier (explode + implode) er nog even tussen gezet, en die zat tussen de andere twee in. :)

“The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer.”
QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers.


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
Verwijderd schreef op woensdag 04 mei 2005 @ 11:56:
Goed, ik verveelde me:

Zie http://public.emielmols.info/benchmark.phps

Resultaat:
code:
1
2
3
Icarus ~ # php benchmark.php
Emiel: 0.017609
MBV: 0.144588

Conclusie: explode is traaaag (zelfs bij ~15 woorden), zoals verwacht. Ik verwacht niet dat implode veel sneller is.
Die benchmark klopt niet, want die van Emiel wordt maar 1 keer gedaan en geen 1000

Kijk eens naar die "&& $i++ < $afterSpace", die $i wordt nooit meer op 0 gezet. De eerste keer $i = 0, de tweede en keren daarna is ie al >= $afterSpace en zal die hele loop dus niet worden uitgevoerd.

http://download.bleq.nl/bench_php2.phps de code is niet al te netjes, maar t doet z'n ding ;)
code:
1
2
3
4
5
6
7
Tot spatie  Fl4sh3r (preg_match)    Emiel (strpos substr)   MBV (explode)
10          0.46522402763367        0.88210487365723        1.1723880767822
20          0.52316689491272        1.1414139270782     1.3555870056152
30          0.57671904563904        1.4923930168152     1.4994080066681
40          0.63903498649597        1.6435859203339     1.65944480896
50          0.68750810623169        1.9021379947662     1.8228280544281
60          0.74108505249023        2.1515579223633     1.9610879421234

[ Voor 54% gewijzigd door Fl4sh3r op 04-05-2005 12:55 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
De manier van StrPos zal ( Mits goed uitgevoerd ) altijd sneller zijn dan de explode. Wat denk je dat explode gaat doen?

Die gaat gewoon netjes met StrPos de locatie van de spaties opzoeken en op dat punt de string splitsen. Hiervoor moet hij ook weer een array alloceren en daar de strings in doen. Dan kan je natuurlijk het makkelijkst gewoon door de string wandelen met StrPos. Dat zal de explode functie tenslotte ook moeten doen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Fl4sh3r schreef op woensdag 04 mei 2005 @ 12:42:
[...]


Die benchmark klopt niet, want die van Emiel wordt maar 1 keer gedaan en geen 1000

Kijk eens naar die "&& $i++ < $afterSpace", die $i wordt nooit meer op 0 gezet. De eerste keer $i = 0, de tweede en keren daarna is ie al >= $afterSpace en zal die hele loop dus niet worden uitgevoerd.

http://download.bleq.nl/bench_php2.phps de code is niet al te netjes, maar t doet z'n ding ;)
code:
1
2
3
4
5
6
7
Tot spatie  Fl4sh3r (preg_match)    Emiel (strpos substr)   MBV (explode)
10          0.46522402763367        0.88210487365723        1.1723880767822
20          0.52316689491272        1.1414139270782     1.3555870056152
30          0.57671904563904        1.4923930168152     1.4994080066681
40          0.63903498649597        1.6435859203339     1.65944480896
50          0.68750810623169        1.9021379947662     1.8228280544281
60          0.74108505249023        2.1515579223633     1.9610879421234
Goed punt inderdaad :) Overheen gekeken. Preg_match doet het dan inderdaad bijzonder netjes.

Acties:
  • 0 Henk 'm!

  • stekkel
  • Registratie: Augustus 2001
  • Laatst online: 17-09 08:05
Fl4sh3r schreef op woensdag 04 mei 2005 @ 12:42:
[...]

http://download.bleq.nl/bench_php2.phps de code is niet al te netjes, maar t doet z'n ding ;)
Wist je dat eval() een hele trage functie is en dat die waarschijnlijk de benchmarkresultaten kan beinvloeden?

Acties:
  • 0 Henk 'm!

  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05 09:40

GX

Nee.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
function pruts($string, $max)
{
    $counter=0;
    for ($i=0;$i<strlen($string);$i++)
    {
        if ($string{$i} == " ")
           $counter++;
        if ($counter==$max)
            break;
    }
    return substr($string,0,$i);
}


Ik zal ook eens kijken of ik deze kan benchen

Gebenched (source)
code:
1
2
3
4
5
~/www/john$ php -q ./spatiesbench.php
Emiel:   0.0044629
MBV:     0.0360346
GX:      0.0092414
Fl4sh3r: 0.0178197


winnaar is duidelijk :+

[ Voor 48% gewijzigd door GX op 04-05-2005 19:39 ]


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
GX schreef op woensdag 04 mei 2005 @ 19:21:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
function pruts($string, $max)
{
    $counter=0;
    for ($i=0;$i<strlen($string);$i++)
    {
        if ($string{$i} == " ")
           $counter++;
        if ($counter==$max)
            break;
    }
    return substr($string,0,$i);
}


Ik zal ook eens kijken of ik deze kan benchen

Gebenched (source)
code:
1
2
3
4
5
~/www/john$ php -q ./spatiesbench.php
Emiel:   0.0044629
MBV:     0.0360346
GX:      0.0092414
Fl4sh3r: 0.0178197


winnaar is duidelijk :+
Zelfde probleem als ik al eerder noemde over die van Emiel, je moet die $i op 0 zetten.

http://download.bleq.nl/bench_php3.phps
code:
1
2
3
4
5
6
7
8
9
strlen($string): 823

spaties Fl4sh3r           Emiel             MBV              GX
10      0.058330059051514 0.021034002304077 0.60167694091797 1.3237280845642
20      0.065638065338135 0.022664070129395 0.76059293746948 2.6887600421906
30      0.062294006347656 0.020734071731567 0.93934679031372 4.1746971607208
40      0.067097902297974 0.022790908813477 1.1035730838776  5.7865397930145
50      0.080018043518066 0.021029949188232 1.3348860740662  7.0966868400574
60      0.061047792434692 0.020951986312866 1.4608480930328  ??


EDIT:
de tijden van Emiel klopten niet, zoals T-Mob hieronder constanteert, $offset werd niet op 0 gezet.
code:
1
2
3
4
5
6
7
8
9
strlen($string): 823

spaties Fl4sh3r           Emiel            MBV              GX
10      0.05925989151001  0.28145623207092 0.59266304969788 1.3018169403076
20      0.062365055084229 0.53805017471313 0.76555705070496 2.6246871948242
30      0.06270694732666  0.78621006011963 0.9334499835968  4.4311029911041
40      0.063833951950073 1.0366020202637  1.0999629497528  5.4068660736084
50      0.062085866928101 1.2809829711914  1.2690479755402  6.9562339782715
60      0.063846111297607 1.6831789016724  ??               ??

/EDIT

Volgens mij werkt break niet op een for... die tijden zijn wel erg extreem bij GX

De eval had blijkbaar toch invloed. Mijn stukje was natuurlijk korter, dus minder tijd nodig bij eval. Uiteindelijk blijkbaar niet sneller dan Emiel's manier

Ik ga toch voor de reguliere expressie :+

Wat er met mijn tijden niet klopt, geen idee 8)7 ik zie niets in die ene regel wat niet klopt...

[ Voor 51% gewijzigd door Fl4sh3r op 04-05-2005 21:29 ]


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 23:12
Nou.. niet echt. Had er vanmiddag ook al even mee gespeeld (ook jouw methode toegevoegd). Mijn conclusie was dat het er nogal aan ligt hoe lang de string is waarin je zoekt en hoeveel woorden je wil hebben. Sommige methoden zijn met lange strings erg duur (explode vooral), andere worden erg duur als je veel woorden zoekt (strpos-methode en string doorwandelen worden harder duurder met het aantal gezochte woorden dan explode()-methode). De enige methode die bij elke combinatie acceptabel presteerde is die met de regex.

In jouw functie kan trouwens nog een optimalisatie: de strlen() kan je uit het for-loopje halen door hem slechts één maal te berekenen voor je het loopje start. Scheelt net weer ff ;)

edit:
Fl4sh3r schreef op woensdag 04 mei 2005 @ 20:58:
De eval had blijkbaar toch invloed. Mijn stukje was natuurlijk korter, dus minder tijd nodig bij eval. Uiteindelijk blijkbaar niet sneller dan Emiel's manier
Volgens mij gaat daar iets mis. Emiels tijden zijn namelijk nagenoeg constant en dat is onmogelijk aangezien er per stap 10 strpos()-en meer uitgevoerd moeten worden... Dat geldt trouwens ook voor je eigen tijden...

edit2: Fout bij Emiel gevonden... Je moet $offset binnen de 1000*loopen op nul zetten, niet ervoor. Nu berekent ie maar 1x de output per stap. (Haha, slow-chat editten)

[ Voor 33% gewijzigd door T-MOB op 04-05-2005 21:28 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05 09:40

GX

Nee.

T-MOB schreef op woensdag 04 mei 2005 @ 21:15:
[...]

Nou.. niet echt. Had er vanmiddag ook al even mee gespeeld (ook jouw methode toegevoegd). Mijn conclusie was dat het er nogal aan ligt hoe lang de string is waarin je zoekt en hoeveel woorden je wil hebben
Ik kwam er inderdaad ook achter :(

Echter deed bij lange strings mijn functie er nog steeds niet meer dan 1 seconde over (geen één overigens, met de emiel-fout er nog in); ik geef eval de schuld :P

Overigens vond ik persoonlijk het duurder worden best jammer, had ik ook niet van te voren aan zien komen.
In jouw functie kan trouwens nog een optimalisatie: de strlen() kan je uit het for-loopje halen door hem slechts één maal te berekenen voor je het loopje start. Scheelt net weer ff ;)
Klopt; echter vond ik het in dit geval niet bijster noodzakelijk :)

edit:

geh, bij mijn script krijg ik af en toe negatieve waarden bij average times :P


negatieve waarden gerepareerd, nu is dit mijn output bij 60 spaties en die lange string uit een andere source hier ergens:

code:
1
2
3
4
Emiel:   0.203141236305
MBV:     0.257047271729
GX:      0.0108384370804
Fl4sh3r: 0.0938363075256

Ziet er grappig uit natuurlijk, maar er lijkt geen drol van te kloppen.
alhier source ik raad aan om de get_microtime() sowieso even over te nemen :P

[ Voor 26% gewijzigd door GX op 04-05-2005 22:04 ]


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 23:12
Toch maar ff in een nieuwe post, fout in de benchmark zat in de regex. Je moet $spaceNr concatten om daadwerkelijk output te krijgen. Met kloppende output is een regex overigens nog steeds het beste:
strlen($string): 823
spaties	    Fl4sh3r	       Emiel	        MBV	        GX
10	0.0641419887543	0.145102977753	0.393733978271	0.744172096252
20	0.094183921814	0.268368005753	0.477469921112	1.466173172
30	0.127284049988	0.394625902176	0.560317993164	2.29862523079
40	0.156450986862	0.523796081543	0.64247584343	3.01198291779
50	0.19378900528	0.667150974274	0.728325128555	3.8662071228
60	0.22429895401	0.77206993103	0.814624071121	4.63668894768


EDIT:
GX schreef op woensdag 04 mei 2005 @ 21:41:
edit:

geh, bij mijn script krijg ik af en toe negatieve waarden bij average times :P
offtopic:
Leip... test je op Blue Gene ofzo? :o

[ Voor 17% gewijzigd door T-MOB op 04-05-2005 21:52 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05 09:40

GX

Nee.

Ik ben er uit
code:
1
2
3
4
5
6
7
        Emiel           MBV             GX              Fl4sh3r
10      0.0362541437149 0.153687977791  0.142634916306  0.0200412273407
20      0.0782668352127 0.216257309914  0.271225726604  0.0249896883965
30      0.0866009632746 0.217268466949  0.328568951289  0.0313873449961
40      0.0980850279331 0.22532158494   0.391987425089  0.0371068477631
50      0.113593840599  0.235495605469  0.46418448925   0.0471341323853
60      0.12773001194   0.247109127045  0.535764431953  0.055618528525

[ Voor 210% gewijzigd door GX op 04-05-2005 22:31 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Als we het toch over mini-optimalisaties hebben; hier een getweakte versie van Emiel's methode die nog zeker 10% sneller is :)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
$afterSpace = 10;
$offset = -1;

do
{
    $offset = strpos($string, ' ', ++$offset);
}
while (--$afterSpace && $offset !== false);

if ($offset === false)
    echo 'not found';
else
    echo substr($string, 0, $offset);

Hier zitten dus de volgende optimalisaties in:

1) de $i is overbodig; je kan net zo goed $afterSpace naar 0 laten tellen (en een logische afvraging is sneller dan de vergelijking met een andere variabele)
2) een do-while scheelt hier 1 conditie-afvraging tov een while
3) pre-increments zijn sneller dan optellingen (en ook sneller dan post-increments btw)
4) single quotes gebruikt voor de needle in de strpos functie
5) in conditie-afvragingen kan volgorde belangrijk zijn. In deze test wordt --$afterSpace eerder 0 dan dat $offset false wordt. Dat scheelt je in deze benchmark dus 1 test in de conditie-afvraging

Overigens is Emiel's methode hier de beste omdat hij ook situaties opvangt waarbij het aantal spaties niet gevonden wordt, en daar netjes melding van geeft. Dat mis ik in de andere methoden. Eigenlijk zou je dus dit moeten gebruiken om een eerlijk vergelijk te krijgen:
PHP:
1
2
3
4
5
6
7
8
9
10
$afterSpace = 10;
$offset = -1;

do
{
    $offset = strpos($string, ' ', ++$offset);
}
while (--$afterSpace);

echo substr($string, 0, $offset);

en dan blijkt deze versie opeens veel dichter bij de snelheid van de RegExp methode te komen ;)

Als je zaken gaat benchen zorg dan niet alleen dat de functies die je gaat benchen niet alleen dezelfde input krijgen, maar ook dezelfde output geven. Gebruik ook gewoon functies, en roep die 1000x aan - de functiecall overhead is dan in alle gevallen gelijk, en je kan de output toetsen. Je weet dan ook dat alle functies hetzelfde doen, en dat je dus ook hetzelfde benched.
In dit geval zou ik gewoon het volgende doen:
PHP:
1
2
3
4
5
6
7
function benchme($string, $spaces)
{
  //-- hier de methode

  //-- return part; gedeelte string t/m aantal spaties, of false
  return $something;
}

[ Voor 42% gewijzigd door crisp op 04-05-2005 23:16 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05 09:40

GX

Nee.

crisp schreef op woensdag 04 mei 2005 @ 22:50:
Overigens is Emiel's methode hier de beste omdat hij ook situaties opvangt waarbij het aantal spaties niet gevonden wordt, en daar netjes melding van geeft. Dat mis ik in de andere methoden. Eigenlijk zou je dus dit moeten gebruiken om een eerlijk vergelijk te krijgen:
Ho eens; wanneer bijvoorbeeld de mijne het juiste aantal spaties niet heeft gevonden is $i evengroot als de gehele string, en output de substr() dus netjes de hele string; Een foutmelding zou hier (naar mijn mening) niet gewenst danwel overbodig zijn.

in any case, meer benchmarks \o/

code:
1
2
3
4
5
6
7
8
gx@oceserver:~/www/john$ php -q ./spatiesbench.php
   Emiel     MBV       GX        Fl4sh3r   Crisp
10 0.036597  0.145239  0.143305  0.021869  0.024767
20 0.053444  0.162800  0.217552  0.029925  0.035671
30 0.069438  0.178288  0.293107  0.039500  0.046501
40 0.085331  0.192821  0.366168  0.049158  0.057144
50 0.101603  0.207580  0.443467  0.059285  0.067738
60 0.117449  0.220994  0.529521  0.069501  0.078168


Lekker crisp z'n edit niet gelezen. Oude manier gebenched.
@crisp; die strlen had ik in nieuwere benches inderdaad al in een variabele geknikkert

[ Voor 9% gewijzigd door GX op 04-05-2005 23:50 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Hier een voorbeeld van een benchmark setup die gewoon eerlijk is aangezien elke functie dezelfde input krijgt, en ook dezelfde output dient terug te geven (string tot aan aantal spaties, of gehele string indien minder spaties gevonden): http://allcrispy.com/benchmarks.phps

Ik heb uiteraard wat dingen herschreven om te voldoen aan de output-rule. GX: jij bent bijvoorbeeld ook sneller af door de strlen op te slaan in een variabele ipv elke iteratie uit te vragen ;)

[ Voor 14% gewijzigd door crisp op 04-05-2005 23:48 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

http://allcrispy.com/benchmarks.phps geupdate met een output check; de regexp methode van Fl4sh3r valt hierbij door de mand omdat die niet de gewenste output oplevert en is dus gediskwalificeerd :P
Ik heb de methode van GX ook even nog wat sneller gemaakt :P

Edit: Fl4sh3r methode gefixed, dus hij mag weer meedoen ;)

[ Voor 53% gewijzigd door crisp op 05-05-2005 00:32 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
Ik was net de methodes aan het herschrijven zodat ze false teruggeven als het opgevraagde aantal spaties er niet in staat, bovendien wat optimalisatie:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  function Fl4sh3r($string, $spaces) {
    if(preg_match("/((.*?)\\s){".$spaces."}/", $string, $matches)==0)
      return false;
    return $matches[0];
  }

  function Emiel($string, $spaces) {
    $offset = -1;

    do {
      $offset = strpos($string, ' ', ++$offset);
      if($offset === false)
        return false;
    } while(--$spaces);

    return substr($string, 0, $offset);
  }

  function GX($string, $spaces) {
    $strlen = strlen($string);
    for($i=0;$i<$strlen;$i++) {
      if($string{$i} == ' '&& (!--$spaces))
        return substr($string,0,$i);
    }
    return false;
  }

  function MBV($string, $spaces) {
    $exploded = explode(' ', $string);
    if(count($exploded) <= $spaces) return false;

    $output = '';
    for($i=0;$i<$spaces;$i++)
      $output .= $exploded[$i].' ';

    return $output;
  }


//edit MBV erbij

[ Voor 23% gewijzigd door Fl4sh3r op 05-05-2005 00:36 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Fl4sh3r schreef op donderdag 05 mei 2005 @ 00:30:
Ik was net de methodes aan het herschrijven zodat ze false teruggeven als het opgevraagde aantal spaties er niet in staat, bovendien wat optimalisatie:
Ok, meegenomen in http://allcrispy.com/benchmarks.phps (voor zover daadwerkelijk sneller) :)

Jouw methode heeft 1 groot manco: op het moment dat je wilt gaan zoeken naar meer spaties dan er in de string zitten gaat jouw regexp backtracken, wat (bij mij) parsetimes oplevert van +/- 1 seconde per functiecall(!)

MBV's methode kon ook anders mbv array_slice, dus daar heb ik ook een alternatief van gemaakt die bij grotere waarden beter lijkt te performen.

[ Voor 15% gewijzigd door crisp op 05-05-2005 00:46 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

Verwijderd

/me aait crisp. Werkt inderdaad een stukje sneller. Nieuwste benches zien er bij mij zo uit (350mhz oid).

Oja, waar is de TS gebleven :+?

[ Voor 16% gewijzigd door Verwijderd op 05-05-2005 00:47 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Die van MBV is na de rewrite trouwens de kortste:
PHP:
1
2
3
4
function benchme_MBV2($string, $spaces)
{
    return implode(' ', array_slice(explode(' ', $string), 0, $spaces));
}

:P

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
Die laatst rewrite van MBV geeft geen false terug, wat ik netter vind dan de hele string, maar goed MHO.

Dat probleem van die backtracking, 8)7 niet getest, wel op te lossen, maar maakt de code groter en dus trager.

Mijn laatste versie:
http://download.bleq.nl/bench_php4.phps

nu slapen :z

[ Voor 3% gewijzigd door Fl4sh3r op 05-05-2005 01:01 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Fl4sh3r schreef op donderdag 05 mei 2005 @ 01:01:
Die laatst rewrite van MBV geeft geen false terug, wat ik netter vind dan de hele string, maar goed MHO.

Dat probleem van die backtracking, 8)7 niet getest, wel op te lossen, maar maakt de code groter en dus trager.

Mijn laatste versie:
http://download.bleq.nl/bench_php4.phps

nu slapen :z
Als je hem met false wilt hebben kan ook:
PHP:
1
2
3
4
5
6
function benchme_MBV2($string, $spaces)
{
    $exploded = explode(' ', $string);
    if (count($exploded) < $spaces) return false;
    return implode(' ', array_slice($exploded, 0, $spaces));
}

maar of je false of juist de hele string terug wilt hebben hangt af van de context waarin je zoiets wilt gebruiken. count() is overigens niet zo heel duur in dit geval.
Overigens is bovenstaande functie bij grotere strings en meer spaties sneller dan de 'improved Emiel function', en op het moment dat je naar meer spaties vraagt dan er zijn is hij zelfs aanzienlijk sneller.
Daarbij zit dit logisch ook goed in elkaar, en zal dus IRL mijn voorkeur hebben boven de reguliere expressie. Het backtrack probleem zal namelijk zeker gaan voorkomen in echte situaties...

[ Voor 7% gewijzigd door crisp op 05-05-2005 01:13 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
Nog 1 post, het blijft boeien

die $exploded die je count() is nooit gemaakt... (te laat)

Als ik bij de mijne erbij zet:
if(count(explode(' ',$string)) <= $spaces) return false;
werkt ie wel, maar is ie behoorlijk traag... als je suggesties hebt, ik lees ze graag (morgen)

[ Voor 7% gewijzigd door Fl4sh3r op 05-05-2005 01:14 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

de count is niet duur, de explode juist wel ;)

suggestie:
PHP:
1
2
3
4
function benchme_Fl4sh3r($string, $spaces)
{
    return preg_match('/^([^ ]* ){' . $spaces . '}/', $string, $matches) ? $matches[0] : false;
}

;)

en ja, die is lightning-fast (zelfs sneller dan jouw regexp, maar deze heeft daarbij ook geen backtrack probleem omdat het een greedy match is) :)
Overigens was de \s bij jou ook foutief omdat die meer matched dan alleen een spatie.

[ Voor 52% gewijzigd door crisp op 05-05-2005 01:36 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Fl4sh3r
  • Registratie: Juni 2002
  • Laatst online: 02-10-2023
Exact hetzelfde bedacht ik me vanmorgen toen ik wakker werd, nu nog ff in mijn benchmark gooien.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Topicstarter
Modbreak:Bovenstaande berichten zijn afgesplitst van [rml][ PHP ] weet niet met welke stringfunctie dit kan[/rml].

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Ik kwam op nog een alternatieve methode mbv strtok, helaas bleek dit trager dan de andere methoden:
PHP:
1
2
3
4
5
6
7
8
9
10
function benchme($string, $spaces)
{
    $output = strtok($string, ' ');
    while (--$spaces && $token = strtok(' '))
    {
        $output .= ' ' . $token;
    }

    return $spaces ? false : $output;
}


Een snellere check om te kijken of het aantal spaties ueberhaupt wel voorkomt in de gegeven string kan eventueel mbv substr_count.

Een andere methode die wellicht al deze methoden qua snelheid kan overtreffen is wanneer je zelf een functie schrijft in bijvoorbeeld C(++) en dat compileert als een loadable module :)

[ Voor 19% gewijzigd door crisp op 06-05-2005 00:32 ]

Intentionally left blank

Pagina: 1