RSS

Krótka historia o buforowaniu

Liczba odsłon: 146

Jedna z pod­sta­wo­wych za­sad opty­ma­li­zo­wa­nia opro­gra­mo­wa­nia mó­wi, że bez zmia­ny algo­ryt­mu, zmia­ny w szyb­koś­ci dzia­ła­nia mo­gą być uzys­ka­ne je­dy­nie przez prze­no­sze­nie ob­cią­że­nia po­mię­dzy pa­mię­cią a pro­ce­so­rem. Albo wy­ni­ki ob­li­cza się za każ­dym ra­zem od no­wa, osią­ga­jąc nis­kie wy­ko­rzys­ta­nie pa­mię­ci, al­bo za­pi­su­je się raz ob­li­czo­ne wy­ni­ki w pa­mię­ci, osią­ga­jąc nis­kie ob­cią­że­nie pro­ce­so­ra. Obydwa po­dej­ścia ma­ją dłu­go­ter­mi­no­wy – po­zy­tyw­ny i ne­ga­tyw­ny – wpływ na wy­daj­ność opty­ma­li­zo­wa­ne­go pro­gra­mu, a tak­że ca­łe­go opro­gra­mo­wa­nia dzia­ła­ją­ce­go na kom­pu­te­rze.

W ana­li­zo­wa­niu sta­tys­tyk od­wie­dzin ser­wi­su WWW wspo­ma­ga mnie tab­li­ca kon­trol­na za­wie­ra­ją­ca adre­sy, naz­wy i iden­ty­fi­ka­to­ry prze­glą­dar­ki stu kom­pu­te­rów klienc­kich, któ­re ostat­nio łą­czy­ły się z moim ser­we­rem. Adresy i iden­ty­fi­ka­to­ry po­bie­ra­ne są z ba­zy da­nych, lecz naz­wy ho­stów za każ­dym ra­zem są roz­wią­zy­wa­ne za po­mo­cą me­cha­niz­mu DNS.

Mechanizm bu­fo­ro­wa­nia od­po­wie­dzi DNS za­zwy­czaj bez prob­le­mu ra­dził so­bie z ta­kim ob­cią­że­niem i ge­ne­ro­wa­nie ta­be­li nie zaj­mo­wa­ło zbyt du­żo cza­su. Gorzej by­ło, gdy mię­dzy ko­lej­ny­mi od­świe­że­nia­mi stro­ny upły­nę­ło spo­ro cza­su i bu­for od­po­wie­dzi DNS ser­we­ra uległ opróż­nie­niu, lub je­że­li ja­kiś host nie miał przy­pi­sa­ne­go od­wrot­ne­go wpi­su DNS. W ta­kich sytu­acjach do­cho­dzi­ło do ab­sur­dal­nej sytu­acji: zopty­ma­li­zo­wa­ne za­py­ta­nie SQL zwra­ca­ło kom­plet wy­ni­ków w cią­gu 0.5 s, a ge­ne­ro­wa­nie ta­be­li zaj­mo­wa­ło na­wet 20 s.

W pew­nym mo­men­cie za­czę­ło mnie to iry­to­wać. Ponie­waż jed­nak apli­kac­je PHP są bez­sta­no­we, włas­ne trwa­łe bu­fo­ro­wa­nie nazw ho­stów mog­łem zreali­zo­wać al­bo lo­kal­nie, za po­mo­cą ses­ji, al­bo glo­bal­nie, w pli­ku dy­sko­wym. Sesje od po­cząt­ku od­rzu­ci­łem, by nie uza­leż­niać cza­su ge­ne­ro­wa­nia od te­go, z ja­kie­go kom­pu­te­ra i ja­kiej prze­glą­dar­ki otwie­ram ra­port. Pozosta­ło za­tem roz­wią­za­nie ba­zu­ją­ce na pli­ku dy­sko­wym.

Zgodnie z za­sa­da­mi ite­ra­cyj­ne­go roz­wo­ju opro­gra­mo­wa­nia, naj­pierw stwo­rzy­łem kla­sę wpro­wa­dza­ją­cą za­her­me­ty­zo­wa­ną abs­trak­cję pro­ce­su tłu­ma­cze­nia adre­su IP na naz­wę ho­sta (rea­li­zo­wa­ne­go funk­cją get­host­by­name() PHP). Generator ta­be­li zmo­dy­fi­ko­wa­łem tak, by za­miast uru­cha­miać funk­cję bez­po­śred­nio, ko­rzy­stał z tej ab­strak­cji i spraw­dzi­łem, że je­go dzia­ła­nie z punk­tu użyt­kow­ni­ka nie uleg­ło zmia­nie.

Następ­nie wpro­wa­dzi­łem moż­li­wość bu­fo­ro­wa­nia rea­li­zo­wa­nych za­py­tań. Podczas two­rze­nia obiek­tu tłu­ma­cza, ostat­nie sto wier­szy pli­ku jest wczy­ty­wa­nych do tab­li­cy asoc­ja­cyj­nej adresnaz­wa ho­sta. Każde tłu­ma­cze­nie jest naj­pierw rea­li­zo­wa­ne z wy­ko­rzys­ta­niem tej tab­li­cy. Jeżeli od­po­wied­nie­go wpi­su jesz­cze w niej nie ma, tłu­ma­cze­nie jest rea­li­zo­wa­ne po sta­re­mu (z uży­ciem get­host­by­name()), a wy­nik jest umiesz­cza­ny w tab­li­cy oraz do­pi­sy­wa­ny na koń­cu pli­ku.

Rozwiąza­nie nie jest mo­że skraj­nie ele­ganc­kie i wy­daj­ne, jed­nak jest sku­tecz­ne. Czas ge­ne­ro­wa­nia ta­be­li wy­ni­ków, po­przed­nio częs­to prze­kra­cza­ją­cy kil­ka se­kund, w więk­szoś­ci przy­pad­ków uległ skró­ce­niu do po­je­dyn­czych mili­se­kund. Cały pro­ces wy­świet­la­nia stro­ny zaj­mu­je te­raz mniej niż se­kun­dę. Jest to szcze­gól­nie od­czu­wal­ne przy częs­tym od­świe­ża­niu stro­ny lub ko­rzy­sta­niu z inter­fej­su do blo­ko­wa­nia wy­bra­nych adre­sów.