Cosa blocca Ruby, Python per ottenere la velocità Javascript V8? [chiuso]


261

Esistono funzionalità di Ruby / Python che bloccano l'implementazione delle ottimizzazioni (ad esempio la cache inline ) del motore V8?

Python è sviluppato congiuntamente da ragazzi di Google, quindi non dovrebbe essere bloccato da brevetti software.

O questa è piuttosto una questione di risorse messe nel progetto V8 da Google.


6
L'introspezione e il sovraccarico dell'operatore sono probabilmente grandi, ma non conosco JS abbastanza bene da darti una risposta reale. Il progetto PyPy è probabilmente la migliore possibilità di Python di raggiungere velocità di tipo JS.
ncoghlan,

11
Hai qualche esempio in cui PyPy è più lento di V8, ad eccezione dello sparatutto in linguaggio informatico che è bollock completo (basta guardare come le cose sono implementate diversamente in diverse lingue lì). O è solo il campo di distorsione della realtà di Google?
fijal

3
V8 non è abbastanza alla pari con Python. Attendere fino a quando V8 deve implementare le specifiche Javascript 1.8 per effettuare un confronto migliore. E a quel punto sono sicuro che qualcuno tenterà di implementare PyPy sul motore V8 al posto di Javascript.
Michael Dillon,

14
Perché sei così sicuro che V8 sia più veloce di Python o Ruby? A cosa?
jcoffland,

6
V8 è assolutamente più veloce di Python / Ruby. Esegui qualsiasi tipo di benchmark che desideri, dal semplice microbenchmark a un'applicazione completa del mondo reale scritta in modo idiomatico in entrambi gli ambienti. È un ordine di grandezza più veloce per la maggior parte delle operazioni native della lingua (ad es. Cose che non vengono delegate al codice C in Python).
Hejazzman,

Risposte:


519

Cosa blocca Ruby, Python per ottenere la velocità Javascript V8?

Niente.

Bene, ok: soldi. (E tempo, persone, risorse, ma se hai soldi, puoi comprarli.)

V8 ha un team di ingegneri brillanti, altamente specializzati, di grande esperienza (e quindi molto pagati) che ci lavorano, che hanno decenni di esperienza (sto parlando individualmente - collettivamente è più come secoli) nella creazione di esecuzione ad alte prestazioni motori per linguaggi OO dinamici. Fondamentalmente sono le stesse persone che hanno anche creato Sun HotSpot JVM (tra molti altri).

Lars Bak, lo sviluppatore principale, ha lavorato letteralmente sulle macchine virtuali per 25 anni (e tutte quelle macchine virtuali hanno portato al V8), che è fondamentalmente la sua intera vita (professionale). Alcune persone che scrivono macchine virtuali Ruby non hanno nemmeno 25 anni.

Esistono funzioni di Ruby / Python che stanno bloccando l'implementazione delle ottimizzazioni (ad es. Cache inline) del motore V8?

Dato che almeno IronRuby, JRuby, MagLev, MacRuby e Rubinius hanno una cache in linea monomorfa (IronRuby) o polimorfica, la risposta è ovviamente no.

Le implementazioni di Ruby moderne fanno già moltissime ottimizzazioni. Ad esempio, per alcune operazioni, la Hashclasse di Rubinius è più veloce di quella di YARV. Ora, questo non sembra terribilmente eccitante fino a quando non ti rendi conto che la Hashclasse di Rubinius è implementata in Ruby puro al 100%, mentre quella di YARV è implementata in C. ottimizzata al 100% a mano

Quindi, almeno in alcuni casi, Rubinius può generare un codice migliore di GCC!

O questa è piuttosto una questione di risorse messe nel progetto V8 da Google.

Sì. Non solo Google. La discendenza del codice sorgente di V8 ha ormai 25 anni. Le persone che stanno lavorando su V8 ​​hanno anche creato la Self VM (fino ad oggi uno dei motori di esecuzione del linguaggio OO più veloci e dinamici mai creati), la Animorphic Smalltalk VM (fino ad oggi uno dei motori di esecuzione Smalltalk più veloci mai creati), l'HotSpot JVM (la JVM più veloce mai creata, probabilmente il periodo VM più veloce) e OOVM (una delle VM Smalltalk più efficienti mai create).

