|
|
  |
Ускорить запись в файл в Windows, Как уменьшить потери времени на запись в файл |
|
|
|
May 16 2010, 19:31
|
Группа: Участник
Сообщений: 9
Регистрация: 16-05-10
Пользователь №: 57 305

|
Есть задача: принимать данные от аппаратуры программой1 и через файл передавать их в программу2. Действие происходит в Windows XP. При этом не устраивает скорость записи данных в файл. Передача осуществляется средствами WinAPI. Есть ли более быстрые способы передачи данных? Желательно минимальное изменение изменение кодов программ по причине того, что программу 1 и 2 делают разные люди.
|
|
|
|
|
May 16 2010, 19:47
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(Igor87 @ May 16 2010, 23:31)  Есть задача: принимать данные от аппаратуры программой1 и через файл передавать их в программу2. Действие происходит в Windows XP. При этом не устраивает скорость записи данных в файл. Передача осуществляется средствами WinAPI. Есть ли более быстрые способы передачи данных? Желательно минимальное изменение изменение кодов программ по причине того, что программу 1 и 2 делают разные люди. Даже средствами WinAPI скорость сильно зависит от того, записываете ли вы файл маленькими кусочками, или же большими блоками. Максимальная скорость получается, если писать блоками с размером, равным величине кластера на диске, отменив буферизацию. Т.е. здесь вы делаете такую буферизацию вручную. Ну, а самая медленная скорость получится, если писать функцией WriteFile() побайтно. А если нужен обмен между двумя программами на одном и том же компьютере, то надо открывать "виртуальные" файлы - файлы, отображаемые на память (при помощи функции API CreateFileMapping()). О том, как это делается, читайте тут - http://frolov-lib.ru/books/bsp/v27/ch1_1.htm
|
|
|
|
|
May 16 2010, 20:13
|
Группа: Участник
Сообщений: 9
Регистрация: 16-05-10
Пользователь №: 57 305

|
Спасибо за ответ! Так как запись нужно вести в режиме реального времени, то при записи маленькими кусочками (не побайтно конечно) скорости не хватает, а если большими кусками, то не хватает только в те моменты, когда ведется запись в файл. Такой вывод сделан на основе того, что каждая запись в файл получается от аппаратуры с меткой времени. Сравнивая соседние метки можем вычислить время, которое информация провела в пути от железа до файла. информация от аппаратуры получается по запрсу программы только после того, как был обработан ответ на старый запрос.
|
|
|
|
|
May 22 2010, 04:39
|
Группа: Участник
Сообщений: 9
Регистрация: 16-05-10
Пользователь №: 57 305

|
Цитата(Xenia @ May 16 2010, 23:47)  А если нужен обмен между двумя программами на одном и том же компьютере, то надо открывать "виртуальные" файлы - файлы, отображаемые на память (при помощи функции API CreateFileMapping()). О том, как это делается, читайте тут - http://frolov-lib.ru/books/bsp/v27/ch1_1.htmПопробовал сделать при помощи файлов, отображаемых на память.Вопрос: какого размера файл лучше всего загружать? Долго тестировал этот параметр. Смотрел время,затрачиваемое на запись в файл (при помощи QueryPerformanceCounter). У меня получилась линейная зависимость (чем меньше файл, тем быстрее он записывается).Это правильный вывод?Просто я слышал рекомендации на тему того, что файл должен быть выровнен по границе страницы памяти...
|
|
|
|
|
May 28 2010, 15:53
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Я не буду слишком категоричной, но в отношении механизма pipes у меня имеются опасения. Pipe - канал между приложениями, а потому быстро записывать в его можно будет только тогда, когда приложение-приемник более прожорливое, чем тот поток данных, который отправляется ему в рот. Если оно не будет успевать их проглатывать (усваивать), передача будет торомозить на функции WriteFile. А если там все-таки возможна буферизация, которая спасает от ситуации, когда скорость передачи выше, чем скорость приема (или приемник глотает не непрерывно, а порциями, между которыми пауза), то будет тот же самый вариант, что и файл, отраженный на память.
|
|
|
|
|
Jun 3 2010, 09:12
|
Участник

