Įpraiškų greičio testai

Šiandien visą dieną rašiau kursinį darbą (tikrai ne apie programavimą… Apie valstybės išlaidų skirstymą pagal valstybės funkcijas bei struktūrinių pokyčių tendencijas :). Tai vakare sugalvojau kad reikia truputį pailsėt ir nuėjau pasibandyt įpraiškų greičių.

Tarkim turim stringą „Čia gali būti tiek Perlas, tiek Pitonas“ ir norim patikrint ar jame yra „Perl“ arba „Python“ (šiuo atveju yra tik „Perl“, nes „Python“ parašytas su trumpa „i“). Šiam tikslui tiktų labai paprasta įpraiška (tiems, kas jau nori rėkti „bet čia juk nereikia įpraiškos!“ pasakysiu „perskaitykit iki galo“ ;)

/Perl|Python/

Aišku šitą dalyką galima optimizuoti, nes abu žodžiai prasideda iš „P“:

/P(erl|ython)/

Viskas gerai, tik tuos skliaustus visada permeta į $1, kas stabdo visą reikalą. Prisiminus išplėstą įpraiškų sintaksę:

/P(?:erl|ython)/

Turbūt nieko geriau jau neišeis išspaust iš šios įpraiškos. Na bet jei jau prisiminėm išplėstą įpraiškų sintaksę, tai dar vieną daiktą galima pridėt (čia jau pavyzdys stiliumi „Nuo didelio rašto išėjo iš krašto“):

/(?<=P)(?:erl|ython)/

Na, palyginimui dar reiktų pridėti ir sprendimą be įpraiškos:

(((index $f, 'Perl') != -1) ||
 ((index $f, 'Python') != -1)) ? 1 : 0;

Na, turim visus variantus, tai reikia juos išsitestuoti:

#!/usr/bin/perl
$f ="Čia gali būti tiek Perlas, tiek Pitonas";

sub regnormal { $f =~ /Perl|Python/;         }
sub regnonopt { $f =~ /P(erl|ython)/;        }
sub regopt    { $f =~ /P(?:erl|ython)/;      }
sub regfancy  { $f =~ /(?<=P)(?:erl|ython)/; }

sub strstr {
(((index $f, 'Perl') != -1) ||
 ((index $f, 'Python') != -1)) ? 1 : 0;
}

use Benchmark;
timethese(-10, { regnormal => 'regnormal', 
                 regnonopt => 'regnonopt',
                 regopt    => 'regopt',
                 regfancy  => 'regfancy',
                 strstr    => 'strstr' });

Štai rezultatai:

C:devellab>perl regex.pl
Benchmark: running regfancy, regnonopt, regnormal, regopt, strstr, for at least 10
CPU seconds...
  regfancy: 17 wallclock secs (12.28 usr +  0.04 sys = 12.32 CPU) @ 67725.60/s
(n=834244)
 regnonopt: 14 wallclock secs (10.00 usr +  0.04 sys = 10.04 CPU) @ 82688.20/s
(n=830603)
 regnormal: 15 wallclock secs (10.10 usr +  0.02 sys = 10.12 CPU) @ 52365.33/s
(n=530199)
    regopt: 14 wallclock secs (10.13 usr +  0.01 sys = 10.14 CPU) @ 154168.16/s
(n=1564036)
    strstr: 13 wallclock secs (10.15 usr + -0.01 sys = 10.14 CPU) @ 272950.11/s
(n=2768533)

Aišku nenuostabu, kad variantas be įpraiškų buvo pats greičiausias. Gal net esu šiek tiek nustebęs, kad jis greitesnis už įpraišką tik du kartus (tikėjausi bent kokių penkių kartų). Viso šio dalyko pamoka tokia: nenaudokite įpraiškų, jei galima išsiversti be jų (na, arba jei be jų kodas susidėtų iš daugybės sudėtingų if – jau ir tas subas, kurį parašiau vizualiai atrodo baisiau už įpraiškas). Jei reikia įpraiškos – skliaustelius rašykite tik gerai viską apgalvoję arba naudokitės išplėstine sintakse.

Nežinau kaip viskas veiktų kitose kalbose. Esmė turbūt liktų ta pati (Ar PHP palaiko (?:...) ?)

Prisiminiau Ruby

Tai kaip sakiau, pasileidau serveryje mod_ruby. Na, galvoju
reikia prisiminti apie ką tas pats Rubinas yra ;)
Taigi išsitraukiau senus savo paties verstus manualus ir programėles,
kurias galima rasti čia ir
pasileidau testinį
skriptuką
. Jo kodą galima rasti čia.

Smagi visgi kalba rubinas. Dar šiek tiek skaitinėjau apie
Smalltalk. Atrodo viena objektinio programavimo pradininkių, bet
skirta daugiausia vaikams (nu kaip Logo beveik, arba man tik toks
įspūdis susidarė). Tačiau smalltalk irgi turi gerų idėjų. Ten viskas
objektas, netgi if yra objektas ;)

