[Perl] CGI omzetten naar ISAPI

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Beste Tweakers,

BIG problem here! Ik heb een aantal websites draaien die ontwikkeld zijn door iemand die inmiddels vertrokken is. Het probleem is dat de site ontzettend langzaam is en de processor bij 1 request meteen naar 100% knalt. Nu hebben we een nieuwe server maar dit helpt erg weinig. Het is onmogelijk om de Perl code te herschrijven.
Nu ben ik opzoek naar alternatieve oplossingen. Ik heb gekeken naar FastCgi en Isapi, aangezien de huidige parser gewoon CGI is.

Maar ik weet echt te weinig over hoe dit allemaal in elkaar zit. Kortom, ik kan wel wat tips gebruiken.

Is het mogelijk om cgi scripts, met kleine aanpassingen door ISAPI afgehandeld te laten worden?
Of is FastCgi een betere optie?
Of heb ik gewoon pech?

Greetz West

Acties:
  • 0 Henk 'm!

  • unclero
  • Registratie: Juni 2001
  • Laatst online: 08:50

unclero

MB EQA ftw \o/

Ik zou het gewoon proberen, maar ik vrees het ergste..

Als de Perl-code dusdanig is opgebouwd dat hij alle resources in beslag neemt denk ik dat er nog eens kritisch naar de code en de bijbehorende data gekeken mag worden.

Quelle chimère est-ce donc que l'homme? Quelle nouveauté, quel monstre, quel chaos, quel sujet de contradiction, quel prodige!


Acties:
  • 0 Henk 'm!

  • LinuX-TUX
  • Registratie: December 2003
  • Laatst online: 17-09 13:27
Als je het nu per direct weer draaiend moet hebben zou ik zoeken naar een profiler en het programma eens onder de loep nemen om snel even de knelpunten eruit te vissen.

Dan kan je daarna rustig in je 'eigen tijd' verder zoeken / vertalen naar iets wat beter in elkaar steekt dan wat er nu draait.

Zoals unclero eigenlijk zegt, kijk naar de data flow wat er gedaan wordt en wat er EIGENLIJK nodig is.
Ik zie niet zoveel (goede) CGI profilers online. Als het een DBase app is zou je OOK kunnen kijken wat er op de database langskomt aan monster queries die vereenvoudigt zouden kunnen worden :Y)

