Sto sviluppando un'estensione PHP, in cui un metodo oggetto deve restituire un array zval
.Come restituire un array da un'estensione PHP, senza copiarlo in memoria?
Il metodo appare come:
ZEND_METHOD(myObject, myMethod)
{
zval **myArrayProperty;
if (zend_hash_find(Z_OBJPROP_P(getThis()), "myArrayProperty", sizeof("myArrayProperty"), (void **) &myArrayProperty) == FAILURE) {
RETURN_FALSE;
}
RETURN_ZVAL(*myArrayProperty, 1, 0);
}
Il codice funziona bene e fa la cosa atteso - restituisce oggetto di myArrayProperty
. Tuttavia, mi piacerebbe ottimizzare il processo.
myArrayProperty
memorizza un array, che può essere abbastanza grande. E la macro RETURN_ZVAL()
duplica quell'array per restituire il valore. Il processo di duplicazione richiede una buona quantità di tempo per acquisire memoria e copiare tutti i valori dell'array. Allo stesso tempo, l'array restituito viene solitamente utilizzato per operazioni di sola lettura. Quindi una buona ottimizzazione sarebbe quella di utilizzare il meccanismo di PHP con il conteggio dei riferimenti e non duplicare i contenuti di myArrayProperty
. Piuttosto vorrei aumentare refcount
di myArrayProperty
e solo tornare puntatore ad esso. Questa è la stessa tattica usata normalmente, quando si lavora con variabili in un'estensione PHP.
Tuttavia, sembra, non c'è modo di farlo - è necessario duplicare il valore per restituirlo da una funzione di estensione PHP. La modifica della firma della funzione per restituire il valore per riferimento, non è un'opzione, poiché collega la proprietà e il valore restituito, ovvero modificando successivamente il valore restituito, modifica anche la proprietà. Questo non è un comportamento accettabile.
L'incapacità di impegnarsi conteggio dei riferimenti aspetto strano, perché stesso codice in PHP:
function myMethod() {
{
return $this->myArrayProperty;
}
è ottimizzata dal meccanismo di conteggio di riferimento. Ecco perché sto facendo questa domanda a StackOverflow nel caso in cui mi sia sfuggito qualcosa.
Quindi, c'è un modo per restituire un array da una funzione nell'estensione PHP, senza copiare l'array in memoria?
Ma non sta per portare a una perdita di memoria o segfault (a seconda di quale viene prima)? Perdita di memoria avverrà quando tutti i riferimenti alla proprietà saranno cancellati, ma la memoria, occupata dal suo contenitore zval non può essere liberata, perché il Refcount rimarrebbe comunque 1. Segfault accadrà, quando il valore restituito sarà eliminato, quindi il suo zval il contenitore viene cancellato insieme all'array (hashTable condiviso, a cui si fa riferimento sia da quel contenitore che dal contenitore zval di proprietà), quindi l'uso di proprietà in seguito porterà a effetti imprevedibili, ma sicuramente sbagliati. –
Riferimenti di proprietà zval - questo è il conto = 1. questo codice aumenta il conteggio, dato che zval viene restituito e sarà referenziato da entrambi gli oggetti e dal chiamante. se l'oggetto non ha bisogno di proprietà diminuirà il conto, quindi sarà di proprietà solo del chiamante. quindi, questo codice mi sembra sano di mente. ma, ancora una volta, tutto ciò è strettamente teorico - non ho ancora scaricato PHP in questo momento – JimiDini
sfortunatamente, come previsto, il codice non funziona - confermato nella pratica: http://pastebin.com/FRfaJZvL. Il problema è come detto sopra: l'oggetto e il chiamante fanno riferimento a posizioni di memoria differenti. –