Išleista Mozilla 1.4 RC1

Šiandien išleistas Mozilla 1.4 RC1,
taigi Mozilla 1.4 jau išlipo iš beta stadijos. Pagrindinis
pagerinimas yra galimybė naudotis MS Proksiais (tai labai svarbu
didelėse korporacijose, kur iki šiol dėl MS proksių reikdavo naudoti
tik IE). Aišku kaip visada krūva kitų nedidelių pagerinimų.

Tiesa, kažkodėl visa 1.4 serija man neveikia ant WinXP namie :/
Reikės pažiūrėt, gal jau čia pataisė (nors jaučiu kad problema pas
mane su Windowsais)

Pagaliau tvarka su webserveriu

Lyg atkasiau kodėl Apache naudojo seną perl versiją –
pasirodo mod_perl buvo instaliuotas per apt-get ir ten su juo
sunkoka susitvarkyt kartais buvo (pasirodo kompiliuotų paketų sistema
ne visada geras dalykas). Žodžiu išėmiau paketus, sukompiliavau viską
per sourcus. Viskas veikia šauniai ir turėtų bent jau teoriškai
greičiau veikt, nes bent jau kodas dabar optimizuotas i686 o ne
i386.

Prie viso šito dar susidėjau ir mod_ruby. Nežinau ar jį kur
panaudosiu, bet tai vis lieka mano planuose ;)

Išleistas PHP4.3.2

Šiandieną išleistas PHP4.3.2. Kadangi php.lt iki antradienio negyvas, tai galvoju
bent savo webloge apie tai parašysiu ;)

Faktiškai 4.3.2 yra pilnas bugfixų ir kitokių dalykų (atrodo
radikaliai niekas nepasikeitė, tokių dalykų kaip
register_globals pokytis lyg išvengta). Šioje
versijoje pataisyta keletas buferio perpildymo klaidų, perdarytas
Apache2.0 SAPI modulis, atsisakyta palaikyti GD1.x.x (nuo šiol tik GD
2.x.x) Windowsuose, parašytas man puslapis PHP CLI ir daug
kitokių visokių vabaliukų išgaudymų. Parsisiųsti galite iš čia, Changelogą rasite čia. Turbūt verta
upsigradint vien dėl tų buferių perpildymų klaidų.

Hmmm… nors aš vis dar su 4.2.3 sėdžiu… Kažkaip stabiliau atrodo.
Na, kai jau išeis 4.3.3, tai ir aš turbūt pasikeisiu ;)

Perlmonks: Ar visada geriausia drėbti tiesą į akis?

Perlmonks kaip dažnai būna, turi
puikią
diskusiją
apie tai ar kompiuteristai turėtų visada drėbti tiesą į
akis (na, stiliumi „kvaily, viską ką čia parašei yra
nesamonė“
arba „ negi sunku eit ir pasiskaityt tą
manualą“
). Diskusijoj nuspręsta, kad kompiuterastai sunkiai
moka bendrauti su žmonėmis. Atrodo kad labai sunku rasti žmogų, kuris
mokėtų puikiai analitiškai mąstyti, o kartu ir mokėti gerai bendrauti
su žmonėmis, o kompiuteristui pasirodo reikia abiejų šių savybių. Dar
man patiko šita citata:

Hitting a backspace key or delete key is a simple thing
while applied to computer but not in social context all the
time

Kompiuteriuose lengva paspaust DELETE jei kas blogai, su žmonėm
sudėtingiau ;)

Naujo Perlo galimybės koduočių klausimu

Kaip minėjau, susidėjau naują (na, netokį jau ir naują.. apie metų
senumo) Perlą 5.8.0. Didžiausias jo pasiekimas yra tas kad viskas
viduje daroma Unikodu ir žymiai lengviau dirbti su koduotėmis. Man
ypač patiko galimybė nurodyti bylos ar IO stream’o
koduotę ir tuo padaryti automagišką koduočių keitimą:

# Nurodom, kad duomenys ateina iso-8859-13 koduote
binmode STDIN, ":encoding(iso-8859-13)";
# Ir kad spausdint juos reikia pakeitus į utf-8
binmode STDOUT, ":encoding(utf-8)";

Na, tokios „automagiškos“ bylų konvertavimo galimybės
turbūt egzistavo jau senokai kitose kalbose (spėju, kad Javoj,
Pythone, Rubine…), bet man pačiam jomis neteko naudotis.

Vienintelis dalykas, su kuriuo nesusitvarkiau kol kas –
libperl.so perkompiliavimas. Atrodo perl versija yra 5.8.0, o libperl
vis dar 5.6.1, tad Apache ir mod_perl naudoja seną versiją (ir dėl to
neveikia perkodavimas). Reikės RTFM’intis ;)