Reklāma:

Pieraksts

Pētīju vienu Zend Framework prezentāciju, un pabrīnījos par vienu notācijas metodi:

$username = new Zend_Form_Element_Text('username');
$username->addFilters(array('StringTrim', 'StringToLower'))
         ->addValidators(array(
             'Alnum',
             array('StringLength', false, array(3, 20))
         ))
         ->setRequired(true)
         ->setLabel('Username');

Sākumā iedomājos, ka šis nav korekts pieraksts, bet gan domāts, lai vizuāli atvieglotu koda uztveri. Piefiksēju to, ka rindiņām beigā snav semikolu un aizdomājos. Tīri teorētiski tā ir elementāri realizēta čeinošana. Mazliet pabakstījos un, izrādās, tas ir elementāri izdarāms. Tas nav, protams, visu objektu visām metodēm, bet tur, kur šāds pieraksts atvieglo darbu, tas ir ieviests.

Tie linuksisti takš domā ar visu ķermeni…

Principā jautājums ir vienkāršs – vai var izdarīt tā, ka kopējot failus ar cp, tiek rādīts progress tāpat, kā tas tiek rādīts, lietojot wget? Principā – ar (ne)standarta metodēm parastajam bezprogresa kopētājam tiek izveidots kopēšanas progresa attēlojums… Can you get cp to give a progress bar like wget?.

Ak jā. Komentāros ir konstruktīvas idejas, kā pasākumu paātrināt un uzlabot :)

Mūžu dzīvo, mūžu mācies

Sauciet mani par losi un ņuņņu, bet es tik tiešām nezināju šo košo MySQL iespēju. Ņemsim par piemēru parastu lapošanu. Mums nepieciešams noskaidrot kopējo ierakstu skaitu un iegūt pēc tam attiecīgo daļu (lapu). Agrāk es rīkojos visvisādi. Lielākoties – divi identiski pieprasījumi. Bet, kā šodien noskaidroju, ir vienkāršāka metode.

SELECT SQL_CALC_FOUND_ROWS 
    lauks, 
    lauks2 
FROM 
    tabula 
ORDER BY 
    lauks 
LIMIT 
    10, 10;

Un uzreizi pēc šī pieprasījuma, izveicam elementāru funkcijas izsaukumu:

SELECT FOUND_ROWS();

Un mēs iegūstam nevis atlasīto ierakstu skaitu (kas ir 10), bet gan visu atbilstošo ierakstu skaitu, kuru mēs iegūtu, ja nebūtu LIMIT daļas. MySQL Information Functions.

The Wide Finder Project

Nemaz ne tik nepopulārais tēls Tim Bray nolēma paeksperimentēt. Domu gājiens vienkāršs – mums nāk jauni procesori, kur viss tiek orientēts uz paralelitāti, nevis takts frekvencēm. Bet, paņemsim par piemēru pašu triviālāko – Apache logfailu (žurnālu) apstrādi un analizēšanu. Varbūt varam kaut ko mainīt?

Viņš ķērās klāt pie specifiskās programmēšanas valodas sistēmas Erlang, kura ir veidota, lai darbu veiktu paralēli uz vairākām sistēmām, kuras būtu savstarpēji aizvietojamas, nepārtraucot aplikācijas darbu. Interesanti, ka valoda faktiski jau varētu tikt uzskatīta par mirušu, ja vien pēc divdesmit gadiem (šogad, ja būsim precīzāki:) tā netiktu atdzīvināta. Pamatā pateicoties iepriekšminētajām izmaiņām procesoru kaujā. Un programmētājiem radās vajadzība pēc iespējas pašiem paralelizēt savus procesus.

Tad, nu, lūk. Viņš nolēma to izdarīt. Un tālāk jau lasiet pie viņa nepārspējami detalizētu stāstu (jā, tas ir programmētājiem un citiem interesentiem domāts garš un aizraujošs stāsts par Apache žurnālu failu parsēšanu:). Starp citu, izrādās ka tas nu kļūst par masveida aizraušanos. Via.

