[PHP] Fastcgi mogelijkheden? (na bekijken Ruby On Rails)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik zit de laatste dagen te stoeien met Ruby On Rails, en zie daar een heel aantal dingen die me erg bevallen.
Een ervan is de FastCGI koppeling, waardoor het gros van alle scripts in een applicatie slechts bij het starten van een nieuw FastCGI proces gebeurt (interessant qua performance).

Nu vraag ik me af wat de mogelijkheden zijn om zoiets m.b.v. PHP te maken.

De FastCGI wrapper van Ror is als volgt:
Ruby:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/local/bin/ruby

def dispatcher_error(path,e,msg="")
  error_message =
    "[#{Time.now}] Dispatcher failed to catch: #{e} (#{e.class})\n  #{e.backtrace.join("\n  ")}\n#{msg}"
  Logger.new(path).fatal(error_message)
rescue Object => log_error
  STDERR << "Couldn't write to #{path} (#{e} [#{e.class}])\n" << error_message
end

begin
  require File.dirname(__FILE__) + "/../config/environment"
  require 'dispatcher'
  require 'fcgi'

  log_file_path = "#{RAILS_ROOT}/log/fastcgi.crash.log"

  FCGI.each_cgi do |cgi| 
    begin
      Dispatcher.dispatch(cgi)
    rescue Object => rails_error
      dispatcher_error(log_file_path, rails_error)
    end
  end
rescue Object => fcgi_error
  dispatcher_error(log_file_path, fcgi_error, "FCGI process #{$$} killed by this error\n")
end

Wat ik hier zie is dat Ruby geintegreerde FCGI support heeft, wat PHP volgens mij niet heeft (afgezien van de mogelijkheid om php via fcgi te draaien, kun je vanuit php niet met fcgi 'praten').

Ik neem echter aan dat deze extensie in Ruby simpelweg binnenkomende verbindingen accepteert, of iets in die trant (zal morgen de docs van FCGI eens bekijken).

Zou het mogelijk zijn om een PHP wrapper te schrijven? iets als volgt (php gecompileerd voor commandline gebruik)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/pad/naar/php

// Load application logic
require_once( 'main_application_file.php' );

try {
  while( $conn = accept_incoming_connection() )
  {
     Application::handle( $conn );
  }
}
catch( Exception $e )
{
  // Handle FCGI disconnect
}


Ik weet dat PHP door velen geroemd wordt door het 'run-by-request' principe, en ben er ook niet op uit om ServletContainer achtige zaken te creeeren. Wel vind ik de ruby oplossing interessant, omdat het met name in applicaties waar veel support classes zijn, die voor iedere request geladen worden, alle benodigde zaken reeds geladen zijn.

Om het wat concreter te maken:
Stel het gaat om een applicatie met 100 classes (incl. BL, DAL, Models, enz).
Het lijkt me dat een oplossing als hierboven sneller zal zijn dan welk caching mechanisme dan ook, omdat het sowieso al 100 calls richting het filesystem scheelt, zelfs al staan de files in de cache van de kernel.
Om hier echter een zinvolle uitspraak over te doen ken ik echter niet genoeg ins & outs van de optimizers & caches voor php, en de exacte manier waarop de APXS koppeling werkt.

Aangezien ik niet weet of er uberhaupt een ZendEncoder + Optimizer of MMcache achtige oplossing voor Ruby is, kan het zijn dat de FCGI wrapper eigenlijk een vergelijkbare oplossing is, en mijn idee dus overbodig is.

Graag jullie ideeen/meningen.

-- Edit:
Even gezocht, want ik meende dat ik ergens een generator gezien had om gemakkelijk vanuit c/c++ code een php extensie te genereren.
M.b.w. SWIG kan ik vermoedelijk vrij gemakkelijk vanuit de FastCGI sources een php extensie creeeren.

