Я пытаюсь сделать случайную запись (тест производительности) в файл, используя несколько потоков (pthread). Похоже, если я закомментирую mutex lock
размер созданного файла меньше фактического, как будто некоторые записи теряются (всегда в несколько кратных размеру куска). Но если я оставлю мьютекс, это всегда точный размер.
Есть ли в моем коде проблема в другом месте и мьютекс на самом деле не требуется (как предложено @evan) или мьютекс нужен здесь
void *DiskWorker(void *threadarg) {
FILE *theFile = fopen(fileToWrite, "a+");
....
for (long i = 0; i < noOfWrites; ++i) {
//pthread_mutex_lock (&mutexsum);
// For Random access
fseek ( theFile , randomArray[i] * chunkSize , SEEK_SET );
fputs ( data , theFile );
//Or for sequential access (in this case above 2 lines would not be here)
fprintf(theFile, "%s", data);
//sequential access end
fflush (theFile);
//pthread_mutex_unlock(&mutexsum);
}
.....
}
Вам определенно нужен мьютекс, потому что вы запускаете несколько разных файловых команд. Базовая файловая подсистема не может знать, сколько файловых команд вы собираетесь вызвать для завершения всей вашей операции.
Так что вам нужен мьютекс.
В вашей ситуации вы можете обнаружить, что вы получаете лучшую производительность, применяя мьютекс вне петля. Причина в том, что в противном случае переключение между потоками может привести к чрезмерному пропуску между различными частями диска. Жесткие диски занимают около 10ms
перемещать головку чтения / записи, чтобы потенциально сильно замедлить процесс.
Так что это может быть хорошей идеей для сравнения.
Вы открываете файл, используя «режим добавления». Согласно C11:
Открытие файла в режиме добавления (
'a'
как первый персонаж в
аргумент mode) заставляет принудительно выполнять все последующие записи в файл
на текущий текущий конец файла, независимо от промежуточных вызовов
fseek
функция.
Стандарт C не определяет, как именно это должно быть реализовано, но в системе POSIX это обычно реализуется с использованием O_APPEND
флаг open
функция, а сброс данных выполняется с помощью функции write
, Обратите внимание, что fseek
Звонок в вашем коде не должен иметь никакого эффекта.
Я думаю, что POSIX требует этого, так как он описывает, как перенаправить вывод в режиме добавления (>>
) сделано оболочка:
При добавлении перенаправления вывода должен появиться файл, имя которого приводит к
от раскрытия слова, которое будет открыто для вывода на назначенный
дескриптор файла. Файл открывается так, как будто функция open () как
определенный в томе системных интерфейсов POSIX.1-2008 был назван
с флагом O_APPEND. Если файл не существует, он должен быть
создано.
И так как большинство программ используют FILE
интерфейс для отправки данных stdout
это наверное требует fopen
использовать open
с O_APPEND
а также write
(а не такие функции, как pwrite
) при записи данных.
Так что если в вашей системе fopen
с 'a'
режим использует O_APPEND
и промывка производится с помощью write
и ваше ядро и файловая система правильно реализуют O_APPEND
флаг, использование мьютекса не должно иметь никакого эффекта при записи не вмешивайся:
Если
O_APPEND
установлен флаг состояния файла, установлен файл
смещение должно быть установлено до конца файла перед каждой записью, и нет
промежуточная операция изменения файла должна происходить между изменениями
смещение файла и операция записи.
Обратите внимание, что не все файловые системы поддерживают это поведение. Проверьте этот ответ.
Что касается моего ответа на ваш предыдущий вопрос, я предложил удалить мьютекс, так как он не должен влиять на размер файла (и это никак не повлияло на мою машину).
Лично я никогда не использовал O_APPEND
и не решился бы сделать это, так как его поведение может не поддерживаться на каком-то уровне, плюс его поведение странно в Linux (см. раздел «Ошибки» в pwrite
).