Alcune lingue interpretate caricano gli script solo una volta?

3

Il vantaggio di un'applicazione compilata è che tutte le librerie e le classi vengono caricate una sola volta e siedono in attesa dell'input giusto?

Vengo da uno sfondo che funziona con PHP e le risorse / classi che sono state caricate hanno caricato ogni richiesta di pagina che mette un cattivo carico sulla memoria del server. Ad esempio, dato il core PHP utilizza 1MB di memoria, e un wordpress carica altri 7MB di oggetti - si finisce con 8MB caricati ogni richiesta .

Ho pensato che fosse lo stesso processo per altri linguaggi di scripting come Python e Ruby.

Tuttavia, ho iniziato a cercare su node.js (perché JavaScript è così bello) e sembra che sia stato caricato una volta (e che la memoria necessaria sia presa una volta sola) e poi si siede in attesa per le richieste che condividono le classi che ha caricato tra i nuovi thread (è il termine giusto?) in modo che non debbano ricaricarli.

Quindi PHP richiederebbe 8MB process * 10 requests = 80MB per dieci richieste simultanee a wordpress. Sembra che node.js prenda 8MB process + 10 requests = ~14MB .

È proprio vero? Ci sono altri linguaggi di scripting che fanno questo?

    
posta Xeoncross 27.06.2011 - 20:43
fonte

2 risposte

2

Come ha detto @ S.Lott, la risposta è "sì". La risposta più complicata è: "Ci sono molti modi in cui questo può essere fatto". Continua a leggere per una spiegazione completa di molti dei modi comuni in cui la memoria può essere condivisa tra richieste concorrenti.

Per capire di più, devi capire come la memoria è effettivamente gestita dal sistema operativo e utilizzata dal programma.

Il sistema operativo assegna memoria a processi . I processi stanno eseguendo programmi che non possono influenzare la memoria dell'altro. All'interno di un processo ci possono essere uno o più thread che il sistema operativo conosce. Ogni thread sta tentando di fare cose, accedere alla memoria, ecc. E può finire (a discrezione del sistema operativo) pianificato sequenzialmente o in parallelo su una o più CPU. (Gli scheduling preferiscono mantenere i thread su una singola CPU, ma non sempre.) Ogni thread è quindi responsabile di fare tutto ciò che vuole fare. Un thread può essere, a seconda del programma, facendo una cosa o più cose.

Hai familiarità con un modello di processi multipli in cui la memoria è assegnata a processi che poi fanno ciascuno una cosa. In questo modello ogni processo ha memoria separata. Pertanto, se si dispone di 10 processi, ognuno dei quali ha caricato 8 MB di dati, sono necessari 80 MB di memoria. In PHP, per impostazione predefinita, ogni processo può servire molte richieste nel corso della sua durata, ma il numero massimo di richieste parallele offerte è uguale al numero di processi che hai eseguito.

L'opzione successiva è il multithreading. Quindi puoi caricare i dati nel thread e quindi più thread possono leggere quei dati. Molte lingue usano il multi-threading in questo modulo. Ad esempio, Java e Python lo fanno. Lo svantaggio di questo stile è che possono accadere cose strane quando 2 thread stanno facendo qualcosa con la stessa memoria, e non è divertente eseguire il debug.

Passando, il trucco utilizzato da Node.js è più semplice. Ricorda che ho detto che a seconda del programma un thread può fare una o più cose? Bene Node.js usa uno stile di programmazione di callback che ogni volta che si ha un evento fa qualcosa, registra un callback per il prossimo evento, quindi fa qualcos'altro. Con questo stile un singolo thread può essere in attesa di eventi per molte richieste. Questo stile può essere utilizzato in qualsiasi lingua, ma è più conveniente quando si dispone di un intero framework che fa la stessa cosa. Alcune lingue dispongono di funzionalità per nascondere tutti i dettagli della richiamata. Se senti parlare di "thread verdi" o "multi-threading cooperativo", è quello che sta succedendo. Esempi di lingue che usano questo includono Ruby e Racket.

Il trucco successivo è che il sistema operativo può essere esplicitamente detto di condividere blocchi di memoria. Questo è disponibile con chiamate di basso livello a cose come mmap , che possono essere esposte in linguaggi di livello superiore in vari modi.

Andando avanti, il sistema operativo a volte sa che può condividere la memoria. Questo è ciò che sta accadendo nel caso delle lingue compilate. Le librerie condivise possono essere lette da, ma non scritte. Tale memoria di sola lettura può essere caricata in molti processi. Hai visto questo quando le librerie condivise vengono caricate in molti programmi C contemporaneamente. In linea di principio un linguaggio interpretato potrebbe utilizzare questo meccanismo stesso, e ho visto discussioni su come farlo, ma in genere non ha senso e non lo fanno.

E un trucco finale. Molti sistemi operativi (tutte le varianti di * nix per esempio) hanno l'idea della memoria copy-on-write. Questa memoria può essere condivisa tra un numero qualsiasi di processi, ma qualsiasi processo che tenta di scriverlo vedrà la memoria copiata altrove, sarà puntata lì e potrà quindi leggere e scrivere da lì. Questo è usato per rendere efficiente la chiamata di fork . Se si utilizza, ad esempio, Apache con un modello pre-fork, è possibile sfruttare questo vantaggio caricando molti dati nel processo Apache principale. Quindi ogni copia biforcuta inizierà a condividere molti dati. Con il passare del tempo i dati non vengono condivisi, ma se si eliminano i processi dopo un certo periodo di tempo è possibile ridurre la pressione della memoria. Non so quanto sia facile farlo con PHP, ma è un trucco mod_perl molto comune e può consentire la condivisione della memoria.

    
risposta data 27.06.2011 - 21:30
fonte
2

Sì.

Il problema con PHP non riguarda la lingua, riguarda l'ambiente di esecuzione che utilizza.

Quasi tutte le lingue ti permettono di scrivere qualsiasi tipo di programma, non solo le pagine web. Un tipo di programma è un server webapp che si avvia e si trova in attesa di richieste. Nella maggior parte dei casi, questo viene eseguito dietro un server Web (Apache, Nginx, lighttpd, ecc.) E riceve le richieste utilizzando uno specifico canale di comunicazione, utilizzando un modulo specifico nel server (come uWSGI, mod_wsgi, jakarta, ecc.) O alcuni protocolli standard (FastCGI o anche HTTP)

Sì, puoi farlo in PHP se vuoi! (usando php-cli, o qualcosa di simile) ma non penso che saresti in grado di utilizzare qualsiasi framework in quella modalità operativa.

    
risposta data 27.06.2011 - 20:57
fonte

Leggi altre domande sui tag