[ Voor 8% gewijzigd door B-Man op 27-06-2005 02:51 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Nog geen reacties zie ik.
Ik heb zelf vandaag gespeeld met de Zend engine, om eens te zien hoe makkelijk ik een extensie kan maken, en het gaat een stuk makkelijker dan ik verwachtte.

Overigens erg interessant, ik heb een eigen C++ CSV parser nu in een extensie verwerkt, wat een factor 4 tot 10 sneller is, voor resp. een regex-based php oplossing en een char-by-char based php oplossing.
String manipulatie in php is dus gewoon traag.
Dat de regex oplossing sneller is vond ik al vreemd, maar zit het dus vermoedelijk in het feit dat de regex engine ook een extensie is (PCRE).

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
B-Man schreef op dinsdag 28 juni 2005 @ 04:31:
Overigens erg interessant, ik heb een eigen C++ CSV parser nu in een extensie verwerkt, wat een factor 4 tot 10 sneller is, voor resp. een regex-based php oplossing en een char-by-char based php oplossing.
fgetcsv()
String manipulatie in php is dus gewoon traag.
Dat de regex oplossing sneller is vond ik al vreemd, maar zit het dus vermoedelijk in het feit dat de regex engine ook een extensie is (PCRE).
String manupilatie in php is niet echt traag hoor, maar char-by-char csv gaan parsen zal inderdaad niet het snelste zijn. PCRE is overigens inderdaad erg snel, maar je zal in dit forum diverse benchmark-topics kunnen vinden waar blijkt dat string-manupilatie tamelijk snel is.
B-Man schreef op maandag 27 juni 2005 @ 02:00:
Wat ik hier zie is dat Ruby geintegreerde FCGI support heeft, wat PHP volgens mij niet heeft (afgezien van de mogelijkheid om php via fcgi te draaien, kun je vanuit php niet met fcgi 'praten').
Voor fastcgi zou je hier eens de commentaren moeten lezen:
http://nl2.php.net/manual/en/install.unix.commandline.php

Ik heb er echter zelf nooit wat mee gedaan.

Ik neem echter aan dat deze extensie in Ruby simpelweg binnenkomende verbindingen accepteert, of
Om het wat concreter te maken:
Stel het gaat om een applicatie met 100 classes (incl. BL, DAL, Models, enz).
Het lijkt me dat een oplossing als hierboven sneller zal zijn dan welk caching mechanisme dan ook, omdat het sowieso al 100 calls richting het filesystem scheelt, zelfs al staan de files in de cache van de kernel.
Om hier echter een zinvolle uitspraak over te doen ken ik echter niet genoeg ins & outs van de optimizers & caches voor php, en de exacte manier waarop de APXS koppeling werkt.

Aangezien ik niet weet of er uberhaupt een ZendEncoder + Optimizer of MMcache achtige oplossing voor Ruby is, kan het zijn dat de FCGI wrapper eigenlijk een vergelijkbare oplossing is, en mijn idee dus overbodig is.
Ik zou hiervoor toch de eAccelerator-extensie (opvolger mmcache) gebruiken. Fastcgi is voor zover ik weet vooral ook bedoeld om niet bij elke request opnieuw de applicatie in te moeten laden, php zit natuurlijk meestal al geintegreerd in het webserverproces.

offtopic:
Tussen 2:00u en 4:31u is de kans groot dat je hier geen antwoord krijgt trouwens ;)

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Woei, een reactie :D

fgetcsv() is aardig snel ja, maar mijn eigen parser is nog 20% sneller. Ik verwerk in een aantal apps gewoon erg grote CSV bestanden, en dan is 20% toch welkom.
En natuurlijk was het een mooie kans om eens te kijken naar de extensiemogelijkheden van PHP5.
Ter illustratie:
code:
1
2
3
4
regex   parser: 73 rows in 1.108930 seconds
new     parser: 73 rows in 5.899053 seconds (char-by-char in php zelf)
ext     parser: 73 rows in 0.209466 seconds (eigen C++ extensie)
fgetcsv parser: 73 rows in 0.250906 seconds

(... waarin het 73 records betreft, verspreid over 14.000 regels. Tevens doet 'new' exact hetzelfde als 'ext', maar dan geschreven in PHP).
String manupilatie in php is niet echt traag hoor, maar char-by-char csv gaan parsen zal inderdaad niet het snelste zijn. PCRE is overigens inderdaad erg snel, maar je zal in dit forum diverse benchmark-topics kunnen vinden waar blijkt dat string-manupilatie tamelijk snel is.
Mja, met dingen zoals dit kan het niet snel genoeg zijn. Char-by-char zal wel traag zijn vanwege een hoop overhead van de Zend engine.
Voor fastcgi zou je hier eens de commentaren moeten lezen:
http://nl2.php.net/manual/en/install.unix.commandline.php

Ik heb er echter zelf nooit wat mee gedaan.

Ik neem echter aan dat deze extensie in Ruby simpelweg binnenkomende verbindingen accepteert, of
De ruby extensie accepteert inderdaad binnenkomende FastCGI verbindingen, en fungeert dus eigenlijk als een soort mini-appserver.
De php pagina's heb ik al uitgebreid bekeken, maar die zijn niet erg nuttig voor mijn vraag. Waar ik het namelijk over heb is de 'context' voor iedere FastCGI request opnieuw opzetten, maar niet de engine 'herstarten'.
De FastCGI implementatie die standaard in PHP zit, behandelt iedere nieuwe request namelijk net zoals de mod_php extensie het doet. Ik wil juist de engine laten draaien, en het script dan in staat stellen om gemakkelijk binnenkomende requests af te handelen.
Als het script blijft draaien, heb je immers een situatie waarin je niet voor iedere request je 'framework' compleet hoeft te laden(/parsen).
FastCGI biedt hier een mooie interface voor aan, zodat ik niet in PHP zelf met sockets enzo hoef te gaan neuzelen.
Het moet dus zo zijn dat de extensie bij een aanroep naar (bijvoorbeeld) fastcgi_accept() variabelen zoals $_GET, $_POST, en zaken als je session opnieuw initialiseert.
Ik zou hiervoor toch de eAccelerator-extensie (opvolger mmcache) gebruiken. Fastcgi is voor zover ik weet vooral ook bedoeld om niet bij elke request opnieuw de applicatie in te moeten laden, php zit natuurlijk meestal al geintegreerd in het webserverproces.
Het ging me niet zozeer om een specifiek product, maar meer om het probleem wat ze oplossen. Heb hier gewoon dat pakket van Zend liggen, 'Zend cache' ofzo? In ieder geval de tool van Zend zelf die het parsen kan cachen.
offtopic:
Tussen 2:00u en 4:31u is de kans groot
dat je hier geen antwoord krijgt trouwens ;)
Heb je wel gezien dat er een dag tussenzat? ;) Het is s'nachts ten minste lekker rustig, kan ik geconcentreerd werken, geen telefoon/mailtjes enz. Sowieso leuk dat het me gelukt is in een paar uur een werkende extensie voor PHP te bouwen.