[ Voor 24% gewijzigd door LinuX-TUX op 22-05-2009 11:41 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Jullie hebben gelijk, ik weet het. Maar Perl programmeurs zijn moeilijk te vinden en de code zit zo inelkaar dat er een centraal hart is waaruit alles geregeld word. Dus had stille hoop op andere afhandeling. De database is vrij uitgebreid en niet zo makkelijk te optimaliseren.

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 19:51

Creepy

Tactical Espionage Splatterer

Je zult toch echt moeten profilen waar het probleem zit. Als een CGI script 100% load oplevert dan gaat het ombouwen naar fastCGI o.i.d. je echt niet helpen.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

Verwijderd

Je kunt vrij eenvoudig meten wat de tijd is die je Perl script gebruikt en hoeveel tijd gaat zitten in queries e.d. Aangenomen dat je unix gebruikt / windows dezelfde ondersteuning voor times heeft. Zet bovenaan het script:

code:
1
my $startTime = (times)[0];


en onderaan het script:

code:
1
2
my $endTime = (times)[0];
warn "time " . ($endTime-$startTime) . " seconds\n";


Dit zet de daadwerkelijke cpu tijd die het script gebruikt als regel in de logs van je server. Tijd voor andere dingen als queries en wordt niet meegeteld.

Zie ook times functie en unix time

Met fastcgi of mod_perl (maar daar moet het script geschikt voor zijn) los je alleen het probleem van 'compileren' van het script op. Dit kan (wel degelijk) de bron van je probleem zijn. Als het script groot is en de depencies niet goed geregeld zijn kan dit best wat tijd kosten.

Mijn perl scripts knallen overigens ook naar 100% maar voor een fractie van een seconde. Met apache benchmark (commando 'ab') halen ze op mijn magere ontwikkelservertje nog steeds 20 request per seconde.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 21:01
Voor zover ik weet is ISAPI, net als CGI en FastCGI, alleen een API om communicatie tussen een webapplicatie en de webserver mogelijk te maken. Het voordeel van FastCGI (en waarschijnlijk ISAPI?) ten opzichte van CGI is dat je een enkel proces kunt hergebruiken voor meerdere (zelfs concurrente) requests. Dat levert dus alleen performancewinst op als het starten van een nieuw proces voor elke request te kostbaar is (dus als je veel requests per seconde wil uitvoeren, of als het opstarten te kostbaar is).

In jouw beschrijving lijkt het er echter op dat het afhandelen van een request zelf te lang duurt. Dan gaat het gebruiken van een andere webserver-interface je niet helpen. Je moet de applicatie zelf efficiënter zien te maken, desnoods door 'm te herschrijven. Als dat, in jouw woorden, "onmogelijk" is, is er vrij weinig wat je kunt doen, helaas.

Acties:
  • 0 Henk 'm!

Verwijderd

Had de link tussen ISAPI naar IIS en dus Windows niet gelegd. Waarschijnlijk is mijn tip om de tijd van het script te meten niet geschikt. Kan geen referenties vinden of de functie 'times' geimplementeerd is op Win32.
Soultaker schreef op zaterdag 23 mei 2009 @ 16:44:
Het voordeel van FastCGI (en waarschijnlijk ISAPI?) ten opzichte van CGI is dat je een enkel proces kunt hergebruiken voor meerdere (zelfs concurrente) requests. Dat levert dus alleen performancewinst op als het starten van een nieuw proces voor elke request te kostbaar is
Klopt helemaal. Perl is alleen een apart beestje en voert een script (als cgi) uit in vijf stappen:
  1. starten perl proces
  2. inlezen
  3. parsen
  4. 'compileren'
  5. uitvoeren
FastCGI ISAPI voert stap 1 (en waarschijnlijk 2) één keer uit en stappen 3 tot 5 meerdere keren. Je wint dus alleen de tijd die het kost om het proces te starten. Gebruik je mod_perl dan voert de server alleen stap 5 uit voor iedere request. De compileer stap voor een groot perl script kan best kostbaar zijn. Een snelheidsverbetering met een factor 20 is dan ook niet vreemd als je overstapt van cgi naar mod_perl.

Jammer genoeg voor de OP is mod_perl specifiek voor Apache.

(edit)'Starten proces toegevoegd aan lijstje en FastCGI vervangen door ISAPI(/edit)

[ Voor 5% gewijzigd door Verwijderd op 24-05-2009 16:36 ]


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 21:01
Uit interesse: wat gebeurt er precies bij compilatie dan? Voor zover ik weet is Perl een geïnterpreteerde taal, dus als je de boel geparset hebt, dan heb je in principe genoeg om 'm uit te voeren. Misschien wordt er nog ergens bytecode gegenereerd, maar dat kan nooit echt kostbaar zijn, lijkt me?

Verder: voor zover ik weet is FastCGI gewoon een module, die je laadt in je webscript. De eerste call naar een FastCGI (FastCGI::accept of iets dergelijks) komt pas als je aan het uitvoeren bent, en dan is je script dus al gecompileerd. Waarom zou het script dan opnieuw gecompileerd moeten worden?
Verwijderd schreef op zondag 24 mei 2009 @ 13:50:
De compileer stap voor een groot perl script kan best kostbaar zijn. Een snelheidsverbetering met een factor 20 is dan ook niet vreemd als je overstapt van cgi naar mod_perl. Jammer genoeg voor de OP is mod_perl specifiek voor Apache.
Maar alleen als die compileerstap de bottleneck vormt. Alleen de topic starter kan hier echt uitsluitsel over geven, maar het lijkt me nog steeds waarschijnlijk dat de executie van het script gewoon te lang duurt, en dan kun je de webserver interface wel optimaliseren, maar daarmee los je het probleem dan niet op. :)

