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.