Després d'una de les meves entrevistes de feina més recents, em va sorprendre adonar-me que l'empresa a la qual vaig sol·licitar encara utilitzava Laravel, un framework PHP que vaig provar fa una dècada. Va ser decent per a l'època, però si hi ha una constant tant en tecnologia com en moda, és el canvi continu i el ressorgiment d'estils i conceptes. Si ets programador de JavaScript, probablement estàs familiaritzat amb aquesta vella broma
Programador 1: "No m'agrada aquest nou marc de JavaScript!"
Programador 2: "No cal preocupar-se. Només espereu sis mesos i n'hi haurà un altre per substituir-lo!"
Per curiositat, vaig decidir veure què passa exactament quan posem a prova vell i nou. Per descomptat, el web està ple de benchmarks i afirmacions, dels quals el més popular és probablement el Punts de referència del marc web de TechEmpower aquí . Tanmateix, avui no farem res tan complicat com ells. Mantendrem les coses agradables i senzilles ambdues perquè aquest article no es converteixi en Guerra i Pau , i que tindreu una lleugera possibilitat de romandre despert quan acabeu de llegir. S'apliquen les advertències habituals: és possible que això no funcioni igual a la vostra màquina, diferents versions de programari poden afectar el rendiment i el gat de Schrödinger es va convertir en un gat zombi que estava mig viu i mig mort al mateix temps.
Per a aquesta prova, faré servir el meu ordinador portàtil armat amb un petit i5 amb Manjaro Linux, tal com es mostra aquí.
El nostre codi tindrà tres tasques senzilles per a cada sol·licitud:
Quina mena de prova idiota és aquesta, us podeu preguntar? Bé, si mireu les sol·licituds de xarxa d'aquesta pàgina, notareu una anomenada sessionvars.js que fa exactament el mateix.
Ja veieu, les pàgines web modernes són criatures complicades i una de les tasques més habituals és la memòria cau de pàgines complexes per evitar l'excés de càrrega al servidor de bases de dades.
Si tornem a renderitzar una pàgina complexa cada vegada que un usuari la sol·licita, només podrem servir uns 600 usuaris per segon.
Però si emmagatzemem aquesta pàgina a la memòria cau com a fitxer HTML estàtic i deixem que Nginx l'enviï ràpidament per la finestra a l'usuari, podrem servir 32.000 usuaris per segon, augmentant el rendiment en un factor de 50 vegades.
L'index.en.html estàtic és la part que va a tothom, i només les parts que difereixen per usuari s'envien a sessionvars.js. Això no només redueix la càrrega de la base de dades i crea una millor experiència per als nostres usuaris, sinó que també disminueix les probabilitats quàntiques que el nostre servidor es vaporitzi espontàniament en una incompliment del nucli deformat quan els klingons ataquen.
El codi retornat per a cada marc tindrà un requisit senzill: mostrar a l'usuari quantes vegades ha actualitzat la pàgina dient "El nombre és x". Per simplificar les coses, ara ens mantindrem allunyats de les cues de Redis, els components de Kubernetes o les Lambdas d'AWS.
Les dades de sessió de cada usuari es desaran en una base de dades PostgreSQL.
I aquesta taula de base de dades es truncarà abans de cada prova.
Simple però efectiu és el lema de Pafera... fora de la línia de temps més fosca de totes maneres...
D'acord, ara per fi podem començar a embrutar-nos les mans. Ens saltarem la configuració de Laravel, ja que només és un grup de compositors i artesans. ordres.
Primer, configurarem la configuració de la nostra base de dades al fitxer .env
A continuació, establirem una única ruta alternativa que envia totes les sol·licituds al nostre controlador.
I configureu el controlador per mostrar el recompte. Laravel, per defecte, emmagatzema les sessions a la base de dades. També proporciona el session()
funció per interactuar amb les dades de la nostra sessió, de manera que només calia un parell de línies de codi per representar la nostra pàgina.
Després de configurar php-fpm i Nginx, la nostra pàgina té un aspecte força bo...
Almenys fins que vegem realment els resultats de la prova...
No, això no és una errada d'ortografia. La nostra màquina de prova ha passat de 600 sol·licituds per segon que representa una pàgina complexa... a 21 sol·licituds per segon que representa "El nombre és 1".
Aleshores, què va fallar? Hi ha alguna cosa malament amb la nostra instal·lació de PHP? Nginx s'està alentint d'alguna manera quan s'interfaça amb php-fpm?
Referem aquesta pàgina en codi PHP pur.
Ara hem utilitzat 98 línies de codi per fer el que van fer quatre línies de codi (i un munt de treballs de configuració) a Laravel. (Per descomptat, si féssim un tractament adequat d'errors i missatges dirigits a l'usuari, això seria aproximadament el doble del nombre de línies.) Potser podrem arribar a 30 sol·licituds per segon?
Va! Sembla que no hi ha res dolent amb la nostra instal·lació de PHP després de tot. La versió pura de PHP fa 700 sol·licituds per segon.
Si no hi ha res dolent amb PHP, potser hem configurat malament Laravel?
Després de buscar al web problemes de configuració i consells de rendiment, dues de les tècniques més populars van ser emmagatzemar a la memòria cau les dades de configuració i encaminar per evitar processar-les per a cada sol·licitud. Per tant, seguirem els seus consells i provarem aquests consells.
Tot es veu bé a la línia d'ordres. Anem a refer la referència.
Bé, ara hem augmentat el rendiment de 21,04 a 28,80 sol·licituds per segon, un augment espectacular de gairebé un 37%! Això seria força impressionant per a qualsevol paquet de programari... excepte pel fet que encara estem fent només 1/24 del nombre de sol·licituds de la versió pura de PHP.
Si penseu que alguna cosa ha d'anar malament amb aquesta prova, hauríeu de parlar amb l'autor del framework Lucinda PHP. En els resultats de les seves proves, ho ha fet Lucinda guanyant a Laravel 36x per a sol·licituds HTML i 90x per a sol·licituds JSON.
Després de provar a la meva pròpia màquina tant amb Apache com amb Nginx, no tinc cap motiu per dubtar-ne. Laravel és realment just això lent! PHP per si sol no és tan dolent, però una vegada que afegiu tot el processament addicional que Laravel afegeix a cada sol·licitud, em resulta molt difícil recomanar Laravel com a opció el 2023.
Comptes de PHP/Wordpress prop del 40% de tots els llocs web del web , convertint-lo amb diferència en el marc més dominant. Personalment, però, trobo que la popularitat no es tradueix necessàriament en qualitat més del que em trobo amb un impuls sobtat incontrolable per aquest extraordinari menjar gurmet de el restaurant més popular del món ... McDonald's. Com que ja hem provat codi PHP pur, no provarem Wordpress en si mateix, ja que qualsevol cosa que inclogui Wordpress seria, sens dubte, inferior a les 700 sol·licituds per segon que vam observar amb PHP pur.
Django és un altre framework popular que ha existit durant molt de temps. Si l'heu utilitzat en el passat, probablement recordeu amb afecte la seva espectacular interfície d'administració de bases de dades juntament amb el molest que era configurar-ho tot de la manera que volíeu. Vegem com funciona Django el 2023, especialment amb la nova interfície ASGI que ha afegit a partir de la versió 4.0.
Configurar Django és molt semblant a configurar Laravel, ja que tots dos eren de l'època en què les arquitectures MVC eren elegants i correctes. Ens saltarem la configuració avorrida i passarem directament a configurar la vista.
Quatre línies de codi són les mateixes que amb la versió de Laravel. Vegem com funciona.
No està gens malament amb 355 peticions per segon. Només és la meitat del rendiment de la versió de PHP pura, però també és 12 vegades superior al de la versió de Laravel. Django vs. Laravel sembla que no hi ha cap competició.
A part dels marcs més grans, inclosos els de la pica de la cuina, també hi ha marcs més petits que només fan una configuració bàsica mentre us permeten gestionar la resta. Un dels millors per utilitzar és Flask i el seu homòleg ASGI Quart. El meu Marc PaferaPy està construït a sobre de Flask, de manera que conec bé com de fàcil és fer les coses mantenint el rendiment.
Com podeu veure, l'script Flask és més curt que l'script PHP pur. Trobo que de tots els idiomes que he utilitzat, Python és probablement el llenguatge més expressiu pel que fa a les tecles escrites. La manca de claus i parèntesis, la comprensió de llistes i dictats i el bloqueig basat en sagnats en lloc de punts i coma fan que Python sigui bastant senzill però potent en les seves capacitats.
Malauradament, Python també és el llenguatge de propòsit general més lent que hi ha, malgrat la quantitat de programari que s'hi hagi escrit. El nombre de biblioteques de Python disponibles és aproximadament quatre vegades més gran que els idiomes similars i cobreix una gran quantitat de dominis, però ningú diria que Python és ràpid ni eficient fora de nínxols com NumPy.
Vegem com es compara la nostra versió de Flask amb els nostres frameworks anteriors.
El nostre script Flask és realment més ràpid que la nostra versió de PHP pura!
Si us sorprèn això, hauríeu d'adonar-vos que la nostra aplicació Flask fa tota la seva inicialització i configuració quan iniciem el servidor gunicorn, mentre que PHP torna a executar l'script cada vegada que arriba una nova sol·licitud.' equival a que Flask és el taxista jove i impacient que ja ha posat en marxa el cotxe i està esperant al costat de la carretera, mentre que PHP és el vell conductor que es queda a casa seva esperant que arribi una trucada i només després condueix. passar a recollir-te. Com que és un noi de la vella escola i venint dels dies en què PHP va ser un canvi meravellós als fitxers HTML i SHTML senzills, és una mica trist adonar-se de quant de temps ha passat, però les diferències de disseny realment fan que PHP sigui difícil. competir contra els servidors Python, Java i Node.js que només es queden a la memòria i gestionen les sol·licituds amb l'àgil facilitat d'un malabarista.
Flask pot ser el nostre marc més ràpid fins ara, però en realitat és un programari força antic. La comunitat Python va canviar als nous servidors ASGI asíncrons fa un parell d'anys i, per descomptat, jo mateix he canviat amb ells.
La versió més recent del Marc Pafera, PaferaPyAsync , es basa en Starlette. Tot i que hi ha una versió ASGI de Flask anomenada Quart, les diferències de rendiment entre Quart i Starlette van ser suficients perquè em tornés a basar el meu codi en Starlette.
La programació asíncrona pot fer por a molta gent, però en realitat no és un concepte difícil gràcies als nois de Node.js que van popularitzar el concepte fa més d'una dècada.
Solíem lluitar contra la concurrència amb multiprocés, multiprocessament, informàtica distribuïda, encadenament de promeses i tots aquells moments divertits que van envellir i dessecar prematurament molts programadors veterans. Ara, només escrivim async
davant les nostres funcions i await
davant de qualsevol codi que pugui trigar una estona a executar-se. De fet, és més detallat que el codi normal, però molt menys molest d'utilitzar que haver de fer front a les primitives de sincronització, el pas de missatges i la resolució de promeses.
El nostre fitxer Starlette té aquest aspecte:
Com podeu veure, està pràcticament copiat i enganxat del nostre script Flask amb només un parell de canvis d'encaminament i el async/await
paraules clau.
Quina millora ens pot aportar realment el codi copiar i enganxar?
Tenim un nou campió, senyores i senyors! El nostre màxim anterior va ser la nostra versió PHP pura amb 704 sol·licituds per segon, que després va ser superada per la nostra versió de Flask a 1080 sol·licituds per segon. El nostre script Starlette aixafa tots els contendents anteriors a 4562 sol·licituds per segon, la qual cosa significa una millora de 6 vegades respecte a PHP pur i una millora de 4 vegades respecte a Flask.
Si encara no heu canviat el vostre codi WSGI Python a ASGI, ara pot ser un bon moment per començar.
Fins ara, només hem cobert els frameworks PHP i Python. Tanmateix, una gran part del món utilitza Java, DotNet, Node.js, Ruby on Rails i altres tecnologies per als seus llocs web. No es tracta de cap manera d'una visió general exhaustiva de tots els ecosistemes i biomes del món, de manera que per evitar fer l'equivalent de programació de la química orgànica, triarem només els marcs que siguin més fàcils d'escriure el codi. . del qual Java definitivament no.
Tret que us hàgiu amagat sota la vostra còpia de K&R C o Knuth's L'art de la programació d'ordinadors durant els darrers quinze anys, probablement heu sentit parlar de Node.js. Aquells de nosaltres que hem existit des del començament de JavaScript estem increïblement espantats, sorpresos o tots dos davant l'estat del JavaScript modern, però no es pot negar que JavaScript també s'ha convertit en una força a tenir en compte als servidors. com a navegadors. Després de tot, fins i tot tenim nombres enters natius de 64 bits ara a l'idioma! Això és molt millor que tot el que s'emmagatzema en flotadors de 64 bits!
ExpressJS és probablement el servidor Node.js més fàcil d'utilitzar, així que farem una aplicació Node.js/ExpressJS ràpida i bruta per servir el nostre comptador.
En realitat, aquest codi era més fàcil d'escriure que les versions de Python, tot i que JavaScript natiu es fa més aviat difícil de manejar quan les aplicacions es fan més grans, i tots els intents de corregir-ho, com ara TypeScript, es tornen ràpidament més detallats que Python.
Vegem com funciona això!
És possible que hagis escoltat contes populars antics (antigues segons els estàndards d'Internet de totes maneres...) sobre Node.js' velocitat, i aquestes històries són majoritàriament certes gràcies a l'espectacular treball que ha fet Google amb el motor JavaScript V8. En aquest cas, però, tot i que la nostra aplicació ràpida supera l'script Flask, la seva naturalesa d'un sol fil és derrotada pels quatre processos asíncrons utilitzats per Starlette Knight que diu "Ni!".
Anem a rebre més ajuda!
D'acord! Ara és una batalla igualada de quatre contra quatre! Fem un punt de referència!
Encara no al nivell de Starlette, però no està malament per a un ràpid hack de JavaScript de cinc minuts. A partir de les meves pròpies proves, aquest script s'està retardant una mica a nivell d'interfície de base de dades perquè node-postgres no és tan eficient com psycopg per a Python. El canvi a sqlite com a controlador de base de dades produeix més de 3000 sol·licituds per segon per al mateix codi ExpressJS.
El més important a tenir en compte és que, malgrat la velocitat d'execució lenta de Python, els marcs ASGI poden ser competitius amb les solucions Node.js per a determinades càrregues de treball.
Així que ara, ens estem apropant al cim de la muntanya, i per muntanya, em refereixo a les puntuacions de referència més altes registrades per ratolins i homes per igual.
Si mireu la majoria dels punts de referència del marc disponibles al web, notareu que hi ha dos idiomes que solen dominar la part superior: C++ i Rust. He treballat amb C++ des dels anys 90, i fins i tot tenia el meu propi marc Win32 C++ abans que MFC/ATL fos una cosa, així que tinc molta experiència amb el llenguatge. No és gaire divertit treballar amb alguna cosa quan ja ho saps, així que farem una versió Rust. ;)
Rust és relativament nou pel que fa als llenguatges de programació, però es va convertir en un objecte de curiositat per a mi quan Linus Torvalds va anunciar que acceptaria Rust com a llenguatge de programació del nucli de Linux. Per a nosaltres, els programadors més antics, això és més o menys el mateix que dir que aquesta nova cosa hippie de la nova era seria una nova esmena a la Constitució dels Estats Units.
Ara, quan ets un programador experimentat, acostumes a no pujar al carro tan ràpid com ho fan els més joves, o en cas contrari et pots cremar pels canvis ràpids de l'idioma o de les biblioteques. (Qualsevol que utilitzi la primera versió d'AngularJS sabrà de què parlo.) Rust encara es troba una mica en aquesta fase de desenvolupament experimental, i em sembla curiós que tants exemples de codi a la web ni tan sols compilar més amb les versions actuals dels paquets.
Tanmateix, no es pot negar el rendiment que mostren les aplicacions Rust. Si no ho has provat mai ripgrep o fd-trobar a grans arbres de codi font, definitivament hauríeu de donar-los una volta. Fins i tot estan disponibles per a la majoria de distribucions de Linux simplement des del gestor de paquets. Estàs intercanviant verbositat per rendiment amb Rust... a lot de verbositat per a lot de rendiment.
El codi complet de Rust és una mica gran, així que només farem una ullada als controladors rellevants aquí:
Això és molt més complicat que les versions de Python/Node.js...
I molt més rendible!
El nostre servidor Rust que utilitza Actix/deadpool_postgres supera amb facilitat el nostre anterior campió Starlette en +125%, ExpressJS en +362% i PHP pur en +1366%. (Deixaré el delta d'actuació amb la versió de Laravel com a exercici per al lector.)
He descobert que aprendre el llenguatge Rust en si ha estat més difícil que altres idiomes, ja que té molts més problemes que qualsevol cosa que he vist fora de 6502 Assembly, però si el vostre servidor Rust pot agafar 14 vegades el nombre de usuaris com el vostre servidor PHP, llavors potser hi ha alguna cosa a guanyar amb canvis de tecnologia després de tot. És per això que la propera versió del Pafera Framework es basarà en Rust. La corba d'aprenentatge és molt superior a la dels llenguatges de script, però el rendiment valdrà la pena. Si no podeu dedicar el temps a aprendre Rust, basar la vostra pila tecnològica en Starlette o Node.js tampoc no és una mala decisió.
En els darrers vint anys, hem passat de llocs d'allotjament estàtic barats a allotjament compartit amb piles LAMP i a llogar VPS a AWS, Azure i altres serveis al núvol. Avui en dia, moltes empreses estan satisfetes amb la presa de decisions de disseny basant-se en qui trobin que estigui disponible o més barat, ja que l'arribada dels còmodes serveis al núvol han fet que sigui fàcil llançar més maquinari a servidors i aplicacions lents. Això els ha donat grans guanys a curt termini a costa del deute tècnic a llarg termini.
Fa 70 anys, hi va haver una gran carrera espacial entre la Unió Soviètica i els Estats Units. Els soviètics van guanyar la majoria de les primeres fites. Van tenir el primer satèl·lit a Sputnik, el primer gos a l'espai a Laika, la primera nau espacial lunar a Luna 2, el primer home i dona a l'espai a Yuri Gagarin i Valentina Tereshkova, etc.
Però a poc a poc van anar acumulant deute tècnic.
Tot i que els soviètics van ser els primers en cadascun d'aquests èxits, els seus processos d'enginyeria i objectius els feien centrar-se en reptes a curt termini més que en la viabilitat a llarg termini. Guanyaven cada vegada que saltaven, però anaven cada cop més cansats i més lents mentre els seus oponents continuaven fent passos constants cap a la meta.
Una vegada que Neil Armstrong va fer els seus passos històrics a la Lluna a la televisió en directe, els nord-americans van prendre el lideratge i després es van quedar allà mentre el programa soviètic va trontollar. Això no és diferent de les empreses actuals que s'han centrat en la propera gran cosa, la propera gran recompensa o la propera gran tecnologia sense desenvolupar hàbits i estratègies adequats a llarg termini.
Ser el primer al mercat no vol dir que us convertireu en el jugador dominant en aquest mercat. Alternativament, prendre el temps per fer les coses bé no garanteix l'èxit, però sens dubte augmenta les teves possibilitats d'assoliments a llarg termini. Si sou el líder tecnològic de la vostra empresa, trieu la direcció i les eines adequades per a la vostra càrrega de treball. No deixis que la popularitat substitueixi el rendiment i l'eficiència.
Voleu descarregar un fitxer 7z que contingui els scripts Rust, ExpressJS, Flask, Starlette i Pure PHP?
Sobre l'autor |
|
![]() |
Jim ha estat programant des que va recuperar un IBM PS/2 durant els anys 90. A dia d'avui, encara prefereix escriure HTML i SQL a mà, i se centra en l'eficiència i la correcció en el seu treball. |