P.S. Kad sāku lasīt, ar tirpām atcerējos to, kā pēc beisika un paskāla ķēros pie fokāla (jā, bija valoda ar tādu košu nosaukumu:) apguves. Vrummm…

Apgreidu spēks

Man ir divi serveri. Viens no tiem 3.6GHz, bet otrs 2.8GHz. Abi ar vienādu atmiņas daudzumu. Abi Xeoni.

Apgreida nolūkos uz lēnākā (kurš darbojas kā failover kaste) nolēmu migrēt no konfigurācijas Apache 1.3 + PHP 4 + MySQL 4 uz Lighttpd + PHP 5 + MySQL 5. Lielas cerības uz ātrdarbības pieaugumu neliku. Bet.

Testu gaitā nodublēju produkcijas datubāzi, sakonfigurēju Lighty. Un paprovēju komplicētākos testus, kādi man ir pieejami. Faktiski tās ir lapas, kuras rāda diezgan milzīgas tabulas, kuras ir atskaites par dienā notikušo.

Atgādināšu, ka apgreids notika uz lēnākās kastes. Tagad “lēnākā” kaste šo komplicēto lapu ver vaļā vidēji 0.05 sekundēs. Kamēr “jaudīgā” ar veco konfigurāciju to dara 1.28 sekundes. Tie ir vidējie skaitļi no 100 testiem ar intervālu 1 min katrs. Lai pasākums būtu maksimāli pietuvināts reālajai dzīvei, pirms veikt testus, palaidu produkcijas procesus testa režīmā, lai būtu puslīdz līdzvērtīga noslodze.

Lielākā problēma bija nomigrēt visus mod_rewrite nosacījumus. Un mazliet paņēmos arīdzan, kamēr SSL sertifikātus piekonfigurēju. Bet citādi viss notika aizdomīgi eleganti un vienkārši…

Visticamākais ka jau pēc atvaļinājuma tiks pabeigta pilnīga testēšana un pasākums tiks palaists produkcijā. Redzēsim, kāds būs reālais ieguvums. Pagaidām izskatās daudzsološi.

ZCE. The becoming.

Kamēr atkārtoju vielu, gatavojoties Zend PHP5 Certification eksāmenam, apgūstu diezgan daudz jaunas lietas. Lai jūs varētu parādīt ar pirkstu uz mani un pasmieties no sērijas es to jau sen zināju, doh!, padalīšos.

Starp citu, vai tiešām mūsu valstiņā nav neviena Zend sertificēta PHP zinātāja?

Par mainīgo mainīgajiem. Izrādās, ka var ekstrapolēt un turpināt mainīgo mainīgo tēmu, veidojot gan nelasāmas adresācijas, gan absurdus mainīgo nosaukumus.

$a = 'b';
$b = 'c';
$c = 'glāžšķūnis';
${'glāžšķūnis'} = 1979;
 
echo $$$a;

Par kontrolstruktūrām. Nezināju, ka break un continue var pievienot parametru un nepieciešams uzmanīties no semikola absences.

Funkcijas iekš PHP vienmēr atgriež vērtību. Pat, ja netiek norādīts, ka kaut kas ir jāatgriež (arī pie return bez parametra), tiek atgriezts NULL.

Atšķirībā no PHP4, iekš PHP5 arī tiem parametriem, kuri tiek padoti kā references, var norādīt noklusēto vērtību.

Ar masīvu kejiem arī ir jautrības.

$arr = Array('1' => 1979);
echo $arr[1]; // Izvadīs 1979
echo $arr['01']; // Uzģenerēs notice līmeņa brīdinājum 

isset(). Arī nav viennozīmīgi.

$a = false;
echo isset($a); // Būs true 
$a = NULL;
echo isset($a); // Būs false
$arr[0=>NULL];
echo isset($arr[0]); // Būs false
echo array_key_exists(0, $arr); // Būs true 

Pie kam, isset() var norādīt vairāk nekā vienu parametru :) Līdz ar ko, šie abi būs identiski:

(isset($a) && isset($b)) === isset($a, $b);

Man jaunums – funkcijas strspn() un strcspn().

Starp citu, arī tiem, kurus neinteresē iespēja kārtot Zend sertifikācijas eksāmenu, derētu tomēr palasīties grāmatu Zend PHP 5 Certification Study Guide (ir pieejama arī PDF formātā, kas nozīmē, ka gan jau ir atrodama arī resursos). Arī tiem, kas uzskata, ka visu zin. Iesācējiem, tiesa, tas neko daudz nedos. Kaut arī…

Ja nu būs arī turpmākajā procesā kas man līdz šim nezināms, rakstīšu turpinājumu.

Shell skriptu rakstīšanas padomi

Build intelligent, unattended scripts. Man noderēja. Tā pa riktīgam noderēja. Labāk, nekā lasīt jau citu rakstītus skriptus un mēģināt izkost t.s. best practices.

Youtube mērogojamība (?)

Interesanti pieraksti par kādu Youtube scalability prezentāciju, kura tika sniegta Google Tech Talks ietvaros. Video versiju var noskatīties teitan. Pārējos GTT video, kā jau ierasts, var meklēt šai lapā.

Terminālis

Kā gadījies, kā ne, bet mums uz vienu terminālo serveri (windows serveris) slēdzas klāt lietotāji ar dažādiem reģionālajiem settingiem. Serveris pie sevis uzliek tos pašus reģionālos iestatījumus, kādi ir lietotājam. Taču, mums tomēr būtu nepieciešams, lai tie ir latviski, jo pretējā gadījumā aplikācija nerāda korekti latviešu burtus. Vienu reizi (pagājušogad septembrī) to jau biju izdarījis. Un šodien, kad nākas to pašu veikt uz servera aizvietotāja aplauzos, jo neatcerējos…

Šo pierakstu pavisam konkrēti sev, lai neaizmirstu atkal. Biezpienu jau esmu pasūtījis.

Ņemam šo arhīvu – setlocale.zip. Tajā ir divi faili. Readme.txt satur informāciju par lokāļu kodiem, bet izpildāmais fails ir tas, ar kuru tās var uzstādīt.

Maģiskā komandrinda, kura, atkarībā no apstākļiem un vajadzībām, ir liekama vai nu Startupā vai lietotāju/grupu/mašīnu logon skriptos, ir sekojoša: setlocale.exe 00000426.

Bļambas, uz ko tas attiecas (lai vēlāk pats varētu sameklēt; tādi kā pseidoatslēgvārdi): reģionālie iestatījumi, regional settings, locale, setlocale, nah.

P.S. Tas gan neatrisina problēmu, ja lietotājs diskonektējas no sesijas un pēc tam atkal piekonektējas, jo tai brīdī startup/logon skripti netiek palaisti un TS lokāli uzstāda uz to, kura ir lietotājam.

DB abstrakcijas leijeri

Veicu testus ar dažiem datubāžu abstrakcijas leijeriem. Testa būtība bija vienkārša – pieslēdzamies DB (mysql šai gadījumā), atlasām 10 ierakstus, ciklā tos nolasām, atslēdzamies no DB. Ar katru draiveri/klasi to veicu 10 identiskus testus ar 5 minūtes ilgu pauzi starp katru no tiem. Katrā testā šīs darbības norādītajā secībā tika atkārtotas 1000 reizes.

PEAR DB
Lai arī morāli novecojis, šo izmantoju ieraduma pēc. Testēju gan mysql gan mysqli draiverus.
PEAR MDB2
Rekomendētākais DB abstrakcijas veids.
PDO_mysql
Runā, ka iekš PHP 5.1 PDO būs iekšā. PHP dabistiskais DB abstrakcijas veids.
ADOdb
Lielās ar to, ka ir pats ātrākais datubāžu abstrakcijas leijeris. Diemžēl, nepiedāvā iespēju izmantot tik ļoti ierasto objektu notāciju, operējot ar rezultātu laukiem.
mysql_* un mysqli_*
Jautrībai paņēmu un palaidu šo visu arīdzan ar iebūvētajām mysql/mysqli funkcijām.