In effetti, Lars Bak, lo sviluppatore principale di V8, ha lavorato su ognuno di questi, oltre a pochi altri.


1
Possiamo avere qualche letteratura di riferimento su "Dato che almeno IronRuby, JRuby, MagLev, MacRuby e Rubinius hanno una cache in linea monomorfa (IronRuby) o polimorfica, la risposta è ovviamente no." per favore?
WDR,

14
SpiderMonkey ha prestazioni comparabili, quindi, come ha fatto Mozilla allora? Hanno soldi molto limitati ...
Salman von Abbas il

8
@SalmanPK: non è la loro prima macchina virtuale e ci sono anche persone intelligenti che lavorano su Mozilla.
Matthieu M.

3
@SalmanPK, miguel: Mozilla ha creato la sua JS VM almeno in parte con il reverse engineering V8. blog.mozilla.org/dmandelin/2010/09/08/presenting-jagermonkey
Ian

2
@Ian V8 è open source (licenza BSD), quindi non c'è bisogno di decodificare, guarda cosa stanno facendo.
dbkk,

78

C'è molto più slancio nell'ottimizzare fortemente gli interpreti JavaScript, motivo per cui vediamo così tante risorse che vengono inserite tra Mozilla, Google e Microsoft. JavaScript deve essere scaricato, analizzato, compilato ed eseguito in tempo reale mentre un essere umano (di solito impaziente) lo sta aspettando, deve funzionare MENTRE una persona sta interagendo con esso e lo fa in un client non controllato ambiente che potrebbe essere un computer, un telefono o un tostapane. DEVE essere efficiente per funzionare efficacemente in queste condizioni.

Python e Ruby vengono eseguiti in un ambiente controllato dallo sviluppatore / deployer. Un server o un sistema desktop robusto in genere in cui il fattore limitante saranno cose come la memoria o l'I / O del disco e non i tempi di esecuzione. O dove è possibile utilizzare ottimizzazioni non del motore come la memorizzazione nella cache. Per queste lingue probabilmente ha più senso concentrarsi sulla lingua e sulle funzioni della libreria impostate sull'ottimizzazione della velocità.

Il vantaggio secondario di questo è che abbiamo due grandi motori JavaScript open source ad alte prestazioni che possono e vengono ri-propositi per ogni tipo di applicazione come Node.js.


43

Una buona parte ha a che fare con la comunità. Python e Ruby per la maggior parte non hanno alcun supporto aziendale. Nessuno viene pagato per lavorare su Python e Ruby a tempo pieno (e soprattutto non viene pagato per lavorare su CPython o MRI per tutto il tempo). V8, d'altra parte, è supportato dalla più potente azienda IT del mondo.

Inoltre, V8 può essere più veloce perché l'unica cosa che conta per le persone V8 è l'interprete: non hanno una libreria standard su cui lavorare, nessuna preoccupazione sulla progettazione del linguaggio. Scrivono solo l'interprete. Questo è tutto.

Non ha nulla a che fare con la legge sulla proprietà intellettuale. Né Python è co-sviluppato da ragazzi di Google (il suo creatore lavora lì insieme ad alcuni altri committer, ma non vengono pagati per lavorare su Python).

Un altro ostacolo alla velocità di Python è Python 3. La sua adozione sembra essere la principale preoccupazione degli sviluppatori linguistici, al punto che hanno congelato lo sviluppo di nuove funzionalità linguistiche fino a quando altre implementazioni non raggiungono.

