Расширение PHP C для управления глобальной памятью

Я пишу расширение C, которое должно выделять глобальный массив при инициализации модуля (этот массив не меняется и актуален для каждого запроса). Я читал об управлении памятью расширений php c, но в большинстве источников не упоминается объявление переменных в стеке.

Это все еще допустимый подход, или более вероятно, что произойдет утечка, и в этом случае я должен предпочесть пемаллок и т. Д.?

Пример кода для иллюстрации вопроса:
В моем заголовке:

ZEND_BEGIN_MODULE_GLOBALS(myExtension)
long long myArray[ARRAY_SIZE];
ZEND_END_MODULE_GLOBALS(myExtension)

И в реализации:

PHP_MINIT_FUNCTION(myExtension) {
    fillUpMyArray();
    return SUCCESS;
}

Спасибо,
Алекс


person Alex K    schedule 10.07.2013    source источник
comment
нельзя ли это сделать с помощью memcache?   -  person    schedule 11.07.2013
comment
Реальная вещь немного сложнее, чем этот пример кода :) В настоящее время я использую APC для хранения данных, но он все еще слишком медленный (загрузка массивного массива и поиск по нему). Версия C на несколько порядков быстрее   -  person Alex K    schedule 11.07.2013
comment
если вам нужно начать расширять его таким образом, возможно, php не тот язык, который следует использовать в первую очередь.   -  person    schedule 11.07.2013
comment
php в основном нормально. Это большой сайт с большой кодовой базой и миллионами ежедневных пользователей. PHP позволяет нам быстро разрабатывать, и все в команде разработчиков это знают. Есть только пара кусков php, которые я переписываю на C, потому что они узкие места. Начать сначала не вариант :(   -  person Alex K    schedule 11.07.2013


Ответы (1)


Существует два основных вида использования памяти внутри расширения php:

  • локальное хранилище потока, которое в zend-языке является "глобальным потокобезопасным" переменным, используемым во время определенного запроса;
    необходимо настроить в ZEND_GINIT_FUNCTION(myExtension) и отключить в ZEND_GSHUTDOWN_FUNCTION(myExtension) [доступно, когда ZEND_MODULE_API_NO >=20060613, php >=5.2.0]
  • хранение на уровне процесса, которое называется "постоянными данными";
    должно быть настроено статически и/или в ZEND_MINIT_FUNCTION(myExtension) и удалено статически и/или в ZEND_MSHUTDOWN_FUNCTION(myExtension)

С помощью макроса ZEND_BEGIN_MODULE_GLOBALS вы объявляете потокобезопасные глобальные переменные, а вам действительно нужны постоянные данные.

(!) Обратите внимание, что php знает только тип данных long, а не long long.

Чего вы не говорите, так это того, как именно вы используете свой массив.
В вашем конкретном случае вы можете просто использовать статический массив, определенный в вашем файле .c/.cpp, плюс функцию доступа к массиву:

static long myArray[ARRAY_SIZE];

ZEND_MINIT_FUNCTION(myExtension)
{
    fillUpMyArray();
    return SUCCESS;
}

ZEND_FUNCTION(myext_get)
{
    long idx;

    if (zend_parse_parameters_ex(0, ZEND_NUM_ARGS() TSRMLS_CC, "l", &idx) == FAILURE)
        RETURN_NULL();

    // TODO check array bounds!

    RETURN_LONG(myArray[idx]);
}
person klaus triendl    schedule 14.11.2013