Testos izpalika Zend freimworka datubāžu adapteri (PDO_mysql un mysqli), jo tie nestrādāja (pie atslēgšanās no DB PHP mira ar segfaultiem, bet pie pieslēgšanās jamais lamājās par nespēju piekļūt protected īpašībām).

Šiem testiem ir tikai teorētiska un tīri karmiska nozīme. Mili un mikrosekundēs mērāmā starpība ir absolūti nenozīmīga WEB aplikācijām. Tiem, kam ātrums ir svarīgs, attiecīgās vietas jau nu nebūs iekš PHP. Un galu galā – lētāk ir iegādāties vēl vienu serveri, nekā cīnīties par nieka sekundes daļām, lai beigu beigās jebkurā gadījumā nāktos iegādāties vēl vienu serveri. Labi, nu jau 80% no servera.

Protams, ka lēnākais ir arī vecākais – PEAR DB (izmantojot mysql draiveri). Amizanti, bet faktiski tik pat ātrs (3% lēnāks) ir MDB2. 10% ieguvuma, salīdzinot ar PEAR DB mysql, iegūsti, izmantojot to pašu PEAR DB, tikai ar mysqli. Bet tie, kam ir PHP5, var priecāties par PDO_mysql, jo viņiem tas strādās vidēji par 23% ātrāk, nekā PEAR DB mysql.

Papildināts ar ADOdb. Ātrdarbība tāda pati, kā PDO mysql un mysqli (konkrētajā gadījumā – par 2% ātrāks par pirmo un par 1% lēnāks, nekā otrais). Ne sūda. Nokļūdījos. Ātrdarbība ir par 10% labāka, nekā tā ir PEAR DB mysql. Faktiski tāda pati, kā PEAR DB mysqli.

Ā. Nuja. PHP 5.2.3 (laists caur CLI, ne apaci), DB uz citas kastes. Gan klienta, gan servera versija ir 5.0.26.

Tabuliņa ar mērījumiem (katra testa izpildes laiks sekundēs):

PEAR DB mysql PEAR DB mysqli PEAR MDB2 PDO mysql ADOdb mysql mysqli
10,60 9,68 10,43 8,80 9,05 9,47 8,36
10,97 10,24 10,83 8,24 8,94 9,10 8,02
10,25 9,28 9,91 7,72 9,07 7,87 7,11
9,22 8,38 9,35 7,62 9,23 7,79 7,28
9,68 8,73 9,76 7,66 9,17 8,61 7,68
10,71 9,99 10,48 7,96 8,99 8,64 7,64
10,03 9,49 9,37 8,34 10,15 8,98 7,34
11,36 9,512 10,77 7,97 9,53 8,47 7,70
11,33 9,52 10,64 8,40 9,63 9,53 7,99
10,23 8,94 10,12 7,58 9,95 8,61 7,94
Vidējā (aritmētiskā) vērtība
10,44 9,38 10,17 8,03 9,37 8,71 7,71
% no maksimālā izpildes laika
100% 90% 97% 77% 90% 83% 74%
% no minimālā izpildes laika (ja tā vienkāršāk saprast)
135% 122% 132% 104% 122% 113% 100%

Testēšanas skriptelis.

IP adreses

Sākotnēji šķita, ka tas ir bugs. #php.lv IRC kanālā andrisp bija apjucis, tad es apjuku. Līdz mazliet padomāju (atcerējos ko līdzīgu , kāstojot stringu par intu).

echo long2ip(ip2long('10.0.0.011')); // Būs 10.0.0.9 

Bet tad paprovēju ar parasto pingu.

$ ping 10.0.0.011
PING 10.0.0.011 (10.0.0.9) 56(84) bytes of data.

Nolēmu iet tālāk.