Per quanto riguarda i dettagli tecnici, non so molto su Ruby, ma Python ha una serie di luoghi in cui è possibile utilizzare le ottimizzazioni (e Unladen Swallow, un progetto di Google, ha iniziato a implementarli prima di mordere la polvere). Ecco alcune delle ottimizzazioni che hanno pianificato . Potrei vedere Python guadagnare velocità V8 in futuro se un JIT alla PyPy verrà implementato per CPython, ma ciò non sembra probabile per i prossimi anni (il focus in questo momento è l'adozione di Python 3, non un JIT).

Molti ritengono inoltre che Ruby e Python possano trarre enormi vantaggi dalla rimozione dei rispettivi blocchi dell'interprete globale .

Devi anche capire che Python e Ruby sono entrambi linguaggi molto più pesanti di JS: forniscono molto di più in termini di libreria standard, caratteristiche del linguaggio e struttura. Il solo sistema di orientamento agli oggetti aggiunge molto peso (in senso positivo, credo). Penso quasi a Javascript come un linguaggio progettato per essere incorporato, come Lua (e per molti versi sono simili). Ruby e Python hanno un set di funzionalità molto più ricco e che l'espressività di solito arriverà a scapito della velocità.


3
In realtà la moratoria sulle nuove funzionalità è stata revocata dalla recente versione di Python 3.2.
jd.

2
+1, ma un congelamento delle funzionalità delle nuove lingue non significherebbe più tempo da dedicare all'ottimizzazione?
Andrew Grimm,

1
@Andrew se solo. L'attenzione si concentra su come velocizzare Jython, IronPython e PyPy, in attesa che le biblioteche si convertano in Python 3 e che evangelizzino Python 3.
Rafe Kettler

2
"Il solo sistema di orientamento agli oggetti aggiunge molto peso" - Le moderne macchine virtuali JavaScript come V8 hanno classi, sono solo implicite. Proprio come in Python non è necessario digitare esplicitamente una variabile in JavaScript, non è necessario digitare esplicitamente una classe. La VM è abbastanza intelligente da esaminare il codice ed estrarre le classi.
Benjamin Gruenbaum,

1
A quanto ho capito, V8 è un compilatore JIT piuttosto che un interprete ... Sono abbastanza sicuro che ci sia una distinzione tra i due. Forse no ... Non lo so.
Luca

24

Le prestazioni non sembrano essere al centro dei principali sviluppatori Python, che sembrano ritenere che "abbastanza veloce" sia abbastanza buono e che le funzionalità che aiutano i programmatori a essere più produttivi siano più importanti delle funzionalità che aiutano i computer a eseguire il codice più velocemente.

In effetti, tuttavia, esisteva un progetto Google (ora abbandonato), unladen-swallow , per produrre un interprete Python più veloce compatibile con l'interprete standard. PyPy è un altro progetto che intende produrre un Python più veloce. C'è anche Psyco , il precursore di PyPy, che può fornire miglioramenti delle prestazioni a molti script Python senza cambiare l'intero interprete, e Cython , che consente di scrivere librerie C ad alte prestazioni per Python usando qualcosa di molto simile alla sintassi di Python.


13

Domanda fuorviante. V8 è un'implementazione JIT (un compilatore just in time) di JavaScript e nella sua più popolare implementazione non browser Node.js è costruita attorno a un loop di eventi. CPython non è un JIT e non è un evento. Ma questi esistono in Python più comunemente nel progetto PyPy: un JIT compatibile con CPython 2.7 (e che presto sarà 3.0+). E ci sono un sacco di librerie di server con eventi come Tornado per esempio. Esistono test del mondo reale tra PyPy che esegue Tornado vs Node.js e le differenze di prestazioni sono lievi.


3
+1 per menzionare Tornado . Mentre va a una velocità comparabile a Node.js, il suo gen.enginemodulo insieme ai generatori Python e la yielddichiarazione ( dal 2.5 !!! possono ridefinire la tua codifica asincrona.
Lukas Bünger,

1
Dal tuo post, pypy ha rilasciato una versione supportata 3.x stabile (e continua a migliorare il supporto, ovviamente): morepypy.blogspot.fr/2014/06/pypy3-231-fulcrum.html
Zeograd

9

Ho appena incontrato questa domanda e c'è anche una grande ragione tecnica per la differenza di prestazioni che non è stata menzionata. Python ha un vasto ecosistema di potenti estensioni software, ma la maggior parte di queste estensioni sono scritte in C o altri linguaggi di basso livello per prestazioni e sono fortemente legate all'API CPython.

Esistono molte tecniche ben note (JIT, garbage collector moderno, ecc.) Che potrebbero essere utilizzate per accelerare l'implementazione di CPython ma tutte richiederebbero modifiche sostanziali all'API, interrompendo la maggior parte delle estensioni del processo. CPython sarebbe più veloce, ma molto di ciò che rende Python così attraente (l'ampio stack di software) andrebbe perso. Ad esempio, ci sono diverse implementazioni Python più veloci là fuori ma hanno poca trazione rispetto a CPython.


9

Credo che a causa delle diverse priorità di progettazione e degli obiettivi del caso d'uso.

In generale, lo scopo principale dello scripting (ovvero delle lingue dinamiche) è quello di essere una "colla" tra chiamate di funzioni native. E queste funzioni native devono a) coprire le aree più critiche / utilizzate di frequente eb) essere il più efficaci possibile.

Ecco un esempio: ordinamento jQuery che causa il blocco di iOS Safari Il blocco è causato da un uso eccessivo delle chiamate get-by-selector. Se get-by-selector verrebbe implementato nel codice nativo ed effettivamente non ci sarà affatto questo problema.

Considera la demo di ray-tracer che viene utilizzata di frequente per la dimostrazione di V8. Nel mondo Python può essere implementato in codice nativo poiché Python fornisce tutte le funzionalità per le estensioni native. Ma nel realm V8 (sandbox lato client) non hai altre opzioni piuttosto che rendere la VM il più [sub] efficace possibile. E quindi l'unica opzione per vedere l'implementazione di ray-tracer è usando il codice dello script.

Quindi priorità e motivazioni diverse.

In Sciter ho fatto un test implementando il core jQurey praticamente completo in modo nativo. Su compiti pratici come ScIDE (IDE fatto di HTML / CSS / Script) credo che tale soluzione funzioni significativamente meglio di qualsiasi ottimizzazione di VM.


5

Come altri hanno già detto, Python ha un compilatore JIT performante sotto forma di PyPy .

Fare benchmark significativi è sempre sottile, ma mi capita di avere un semplice benchmark di K-medie scritto in diverse lingue - puoi trovarlo qui . Uno dei vincoli era che i vari linguaggi dovevano implementare tutti lo stesso algoritmo e cercare di essere semplici e idiomatici (al contrario di ottimizzati per la velocità). Ho scritto tutte le implementazioni, quindi so di non aver imbrogliato, anche se non posso affermare per tutte le lingue che ciò che ho scritto è idiomatico (ho solo una conoscenza passante di alcune di quelle).

Non pretendo alcuna conclusione definitiva, ma PyPy è stata tra le implementazioni più veloci che ho ottenuto, molto meglio di Node. CPython, invece, era alla fine più lenta della classifica.


5

L'affermazione non è esattamente vera

Proprio come V8 è solo un'implementazione per JS, CPython è solo un'implementazione per Python. Pypy ha prestazioni corrispondenti ai V8 .

Inoltre, c'è il problema delle prestazioni percepite: poiché V8 è nativamente non bloccante, lo sviluppo Web porta a progetti più performanti perché si salva l'attesa IO. E V8 viene utilizzato principalmente per Web dev dove l'IO è la chiave, quindi lo confrontano con progetti simili. Ma puoi usare Python in molte, molte altre aree oltre al web dev. E puoi anche usare le estensioni C per molte attività, come calcoli scientifici o crittografia e dati crunch con perf fulmini.

Ma sul web, i progetti Python e Ruby più popolari stanno bloccando. Python, in particolare, ha l'eredità dello standard sincrono WSGI, e framework come il famoso Django si basano su di esso.

Puoi scrivere Python asincrono (come con Twisted, Tornado, gevent o asyncio) o Ruby. Ma non è fatto spesso. Gli strumenti migliori stanno ancora bloccando.

Tuttavia, sono alcuni dei motivi per cui le implementazioni predefinite in Ruby e Python non sono così veloci come V8.

Esperienza

Come ha sottolineato Jörg W Mittag, i ragazzi che lavorano su V8 ​​sono geni della VM. Python è sviluppato da un gruppo di persone appassionate, molto bravo in molti domini, ma non è specializzato nell'ottimizzazione delle VM.

risorse

La fondazione Python Software ha pochissimi soldi: meno di 40.000 in un anno per investire in Python. Questo è un po 'folle quando pensi che grandi giocatori come Google, Facebook o Apple stiano tutti usando Python, ma è la brutta verità: la maggior parte del lavoro viene svolto gratuitamente. Il linguaggio che alimenta Youtube ed esisteva prima di Java è stato realizzato artigianalmente da volontari.

Sono volontari intelligenti e dedicati, ma quando si identificano hanno bisogno di più succo in un campo, non possono chiedere 300k per assumere uno specialista di prim'ordine per questa area di competenza. Devono cercare qualcuno che lo farebbe gratuitamente.

Mentre funziona, significa che devi essere molto attento alle tue priorità. Quindi, ora dobbiamo guardare:

obiettivi

Anche con le ultime funzionalità moderne, scrivere Javascript è terribile. Hai problemi di scoping, pochissime raccolte, terribili manipolazioni di stringhe e array, quasi nessuna lista std a parte data, matematica e regex e niente zucchero sintattico anche per operazioni molto comuni.

Ma in V8, hai velocità.

Questo perché, la velocità era l'obiettivo principale di Google, dal momento che è un collo di bottiglia per il rendering delle pagine in Chrome.

In Python, l'usabilità è l'obiettivo principale. Perché non è quasi mai il collo di bottiglia del progetto. La scarsa risorsa qui è il tempo degli sviluppatori. È ottimizzato per lo sviluppatore.


1

Perché le implementazioni JavaScript non devono preoccuparsi della retrocompatibilità dei loro binding.

Fino a poco tempo fa, i soli utenti delle implementazioni JavaScript erano i browser web. A causa dei requisiti di sicurezza, solo i fornitori di browser Web hanno avuto il privilegio di estendere la funzionalità scrivendo i collegamenti ai tempi di esecuzione. Pertanto, non era necessario mantenere compatibile con l'API C dei binding, era consentito richiedere agli sviluppatori del browser Web di aggiornare il loro codice sorgente con l'evoluzione dei runtime JavaScript; stavano comunque lavorando insieme. Anche V8, che era un ritardatario del gioco, e guidato anche da uno sviluppatore molto esperto, ha cambiato l'API man mano che migliorava.

OTOH Ruby viene utilizzato (principalmente) sul lato server. Molte estensioni ruby ​​popolari sono scritte come collegamenti C (considera un driver RDBMS). In altre parole, Ruby non sarebbe mai riuscito senza mantenere la compatibilità.

Oggi, la differenza esiste ancora in una certa misura. Gli sviluppatori che usano node.js si lamentano del fatto che è difficile mantenere le loro estensioni native retrocompatibili, poiché V8 cambia l'API nel tempo (e questo è uno dei motivi per cui è stato biforcato node.js). Il rubino IIRC sta ancora adottando un approccio molto più conservatore in questo senso.


1

V8 è veloce grazie a JIT, albero a gomiti, inferenziatore di tipo e codice ottimizzato per i dati. Puntatori con tag, tag NaN dei doppi. E ovviamente esegue le normali ottimizzazioni del compilatore nel mezzo.

I semplici motori ruby, python e perl non fanno nessuno di questi, solo piccole ottimizzazioni di base.

L'unica vm importante che si avvicina è luajit, che non fa nemmeno l'inferenza del tipo, la piegatura costante, la codifica NaN né i numeri interi, ma usa strutture di codice e dati simili simili, non grasse come le lingue cattive. E i miei prototipi di linguaggi dinamici, pozione e p2 hanno caratteristiche simili a luajit e superano la v8. Con un sistema di tipi opzionale, "digitazione graduale", potresti facilmente superare la v8, in quanto puoi bypassare l'albero motore. Vedi il dardo.

I noti backend ottimizzati, come pypy o jruby, soffrono ancora di varie tecniche di ingegneria eccessiva.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.