производительность — stream_set_write_buffer или блокировка файлов в PHP?

Я пытаюсь создать систему кеширования, в которой можно записать большой объем данных (от 8 до 200 КБ) как можно быстрее.

В настоящее время я применяю функции блокировки файлов, используя код, подобный приведенному ниже:

$file_handle=fopen($file_name,"w");
flock($file_handle,LOCK_EX);
fwrite($file_handle,$all_data);
flock($file_handle,LOCK_UN);
fclose($file_handle);

Является ли это наиболее оптимальным способом, позволяющим записывать в файл одновременно только одному процессу, если многие запускают один и тот же сценарий одновременно, или я должен также включить stream_set_write_buffer($file_handle,0); или я должен отказаться от блокировки файлов?

4

Решение

Короче:

file_put_contents($file_name, $all_data, LOCK_EX);

Длинная история:
Есть одна проблема с вашим кодом: режим «w» усекает файл до того, как будет установлена ​​блокировка. Если два отдельных процесса усекают файл, то один пишет 200 КБ, а другой записывает 8 КБ, в вашем файле останется 192 КБ мусора. Я бы порекомендовал открыть файл в режиме «c» и в конце урезать его после того, как все данные записаны:

$file_handle = fopen($file_name, 'c');
stream_set_write_buffer($file_handle, 0); // try to disable write buffering
flock($file_handle, LOCK_EX);
fwrite($file_handle, $all_data); // write to possibly pre-allocated space
ftruncate($file_handle, strlen($all_data)); // remove gabage left from previous write
fflush($file_handle); // flush write buffers if enabled
flock($file_handle, LOCK_UN);
fclose($file_handle);

‘c’ Открыть файл только для записи. Если файл не существует, он создается. Если он существует, он не усекается (в отличие от ‘w’), и вызов этой функции не выполняется (как в случае с ‘x’). Указатель файла располагается в начале файла. Это может быть полезно, если необходимо получить консультативную блокировку (см. Flock ()) перед попыткой изменить файл, так как использование ‘w’ может обрезать файл до получения блокировки (если требуется усечение, ftruncate () может быть используется после запроса блокировки).

Вы должны убедиться, что буфер записи очищен перед снятием блокировки, либо вызывая fflush() или отключение буферизации записи. поскольку stream_set_write_buffer(); может потерпеть неудачу, лучше иметь fflush() тем не мение. Также обратите внимание, что буферизация записи предназначена для повышения производительности последовательной записи. Поскольку вы выполняете только одну операцию записи, буфер записи может немного снизить производительность, поэтому лучше сначала попытаться отключить его.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]