Группа: Свой
Сообщений: 60
Регистрация: 8-11-05
Пользователь №: 10 602

|
Смотри в сторону API функций: CreateFileMapping, MapViewOfFile Скорость записи в файл получается очень приличная.
|
|
|
|
|
Jun 4 2010, 01:18
|
Группа: Участник
Сообщений: 9
Регистрация: 16-05-10
Пользователь №: 57 305

|
Цитата(Deka @ May 28 2010, 13:48)  Можно попробовать сделать виртуальный диск и именно там расположить файл. Это позволит не переделывать программы. А как это можно сделать? По поводу CreatePipe, я читал, что все механизмы межпроцессного взаимодействия основаны на файлах отображаемых на память. И в пределе могут достигать скорости этого метода. Так что я пока остановился на файлах отображаемых в память. Вроде задержки уменшились, но возникла проблема того, что весь файл надо держать в памяти, а он может заполняться данными около часа.Там объем приличный может набегать. Я думал, что можно отображать часть файла, но похоже ошибся. Вот только память выделяется как-то не прямо пропорционально.То есть я вроде отображаю здоровый файл, а прибавка занимаемой памяти процессором маленькая.То есть механизм состоит не в том, что файл целиком находится в оперативной памяти, правильно?
|
|
|
|
|
Jun 7 2010, 14:21
|
Группа: Свой
Сообщений: 10
Регистрация: 9-12-07
Из: Москва
Пользователь №: 33 124

|
Цитата(Igor87 @ Jun 4 2010, 04:18)  Вот только память выделяется как-то не прямо пропорционально.То есть я вроде отображаю здоровый файл, а прибавка занимаемой памяти процессором маленькая.То есть механизм состоит не в том, что файл целиком находится в оперативной памяти, правильно? Для обмена данными с помощью общей памяти используются три функции: CreateFile - собственно создаем начальный handle, который дублируем в другой программе, CreateFileMapping - задаем, какого размера у нас будет общая память MapViewOfFile - создаем "окно", в которое 1-й процесс пишет, 2-й - читает... Поэтому, Вы можете создать большое общее пространство, и, открывая в нем "окна" небольшого размера для записи, записав, уведомлять считывающую программу о готовности очередного окна. Программа-считыватель открывает окно, читает, посылает уведомление пишущей, та закрывает окно, и оперативная память для данного окна освобождается. Поэтому реально выделенный объем будет равен ровно тому объему, который уже записан, но еще не прочитан. Далее, организуется запись "по кругу", когда вы по достижении конца файла начинаете писать в его начало. Если вы читаете быстрее, чем пишете, получится стабильная система. Насчет страниц памяти тоже все верно, для современных интеловских процессоров размер страницы составляет 4 килобайта, на кратную величину и надо ориентироваться... Использование каналов, на мой взгляд, для данной задачи несколько удобнее, потому что вам не нужно заботиться о синхронизации - для случая с потоком, скажем, 1 мегабайт/с это вполне подойдет (если, конечно, приемник успевает "переварить" этот поток с точки зрения вычислительной трудоемкости). Кроме того, для ОС Линукс такой подход вообще стандартен - перенаправить вывод одной программы на ввод другой - например, результат поиска файлов на поиск шаблона имени а потом на программу сортировки. При этом вся буферизация/синхронизация ложится на ОС, и все работает очень эффективно - самому написать без вдумчивого анализа и большого опыта написания многопоточных программ вряд ли получится... Если же потоки горазбо больше - гигабитный Ethernet фильтровать, к примеру, то, как альтернативу, предлагаю рассмотреть возможность использования MPI - ru.wikipedia.org/wiki/MPI - он изначально создавался для больших вычислительных систем с интенсивным обменом данными между различными процессами/узлами кластеров.
|
|
|
|
|
Jun 13 2010, 16:08
|
Группа: Участник
Сообщений: 9
Регистрация: 16-05-10
Пользователь №: 57 305

|
А GetSystemInfo() говорит, что гранулярность памяти 64 Кбайта. Пока остановился на варианте с файлами оторбражаемыми на память. Работает и, предварительно, скорость устраивает. По поводу MPI. Спасибо за сведения! Если этот вариант не покатит - попробую! Всем спасибо! Пока все.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|