Вопрос

Когда я перебираю строки в файле A, я разбираю строку и помещаю каждую строку (char*) в char**.

В конце строки я затем запускаю процедуру, которая состоит из открытия файла B, используя fgets, fseek и fgetc чтобы захватить символы из этого файла.Затем я закрываю файл B.

Я повторяю повторное открытие и повторное закрытие файла B для каждой строки.

Что я хотел бы знать, так это:

  1. Значительно ли снижается производительность при использовании malloc и free, такой , что я должен использовать что - то статическое , например myArray[NUM_STRINGS][MAX_STRING_WIDTH] вместо динамического char** myArray?

  2. Есть ли значительные затраты на производительность при открытии и закрытии файла B (концептуально, много тысяч раз)?Если мой файл A отсортирован, есть ли способ для меня использовать fseek чтобы переместить "назад" в файл B, чтобы сбросить место, где я ранее находился в файле B?

Редактировать Оказывается, что двукратный подход значительно сократил время выполнения:

  1. Мой файл B на самом деле является одним из двадцати четырех файлов.Вместо того чтобы открывать один и тот же файл B1 тысячу раз, а затем B2 тысячу раз и т.д.Я открываю файл B1 один раз, закрываю его, B2 один раз, закрываю и т.д.Это сокращает многие тысячи fopen и fclose операций примерно до 24.

  2. Я использовал rewind() чтобы сбросить указатель на файл.

Это позволило увеличить скорость примерно в 60 раз, что более чем достаточно.Спасибо, что указали мне на rewind().

Это было полезно?

Решение

Если ваш динамический массив со временем растет, на некоторых из них возникает стоимость копирования. reallocс.Если вы используете эвристику «всегда удвоить», это амортизируется до O(n), так что это не так уж и плохо.Если вы заранее знаете размер, массив, выделенный в стеке, все равно будет работать быстрее.

По второму вопросу читайте rewind.Он должен быть быстрее, чем постоянное открытие и закрытие, и позволяет вам меньше управлять ресурсами.

Другие советы

Что я хотел бы знать:

  • ваш код работает правильно?
  • он работает достаточно быстро для вашей цели?

Если оба ответа — «да», ничего не меняйте.

Открытие и закрытие имеют переменные накладные расходы в зависимости от того, конкурируют ли другие программы за этот ресурс.

сначала измерьте размер файла а затем используйте это, чтобы заранее вычислить размер массива, чтобы выполнить одно большое распределение кучи.

Сразу многомерный массив у вас не получится, но немного арифметики с указателями и все готово.

Можете ли вы не кэшировать позиционную информацию в другом файле, а затем вместо того, чтобы открывать и закрывать его, использовать предыдущие индексы поиска в качестве смещения?На самом деле зависит от конкретной логики.

  1. Если ваши файлы большие, дисковый ввод-вывод будет намного дороже, чем управление памятью.Беспокойство о производительности malloc/free перед профилированием указывает на то, что узким местом является преждевременная оптимизация.

  2. Вполне возможно, что накладные расходы из-за частого открытия/закрытия значительны в вашей программе, но, опять же, фактический ввод-вывод, вероятно, будет более дорогим, если только файлы не малы, и в этом случае потеря буферов между закрытием и открытием потенциально может вызвать дополнительный дисковый ввод-вывод.И да, вы можете использовать ftell(), чтобы получить текущую позицию в файле, а затем fseek с SEEK_SET, чтобы добраться до нее.

Использование динамической памяти всегда снижает производительность.Использование статического буфера обеспечит повышение скорости.

При повторном открытии файла также произойдет снижение производительности.Вы можете использовать fseek(pos, SEEK_SET) для установки указателя файла в любую позицию в файле или fseek(offset, SEEK_CUR) для выполнения относительного перемещения.

Значительное снижение производительности является относительным, и вам придется определить, что это означает, самостоятельно.

  1. Я думаю, что лучше выделить фактическое пространство, которое вам нужно, и накладные расходы, вероятно, не будут значительными.Это позволяет избежать как тратить пространство и переполнение стека

  2. ДА.Хотя ввод-вывод кэшируется, вы выполняете ненужные системные вызовы (открываете и закрываете).Используйте fseek с вероятно SEEK_CUR или SEEK_SET.

В обоих случаях имеется некоторый снижение производительности, но его значимость будет зависеть от размера файлов и контекста, в котором работает ваша программа.

  1. Если вы действительно знаете максимальное количество строк и максимальную ширину, это будет намного быстрее (но вы можете потратить много памяти, если используете меньше «максимума»).Счастливая среда — сделать то, что делают многие реализации динамических массивов в C++:всякий раз, когда вам нужно перераспределить myArray, выделите вдвое больше места, чем вам нужно, и перераспределите снова только тогда, когда у вас закончится место.Это требует производительности O(log n).

  2. Это может стать большим ударом по производительности.Я настоятельно рекомендую использовать fseek, хотя детали будут зависеть от вашего алгоритма.

Я часто обнаруживаю, что затраты на производительность перевешиваются прямым управлением памятью, которое поставляется с malloc и эти низкоуровневые обработчики C в памяти.Если только эти области памяти не останутся статичными и нетронутыми в течение времени, которое в амортизированном времени превышает время воздействия на эту память, возможно, будет более выгодно придерживаться статического массива.В конце концов, решать вам.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top