De meesten van jullie kennen natuurlijk de pricewatch wel en vast ook wel de winkelmandjes-functionaliteit daarvan.
Die is onlangs aangepast om een wat betere zoektocht naar de goedkoopste shops te hebben, namelijk door alle producten die een shop niet levert als een nieuw winkelmandje te beschouwen en een nieuwe zoektocht te doen. En dat levert dus een leuke recursie op.
Meestal niet zo'n probleem, want de functie wordt sowieso maar vrij weinig aangeroepen, dus als ie wat slomer is... ach boeie.
Maar als er een wat langere lijst (een complete pc bijv) van populaire producten wordt uitgekozen, dan loopt het al heel snel tegen de execution time limits van php aan. Ik heb overigens niet de indruk dat het feit dat het in php draait erg veel uitmaakt voor de complexiteit en dus de functionaliteit in de basis, maar goed. Een configuratie uit de best buy guide van 15 producten (met in totaal 399 prijs-vermeldingen van 80 shops) loopt bijvoorbeeld al tegen de time limit aan en duurt op een verder onbelaste P4 2.8Ghz ruim 40 seconden.
Daarbij is er al een optimalisatie om reeds uitgerekende deelcombinaties te cachen en die te hergebruiken, als dat niet gebeurt gaat het voorbij de 120 seconden. Verder worden al die prijzen in één keer opgehaald (paar ms) om te voorkomen dat er een paar honderd tot duizend queries uitgevoerd worden vanwege de recursie.
Het beperken van de diepte (aantal verschillende shops waarbij een bestelling mag plaatsvinden) heeft doordat de caching minder effectief/moeilijker wordt een averechts effect. Tenzij ik dat verkeerd doe natuurlijk
In de basis is het algoritme nu zoiets (pseudo code):
Dit is overigens een nogal abstracte versie, o.a. de functies zijn niet per se een functie maar gewoon code die zo het makkelijkst samen te vatten is. Met bovenstaand getallenvoorbeeld wordt de 'zoekGoedkoopsteShops'-functie zo'n 300k x aangeroepen, en de 'zoekGoedkoopsteShopsVoorProducten'-functie zo'n 3k keer. Dus de cache heeft wel effect.
De vraag is natuurlijk:
Hoe kan het beter? Met name een reductie in het aantal recursies die ik over het hoofd zie is welkom, of uiteraard een handiger zoekalgortime. Dat is niet echt mijn sterkste punt.
Een andere optimalisatie die ik bedacht had was het limiteren van de resultaatset van 'zoekShopsVoorProducten' na de eerste stap om zo grootte van de "deelmandjes" wat te verkleinen. Alleen zal dat natuurlijk de kwaliteit van de zoektocht wat verminderen (je kan bijv alleen de shops nemen met prijzen onder de mediaan)
Die is onlangs aangepast om een wat betere zoektocht naar de goedkoopste shops te hebben, namelijk door alle producten die een shop niet levert als een nieuw winkelmandje te beschouwen en een nieuwe zoektocht te doen. En dat levert dus een leuke recursie op.
Meestal niet zo'n probleem, want de functie wordt sowieso maar vrij weinig aangeroepen, dus als ie wat slomer is... ach boeie.
Maar als er een wat langere lijst (een complete pc bijv) van populaire producten wordt uitgekozen, dan loopt het al heel snel tegen de execution time limits van php aan. Ik heb overigens niet de indruk dat het feit dat het in php draait erg veel uitmaakt voor de complexiteit en dus de functionaliteit in de basis, maar goed. Een configuratie uit de best buy guide van 15 producten (met in totaal 399 prijs-vermeldingen van 80 shops) loopt bijvoorbeeld al tegen de time limit aan en duurt op een verder onbelaste P4 2.8Ghz ruim 40 seconden.
Daarbij is er al een optimalisatie om reeds uitgerekende deelcombinaties te cachen en die te hergebruiken, als dat niet gebeurt gaat het voorbij de 120 seconden. Verder worden al die prijzen in één keer opgehaald (paar ms) om te voorkomen dat er een paar honderd tot duizend queries uitgevoerd worden vanwege de recursie.
Het beperken van de diepte (aantal verschillende shops waarbij een bestelling mag plaatsvinden) heeft doordat de caching minder effectief/moeilijker wordt een averechts effect. Tenzij ik dat verkeerd doe natuurlijk
In de basis is het algoritme nu zoiets (pseudo code):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| zoekGoedkoopsteShops($productIds) { if(incache) return cache; else return zoekGoedkoopsteShopsVoorProducten($productIds); } zoekGoedkoopsteShopsVoorProducten($productIds) { $shops = zoekShopsVoorProducten($productIds); foreach($shops as $shop) { $mandjeBijShop = telPrijsVoorShop($shop); if(count($mandjeBijShop['nietGeleverd']) > 0) $mandjeBijShop['overigeProducten'] = zoekGoedkoopsteShops($mandjeBijShop['nietGeleverd']); $shop['prijzen'] = $mandjeBijShop; } return sorteerEnLimiteerShops($shops); } |
Dit is overigens een nogal abstracte versie, o.a. de functies zijn niet per se een functie maar gewoon code die zo het makkelijkst samen te vatten is. Met bovenstaand getallenvoorbeeld wordt de 'zoekGoedkoopsteShops'-functie zo'n 300k x aangeroepen, en de 'zoekGoedkoopsteShopsVoorProducten'-functie zo'n 3k keer. Dus de cache heeft wel effect.
De vraag is natuurlijk:
Hoe kan het beter? Met name een reductie in het aantal recursies die ik over het hoofd zie is welkom, of uiteraard een handiger zoekalgortime. Dat is niet echt mijn sterkste punt.
Een andere optimalisatie die ik bedacht had was het limiteren van de resultaatset van 'zoekShopsVoorProducten' na de eerste stap om zo grootte van de "deelmandjes" wat te verkleinen. Alleen zal dat natuurlijk de kwaliteit van de zoektocht wat verminderen (je kan bijv alleen de shops nemen met prijzen onder de mediaan)