[ Voor 14% gewijzigd door Soultaker op 24-05-2009 15:13 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Soultaker schreef op zondag 24 mei 2009 @ 13:56:
Uit interesse: wat gebeurt er precies bij compilatie dan? Voor zover ik weet is Perl een geïnterpreteerde taal, dus als je de boel geparset hebt, dan heb je in principe genoeg om 'm uit te voeren. Misschien wordt er nog ergens bytecode gegenereerd, maar dat kan nooit echt kostbaar zijn, lijkt me?
Inderdaad bytecode en initialisatie van het script. De factor 20 snelheidswinst die ik noem was voor een groot script (6k regels) Waar exact de winst zit (het starten van het proces of het compilen) durf ik je niet te zeggen. Wel kost het compileren van dit script op de command line circa 0.20 seconden terwijl compleet uitvoeren 0.30 seconden duurt (uitvoeren is in dit geval een database connectie maken en een tabelletje dumpen) Perl zelf starten kost 0.01 seconde.
Verder: voor zover ik weet is FastCGI gewoon een module, die je laadt in je webscript. De eerste call naar een FastCGI (FastCGI::accept of iets dergelijks) komt pas als je aan het uitvoeren bent, en dan is je script dus al gecompileerd. Waarom zou het script dan opnieuw gecompileerd moeten worden?
Je hebt gelijk / dank voor de correctie: FastCGI start je script maar één keer en voert een loop in het script meerdere malen uit. Heb m'n vorige bericht gecorrigeerd. Ik zat de te denken aan een techniek als ISAPI waarbij de intrepeter geladen wordt binnen de webserver waardoor je de overhead van het starten van een nieuw proces niet hebt. Heb even zitten neuzen in de FastCGI documentatie en dat doet bijna hetzelfde als mod_perl.

Daarmee valt FastCGI af als optie voor OP. Net als mod_perl zijn er (niet triviale) wijzigingen nodig in de code.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Het klopt dat ik het over 1 request heb, maar dat komt omdat we 1 website hebben overgeheveld naar een nieuwe server, zodat de server ontlast word. Het resultaat valt alleen erg tegen. De originele server heeft ongeveer 15 perl processen tegelijk openstaan. Als dit er 20 worden, is de server bijna "onbereikbaar" en moet IIS worden herstart.
Soultaker schreef op zaterdag 23 mei 2009 @ 16:44:
Voor zover ik weet is ISAPI, net als CGI en FastCGI, alleen een API om communicatie tussen een webapplicatie en de webserver mogelijk te maken. Het voordeel van FastCGI (en waarschijnlijk ISAPI?) ten opzichte van CGI is dat je een enkel proces kunt hergebruiken voor meerdere (zelfs concurrente) requests. Dat levert dus alleen performancewinst op als het starten van een nieuw proces voor elke request te kostbaar is (dus als je veel requests per seconde wil uitvoeren, of als het opstarten te kostbaar is).

In jouw beschrijving lijkt het er echter op dat het afhandelen van een request zelf te lang duurt. Dan gaat het gebruiken van een andere webserver-interface je niet helpen. Je moet de applicatie zelf efficiënter zien te maken, desnoods door 'm te herschrijven. Als dat, in jouw woorden, "onmogelijk" is, is er vrij weinig wat je kunt doen, helaas.
@willemjoosten
Ik heb toch wel even je script timer gebruikt. Kom uit op 0.328 seconds per pagina. En toch duurt het veel langer voordat de pagina getoont word in de browser. De processor heeft bij 1 gebruiker al een piek van 100% tijdens deze compilatie.

Ik heb een test site op de server gezet. Als je deze wilt bekijken kan dat door de hostfile aan te passen en johannus2.nl toe te voegen op 94.142.209.166

[ Voor 13% gewijzigd door Verwijderd op 25-05-2009 09:42 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op maandag 25 mei 2009 @ 09:23:
@willemjoosten
Ik heb toch wel even je script timer gebruikt. Kom uit op 0.328 seconds per pagina. En toch duurt het veel langer voordat de pagina getoont word in de browser. De processor heeft bij 1 gebruiker al een piek van 100% tijdens deze compilatie.
Klopt dat het (veel) langer duurt. Je meet alleen de tijd die je script daadwerkelijk iets aan het doen is. Tijd voor het starten van het proces en tijd die het script wacht op bijvoorbeeld het uitvoeren van database queries die meet je niet. Toch is 0.3 seconden lang (lees pittig of slecht geschreven script)

Als de Time::HiRes module geinstalleerd is kun je eventueel nog de totale tijd meten. Zie het voorbeeld onder 'measure elapsed time'. En voeg deze regel toe bovenaan je script.

code:
1
 use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);


Het verschil tussen de tijd die je op deze manier meet en de 0.3 seconden is de tijd die het script bezig is met externe dingen als database queries etc. Als dit ook lang is dan gaat ISAPI je dus ook niet helpen.
Ik heb een test site op de server gezet. Als je deze wilt bekijken kan dat door de hostfile aan te passen en johannus2.nl toe te voegen op 94.142.209.166
Die werkt niet, zelfs telnetten naar poort 80 op dat ip adres niet. Krijg van 94.142.209.162 een icmp response 'destination unreachable'. Firewall?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
[qoute]Die werkt niet, zelfs telnetten naar poort 80 op dat ip adres niet. Krijg van 94.142.209.162 een icmp response 'destination unreachable'. Firewall?[/qoute]

Vreemd! gebruik je wel http://94.142.209.166/ ? Deze kan je inmiddels ook zonder host file aanroepen.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op dinsdag 26 mei 2009 @ 09:32:
Vreemd! gebruik je wel http://94.142.209.166/ ? Deze kan je inmiddels ook zonder host file aanroepen.
Met of zonder hosts file hetzelfde resultaat: destination unreachable.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 26 mei 2009 @ 09:49:
[...]


Met of zonder hosts file hetzelfde resultaat: destination unreachable.
You're right! Fixed it!

Acties:
  • 0 Henk 'm!

Verwijderd

Ok dat werkt. Het generen van de pagina duurt totaal circa 3 seconden (tijd tussen versturen request en eerste pakketje, daarna is alles binnen 0.1 seconden binnen) 10% van die tijd is het script daadwerkelijk bezig. Als je nog meet met Time::HiRes dan weet je ook hoeveel tijd het script met externe dingen bezig is en hoeveel tijd het starten van het proces kost.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 26 mei 2009 @ 10:12:
Ok dat werkt. Het generen van de pagina duurt totaal circa 3 seconden (tijd tussen versturen request en eerste pakketje, daarna is alles binnen 0.1 seconden binnen) 10% van die tijd is het script daadwerkelijk bezig. Als je nog meet met Time::HiRes dan weet je ook hoeveel tijd het script met externe dingen bezig is en hoeveel tijd het starten van het proces kost.
Krijg (het staat nu nog bovenaan de pagina) [3.222527] als resultaat. Dat is niet mis :( Welke conclusie mag ik hieruit trekken? Dat perl 0,3 sec nodig heeft en 2.9 andere factoren zoals mysql?

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op dinsdag 26 mei 2009 @ 10:23:
[...]Krijg (het staat nu nog bovenaan de pagina) [3.222527] als resultaat. Dat is niet mis :( Welke conclusie mag ik hieruit trekken? Dat perl 0,3 sec nodig heeft en 2.9 andere factoren zoals mysql?
Dat is inderdaad de conclusie die je mag trekken. Onder andere factoren vallen naast de database dingen als bestanden inlezen, externe scripts of programma's aanroepen e.d.

Ter vergelijking de timing van eerder genoemd groot script: reactietijd in browser 0.50 seconden, cpu tijd 0.07 en totale tijd (de 3.2 bij jou) 0.20. Doe ik een zoekopdracht met een heftige query dan blijft de cpu tijd ongeveer gelijk maar stijgt de totale tijd naar 0.9 seconden.

Acties:
  • 0 Henk 'm!

  • LinuX-TUX
  • Registratie: December 2003
  • Laatst online: 17-09 13:27
LinuX-TUX schreef op vrijdag 22 mei 2009 @ 11:38:
...
Als het een DBase app is zou je OOK kunnen kijken wat er op de database langskomt aan monster queries die vereenvoudigt zouden kunnen worden :Y)
Ik denk toch dat je een Query Analyzer erbij moet trekken of gewoon in de CGI scripts moet kijken wat voor (achtelijke) queries er voorbij komen.

Als je lekker inefficient zit te joinen en alles meeneemt krijg je idd lange query tijden. Is helemaal zo gek nog niet en komt vaker voor dan je denkt :Y)

Soms makkelijk op te lossen door een view in het leven te roepen (bij grote getalen en complexe objecten die gelinkt zijn aan elkaar maar niet altijd nodig zijn bij elkaar) en meestal op te lossen door de initieele query te herzien en te verbeteren/optimaliseren.

Al met al, Google is the place to be :Y)
Pagina: 1