$ ping 10.0.0.0xa
PING 10.0.0.0xa (10.0.0.10) 56(84) bytes of data.

HA! Ik dienas kas jauns…

Apostrofs revisited

Uzveidoju atsevišķu lapeli Apostrofam. Galvenā izmaiņa – ir pieejama 64bit versija. Lūgtum, notestēt to uz Windows XP 64bit un sniegt atskaiti pie attiecīgā Apostrofa sākumieraksta. Šeit komentāri būs slēgti (lai tie visi krājas vienuviet).

Beidzot saņēmos (Wall4PHP)

Slinkums nav brālis. Bet nu tomēr – saņēmos un sapakoju tekošo produkcijas versiju, pielaboju dažus rindā stāvošus bugus un ekušeku – Wall4PHP 1.1 klāt. Tagad lielākā galvas lauzīšana ir par to, vai pakļauties lietotāju vēlmēm un atiet no striktās “nekādu fiņķikļušku”, vai arī tomēr palikt pie parastā vienkāršā Wall.

MySQL un UTF8

Superfeini. Tagad, viens un tas pats atradīsies, meklējot glāžšķūņ, GLĀŽŠĶŪŅ, glazskun, vai GlĀžŠķŪņ (jā, tā dikti daudzi dara!). Beidzot izauga rokas pārstumt WordPress tabulas no latin1 uz utf8.

А технологии, а технологии, а технологии, как люди!

Ja lauks ir TEXT, TINYTEXT, vai tml, tad pārtaisam to par BLOB:
ALTER TABLE `table` MODIFY `column` BLOB.

Ja tas ir VARCHAR, CHAR, vai kas tml, tad taisām to par BINARY:
ALTER TABLE `table` MODIFY `column` BINARY(column-length).

Un galu galā, konvertējam uz utf8:
ALTER TABLE `table` MODIFY `column` VARCHAR(254) CHARACTER SET utf8.

Iepriekšminētā caurdibenība ir nepieciešama, lai mysql nepazaudētu oriģinālo saturu, kas ir cellēs, to konvertējot starp dažādiem enkodingiem. Jo MySQLprāt tur nebūt nav UTF-8, bet gan Latin-1, kā rezultātā, taisot pa tiešo kolonnas par UTF-8, mēs rezultātā iegūtu to, ko viņš redz tai cellē kā Latin-1 kodējumā. Sava veida dubulto UTF-8 :)

Ja nu kādu variable izmēru lauku (VARCHAR, piem) tomēr netīšām nokonvertējām uz BLOB, tad tam galā tiek pielipināti nullveidīgi baitiņi (0×00) līdz maksimālajam iespējamajam lauka izmēram. Tam mēs uzrakstām vienkāršu vaicājumu: UPDATE `table` SET `column` = REPLACE(`column`, x'00', ''), kas aizvāks visus liekumus.

Ja pasākums neaprobežojās ar vienu vai divām tabulām un desmit laukiem, tad, iespējams, ir vērts uzrakstīt mazu skriptiņu (pitonā, pēhāpē, perlā, javā, – kur un sirds kāro), kas visu iepriekšaprakstīto veic pats. Pirmām kārtām gana laba izklaide, otrām kārtām – nav tik apnicīgi, kā veikt visu iepriekšminēto manuāli.

Vēl varētu parekomendēt rezerves kopijas. Nopietni. Ja jūs šādi kaut ko sačakarēsiet, atpakaļceļš būs ellīgi sāpīgs (ja vispār iespējams). Pietiek jau uztaisīt identisku tabulu apstrādājamajai (SHOW CREATE TABLE `table`), uztaisīt tabulu bak_table, un to aizpildīt: INSERT INTO `bak_table` (SELECT * FROM `table`).

Paldies par uzmanību.

INSERT DELAYED

Šodien, pateicoties tam, ka viens no XML-RPC servisiem sāka mums gāzt nenormālu kaudzi pieprasījumu (kaut ko līdzīgu piegādes atskaitēm), webserveris līka ciet. Gan jau ka kāds pamanīja.

