Quali caratteristiche semantiche di Python (e di altri linguaggi dinamici) contribuiscono alla sua lentezza?
Nessuna.
Le prestazioni delle implementazioni linguistiche sono una funzione del denaro, delle risorse e delle tesi di dottorato, non delle caratteristiche linguistiche. Self è molto più dinamico di Smalltalk e leggermente più dinamico di Python, Ruby, ECMAScript o Lua e aveva una VM che superava tutte le VM Lisp e Smalltalk esistenti (in effetti, la distribuzione di Self veniva fornita con un piccolo interprete Smalltalk scritto in Self e anche quello era più veloce della maggior parte delle VM Smalltalk esistenti), ed era competitivo, e talvolta anche più veloce delle implementazioni C ++ dell'epoca.
Quindi, Sun ha smesso di finanziare Self e IBM, Microsoft, Intel e Co. hanno iniziato a finanziare C ++ e la tendenza si è invertita. Gli sviluppatori Self hanno lasciato Sun per avviare la propria azienda, dove hanno utilizzato la tecnologia sviluppata per Self VM per costruire una delle VM Smalltalk più veloci di sempre (la VM animorfa), quindi Sun ha riacquistato quella società e una versione leggermente modificata di che Smalltalk VM è ora meglio conosciuto con il nome di "HotSpot JVM". Ironia della sorte, i programmatori Java guardano dall'alto in basso i linguaggi dinamici per essere "lenti", quando in realtà Javaè stato lento fino all'adozione della tecnologia del linguaggio dinamico. (Sì, esatto: HotSpot JVM è essenzialmente una VM Smalltalk. Il verificatore bytecode esegue molti controlli del tipo, ma una volta che il bytecode è accettato dal verificatore, dalla VM e, in particolare, dall'ottimizzatore e dal JIT non lo è molto interessante con i tipi statici!)
CPython semplicemente non fa molte cose che rendono veloci i linguaggi dinamici (o piuttosto il dispacciamento dinamico): compilazione dinamica (JIT), ottimizzazione dinamica, allineamento speculativo, ottimizzazione adattiva, de-ottimizzazione dinamica, feedback / inferenza di tipo dinamico. C'è anche il problema che quasi tutta la libreria standard e core è scritta in C, il che significa che anche se rendi Python 100 volte più veloce all'improvviso, non ti aiuterà molto, perché qualcosa come il 95% del codice eseguito da un Il programma Python è C, non Python. Se tutto fosse scritto in Python, anche un moderato aumento di velocità creerebbe un effetto valanghe, in cui gli algoritmi diventano più veloci e le strutture dei dati core diventano più veloci, ma ovviamente anche le strutture dei dati core vengono utilizzate all'interno degli algoritmi e gli algoritmi core e i dati core le strutture sono utilizzate ovunque,
Ci sono un paio di cose notoriamente dannose per i linguaggi OO gestiti in memoria (dinamici o meno) nei sistemi odierni. La memoria virtuale e la protezione della memoria possono essere un killer per le prestazioni della garbage collection in particolare e per le prestazioni del sistema in generale. Ed è completamente inutile in un linguaggio sicuro per la memoria: perché proteggere dagli accessi alla memoria illegali quando non ci sono accessi alla memoria nella lingua per cominciare? Azul ha capito di usare MMU potenti e moderni (Intel Nehalem e più recenti, e l'equivalente di AMD) per aiutare la raccolta dei rifiuti invece di ostacolarli, ma anche se è supportato dalla CPU, gli attuali sottosistemi di memoria dei sistemi operativi tradizionali non sono abbastanza potenti per consentire questo (motivo per cui la JVM di Azul in realtà funziona virtualizzata sul metallo nudo oltre il sistema operativo, non al suo interno).
Nel progetto Singularity OS, Microsoft ha misurato un impatto del ~ 30% sulle prestazioni del sistema quando si utilizza la protezione MMU anziché il sistema di tipi per la separazione dei processi.
Un'altra cosa che Azul notò quando costruirono le loro CPU Java specializzate fu che le moderne CPU tradizionali si concentrano sulla cosa completamente sbagliata quando provano a ridurre il costo dei fallimenti della cache: provano a ridurre il numero di errori della cache attraverso cose come la previsione del ramo, il prefetch della memoria, e così via. Ma, in un programma OO fortemente polimorfico, i modelli di accesso sono sostanzialmente pseudo-casuali, semplicemente non c'è nulla da prevedere. Quindi, tutti questi transistor sono semplicemente sprecati e ciò che si dovrebbe fare è invece ridurre il costo di ogni singola perdita della cache. (Il costo totale è il costo #misses *, il mainstream cerca di far cadere il primo, Azul il secondo.) Gli Java Compute Accelerators di Azul potrebbero avere 20000 missioni simultanee della cache in volo e fare comunque progressi.
Quando ha iniziato Azul, che pensavano avrebbero preso alcuni componenti off-the-shelf di I / O e progettare il proprio core della CPU specializzato, ma quello che in realtà ha finito per avere bisogno di fare era l'esatto contrario: hanno preso un piuttosto standard di off-the- core RISC core a 3 indirizzi e progettato il proprio controller di memoria, MMU e sottosistema cache.
tl; dr : La "lentezza" di Python non è una proprietà del linguaggio ma a) la sua ingenua (primaria) implementazione eb) il fatto che CPU e sistemi operativi moderni sono specificamente progettati per far funzionare C velocemente e le funzionalità che avere per C non sta aiutando (cache) o addirittura danneggiando attivamente (memoria virtuale) le prestazioni di Python.
E puoi inserire praticamente qualsiasi linguaggio gestito dalla memoria con un polimorfismo dinamico ad hoc qui ... quando si tratta delle sfide di un'implementazione efficiente, anche Python e Java sono praticamente "lo stesso linguaggio".