Sāku ar bēdāšanos un nervozu pīpēšanu. Man tas palīdz ģenerēt idejas – pīpēšana, vai jebkura cita darbība, kura nav saistīta ar piedomāšanu. Tas vēl nav viss. Šīs darbības laikā es galvā imitēju sarunu par šo problēmu. Vai arī provēju vienkārši pa punktiem izklāstīt problēmu, iedomājoties, ka to daru cilvēkam, kurš ir mazāk kvalificēts (nav IT zinātājs). Palīdz.

Bet ne par to stāsts, kā viegli nojaust pēc ieraksta nosaukuma. Tad, lūk. Manā galā apstrādes skripts ievieto saņemto atskaiti tabulā. Šobrīd attiecīgā MySQL tabula satur 12 398 374 ierakstus. Sakarā ar to, ka no šī lēruma informācijas ir nepieciešamas šādas tādas atskaites, lai procesu vienkāršotu, tabulai tika izveidoti lērums ar indeksiem. Tai laikā ierakstu skaits bija daždesmit tūkstoši. Arī pie dažiem miljoniem viss strādāja un slikti nevienam nebija.

Un tad nāca vakardiena. Nekādi nespēju saprast, aiz kam web serveris liecas ciet. Ja līdz šim noslodze bija minimāla, tad tagad momentāni tiek paķerti visi apache procesi, tiek izveidotas milzums konekcijas uz DB serveri un nekas nenotiek.

Izrādās, ka beidzot MySQLs ir sapratis, ka nu ir grūti atjaunot indeksus tādam milzumam datu. Un uz katru INSERT patērēja gana lielu laika sprīdi. Ja līdz šim tā pussekunde nebija pamanāms lielums, tad tagad šī aizkavēšanās maksāja pastarpināto serveru resursus. DB serveris sevišķi nespringa, bet webserveris gan. Sen nebiju redzējis noslodzes vidējās vērtības aizejam otrajā simtā…

Tā kā situācija prasīja momentānu risinājumu, sāku cīņu. Provēju ar trafika ierobežošanu (mod_bandwidth, piemēram). Nekas labs no tā neiznāca. Tad vienkārši nogriezu (izņemot no atļautajiem hostiem attiecīgo IP), līdz izdomāšu, kā problēmu risināt (otrā galā pieprasījumi tā vai tā krājas rindā).

Un tad nāca apskaidrība. Atminējos par INSERT DELAYED. Tas bija tieši tas, kas man nepieciešams. Sakarā ar to, ka DB serveris nekādas satraukuma pazīmes neizrādīja, bet WEB serveris nespēja celt tādu vienlaicīgu un relatīvi ilgstošu savienojumu skaitu, šis ir ideāls risinājums.

INSERT DELAYED dara vienkāršu lietu – visus ar šo komandu izsauktos insertus krāj rindā un, atkarībā no konfigurācijas, ik pa laikam sastumj datubāzē. Labums – komandas izsaucējam nav jāgaida, kamēr reāli tā izpildīsies (tas ir labi tikai tai gadījumā, kad nav nepieciešamas nekādas post factum pārbaudes). Bet lielākais ieguvums – ātrdarbība. Tiek izveidots atsevišķs process, kurš nodarbojas ar to, ka pako, gaida un izpilda šos pieprasījumus. Process tos ievieto pa paciņām, t.i. – sakrājot konkrētu skaitu, ievieto tos datubāzē vienā rāvienā, kas ir stipri ātrāk, nekā, ja to dara pa vienam un nodažādām konekcijām. Kā arī, ja tabula tiek biežo lokota, tad ievietojošajam klientam nav jāgaida, līdz loks atbrīvosies.

P.S. Atgādiniet man kaut kad uzrakstīt par LIKE versus INSTR, INSERT INTO table SET ..., CONVERT ļaunumu, NULL superļaunumu, kā arī citiem sīkumiem.

« Senāki ieraksti Jaunāki ieraksti »