Программа должна в процессе работы быстро записывать данные на винт. Хочется, чтобы использовалась максимально возможная скорость данного винта. После WriteFile используется FlushFileBuffers. Коробит от того, что я вызываю эту функцию даже в момент, когда записывается очень маленькое количество данных (например, 4 байта). "Беспокоить" винт из-за такой мелочи как-то не хочется...
Можно ли как-нибудь определить наиболее эффективное минимальное количество данных для данного винта, которое он быстро запишет в файле, но и чтоб не гонять его по пустякам...
Ведь как я понимаю 4 байта и 256 байт он будет записывать одиаковое количество времени. А если дважды flush-нуть по 4 байта, то уйдет вдвое больше времени (или я не прав?).
По размеру кластера что-ли записывать?
Какими функциями можно определить необходимые величины*
14.04.05 08:34: Перенесено модератором из 'C/C++. Прикладные вопросы' — Odi$$ey
Здравствуйте, 7C, Вы писали:
7C>Программа должна в процессе работы быстро записывать данные на винт. Хочется, чтобы использовалась максимально возможная скорость данного винта. После WriteFile используется FlushFileBuffers. Коробит от того, что я вызываю эту функцию даже в момент, когда записывается очень маленькое количество данных (например, 4 байта). "Беспокоить" винт из-за такой мелочи как-то не хочется... 7C>Можно ли как-нибудь определить наиболее эффективное минимальное количество данных для данного винта, которое он быстро запишет в файле, но и чтоб не гонять его по пустякам... 7C>Ведь как я понимаю 4 байта и 256 байт он будет записывать одиаковое количество времени. А если дважды flush-нуть по 4 байта, то уйдет вдвое больше времени (или я не прав?). 7C>По размеру кластера что-ли записывать? 7C>Какими функциями можно определить необходимые величины*
А зачем постоянно вызывать FlushFileBuffers?
[ Posted via RSDN@Home 1.1.4 beta 4 (303) listening to Led Zeppelin — Stairway To Heaven ]
It's kind of fun to do the impossible (Walt Disney)
Здравствуйте, 7C, Вы писали:
7C>Программа должна в процессе работы быстро записывать данные на винт. Хочется, чтобы использовалась максимально возможная скорость данного винта. После WriteFile используется FlushFileBuffers. Коробит от того, что я вызываю эту функцию даже в момент, когда записывается очень маленькое количество данных (например, 4 байта). "Беспокоить" винт из-за такой мелочи как-то не хочется... 7C>Можно ли как-нибудь определить наиболее эффективное минимальное количество данных для данного винта, которое он быстро запишет в файле, но и чтоб не гонять его по пустякам... 7C>Ведь как я понимаю 4 байта и 256 байт он будет записывать одиаковое количество времени. А если дважды flush-нуть по 4 байта, то уйдет вдвое больше времени (или я не прав?). 7C>По размеру кластера что-ли записывать? 7C>Какими функциями можно определить необходимые величины*
Что означает быстро?
Стоит проверить несколько пунктов:
1. Проверить включен ли режим DMA для дисков.
2. Использовать быстрый диск: с большой скоростью вращения шпинделя, с большим объёмом буффера, с большой плотностью записи.
3. Использовать RAID.
4. Дефрагментировать диск перед записью данных.
5. Производить запись в уже существующий файл (т.е. в зарезервированное пространство.)
6. Производить запись на raw раздел.
7. Производить запись на отдельний жесткий диск.
8. Отключить сервисы которые могут снизить скорость работы: сжатие данных, построение индексов для поиска, антивирусы, файл подкачки.
9. Проверить включена ли отложенная запись на диск.
10. Организовать кеш для данных в памяти, а затем сбрасывать данные на диск.
11. Ускорить части не относящиеся к диску, постараться избежать преобразований данных bin->text, и копирования данных.
12.
Использование flush скорости не добавляет.
Запись лучше вести большими блоками дабы избежать потерь с связанных с Большим количеством вызовов WriteFile.
S>Что означает быстро?
S>Стоит проверить несколько пунктов:
S>1. Проверить включен ли режим DMA для дисков. S>2. Использовать быстрый диск: с большой скоростью вращения шпинделя, с большим объёмом буффера, с большой плотностью записи. S>3. Использовать RAID. S>4. Дефрагментировать диск перед записью данных. S>5. Производить запись в уже существующий файл (т.е. в зарезервированное пространство.) S>6. Производить запись на raw раздел. S>7. Производить запись на отдельний жесткий диск. S>8. Отключить сервисы которые могут снизить скорость работы: сжатие данных, построение индексов для поиска, антивирусы, файл подкачки. S>9. Проверить включена ли отложенная запись на диск. S>10. Организовать кеш для данных в памяти, а затем сбрасывать данные на диск. S>11. Ускорить части не относящиеся к диску, постараться избежать преобразований данных bin->text, и копирования данных. S>Использование flush скорости не добавляет. S>Запись лучше вести большими блоками дабы избежать потерь с связанных с Большим количеством вызовов WriteFile.
Трудно было рассчитывать на столь всеобъемлющий ответ.
Моя программа постоянно генерит большое количество данных, которое нужно сохранить. Причем, объем этих данных заранее неизвестен (фактически ограничен размером свободого места на винте). Цель программы: сохранять эти данные максимально быстро, но делать это равномерно по времени (программа не должна запинаться, когда системе "вздумается" записывать данные).
Насчет flush'а я не решил использовать его или нет. То что он не ускоряет понятно, но с помощью него я пытаюсь регулировать фактическую запись на винт, ведь насколько я понимаю, вызов WriteFile не гарантирует что данные окажутся на винте. Мне крайне нежелательно, чтоб программа работала-работала, а потом, бац, встала и ждет когда винт запишет.
Выбирать винт не приходится, можно только посоветовать пользователю использовать лучший из имеющихся (отдельный быстрый винт и всё такое). К тому же не хотелось бы менять настройки на компе пользователя. С поддержкой потом геморра необерешься. Дам рекомандации пользователям по настройке, а сам ничего делать не буду.
Если можно напишите поподробней по пункту 9. Как узнать включена ли отложенная запись на диск?
Пункт 5 — тоже интересно. Жаль только, что неизвестно сколько резервировать, если объема не хватит, дополнительное резервирование внесет недопустимую паузу в работе программы.
А что никак нельзя узнать какие блоки по WriteFile быстрее всего запишет винт?
Здравствуйте, 7C, Вы писали:
7C>Здравствуйте, silamantex, Вы писали:
S>>Что означает быстро?
S>>Стоит проверить несколько пунктов:
S>>1. Проверить включен ли режим DMA для дисков. S>>2. Использовать быстрый диск: с большой скоростью вращения шпинделя, с большим объёмом буффера, с большой плотностью записи. S>>3. Использовать RAID. S>>4. Дефрагментировать диск перед записью данных. S>>5. Производить запись в уже существующий файл (т.е. в зарезервированное пространство.) S>>6. Производить запись на raw раздел. S>>7. Производить запись на отдельний жесткий диск. S>>8. Отключить сервисы которые могут снизить скорость работы: сжатие данных, построение индексов для поиска, антивирусы, файл подкачки. S>>9. Проверить включена ли отложенная запись на диск. S>>10. Организовать кеш для данных в памяти, а затем сбрасывать данные на диск. S>>11. Ускорить части не относящиеся к диску, постараться избежать преобразований данных bin->text, и копирования данных. S>>Использование flush скорости не добавляет. S>>Запись лучше вести большими блоками дабы избежать потерь с связанных с Большим количеством вызовов WriteFile.
7C>Трудно было рассчитывать на столь всеобъемлющий ответ. 7C>Моя программа постоянно генерит большое количество данных, которое нужно сохранить. Причем, объем этих данных заранее неизвестен (фактически ограничен размером свободого места на винте). Цель программы: сохранять эти данные максимально быстро, но делать это равномерно по времени (программа не должна запинаться, когда системе "вздумается" записывать данные).
Какая скорость потока данных? МБ/с?
7C>Насчет flush'а я не решил использовать его или нет. То что он не ускоряет понятно, но с помощью него я пытаюсь регулировать фактическую запись на винт, ведь насколько я понимаю, вызов WriteFile не гарантирует что данные окажутся на винте. Мне крайне нежелательно, чтоб программа работала-работала, а потом, бац, встала и ждет когда винт запишет.
Можно попробовать решить проблему используя нити и собственный буффер.
В одной нитке генерируются данные, она же помещает их в буффер.
Задача другой производить запись данных на диск, а главное вызывать с некотором интервалом flush, не через время, а после записи определённого объема данных.
Насколько я понимаю, основное требование, чтобы получение данных и их запись происходили одновременно?
7C>Выбирать винт не приходится, можно только посоветовать пользователю использовать лучший из имеющихся (отдельный быстрый винт и всё такое). К тому же не хотелось бы менять настройки на компе пользователя. С поддержкой потом геморра необерешься. Дам рекомандации пользователям по настройке, а сам ничего делать не буду.
Может иметь смысл увеличить размер кластера, для используемой FS.
7C>Если можно напишите поподробней по пункту 9. Как узнать включена ли отложенная запись на диск?
В DeviceManager посмотреть в свойствах диска. Должна быть включена.
7C>Пункт 5 — тоже интересно. Жаль только, что неизвестно сколько резервировать, если объема не хватит, дополнительное резервирование внесет недопустимую паузу в работе программы.
7C>А что никак нельзя узнать какие блоки по WriteFile быстрее всего запишет винт?
Это не решит проблему в целом. Единственное, не стоит записывать данные очень маленькими блоками.
По WriteFile данные попадают сначала в дисковый кеш, а только затем ОС сохранит их на диск.
Поэтому размер блока указанного для WriteFile не столь важен.
Удачи!
Re[4]: Быстрая запись на винт
От:
Аноним
Дата:
07.04.05 09:06
Оценка:
У меня осталось очень хорошее впечатление о скорости работы функций ввода/вывода из мультимедийной библиотеки (работа с аудио/видео потоками, устройствами видео/аудио).
Кажется их название начинается на mmio... (точно уже не помню, т.к. было давно). Можно их попробовать вместо WriteFile
Здравствуйте, silamantex, Вы писали:
S>Какая скорость потока данных? МБ/с?
Максимально возможная для данного компа.
Мне нужно выжать всё, что можно выжать. Дело втом, что современные компьютеры слишком слабы для моей программы и я пытаюсь выжать из них все на что они способны. Чтоб не ходить вокруг да около скажу: это программа для захвата экрана компьютера (например, пять раз в секунду) и запись всего этого в видеофайл (avi). Отсюда требование к "ровной" работе программы (у avi ведь framerate — величина постояная). Узкое место в этом: сохранение на винт каждого кадра. Кстати, я не пишу прямо в avi, а программо пакую каждый массив и только после этого записываю на винт — получается быстрее, т.к. пакуется в разы, а меньшее количество данных намного быстрее сохраняется на винт.
S>Можно попробовать решить проблему используя нити и собственный буффер. S>В одной нитке генерируются данные, она же помещает их в буффер. S>Задача другой производить запись данных на диск, а главное вызывать с некотором интервалом flush, не через время, а после записи определённого объема данных.
Идея интересная. Размер каждого кадра я знаю... как часто он должен записываться тоже... Даст ли это выигрыш по скорости? Попробовать стоит...
7C>>А что никак нельзя узнать какие блоки по WriteFile быстрее всего запишет винт? S>Это не решит проблему в целом. Единственное, не стоит записывать данные очень маленькими блоками. S>По WriteFile данные попадают сначала в дисковый кеш, а только затем ОС сохранит их на диск.
Если знать когда кэш сам сбрасыватся на винт, то flush не понадобится вообще.
Здравствуйте, 7C, Вы писали:
7C>Здравствуйте, silamantex, Вы писали:
S>>Какая скорость потока данных? МБ/с? 7C>Максимально возможная для данного компа. 7C>Мне нужно выжать всё, что можно выжать. Дело втом, что современные компьютеры слишком слабы для моей программы и я пытаюсь выжать из них все на что они способны. Чтоб не ходить вокруг да около скажу: это программа для захвата экрана компьютера (например, пять раз в секунду) и запись всего этого в видеофайл (avi). Отсюда требование к "ровной" работе программы (у avi ведь framerate — величина постояная). Узкое место в этом: сохранение на винт каждого кадра. Кстати, я не пишу прямо в avi, а программо пакую каждый массив и только после этого записываю на винт — получается быстрее, т.к. пакуется в разы, а меньшее количество данных намного быстрее сохраняется на винт.
Присоединяясь к тому что сказал silamantex, добавлю, что можно добится большего эффекта компрессии кадров, если их паковать некими группами похожих кадров. В крайнем случае можно совместно паковать например, по 5 кадров и записывать каждую секунду.
Re: Быстрая запись на винт
От:
Аноним
Дата:
07.04.05 14:11
Оценка:
Я подобную программу по захвату экрана или части экрана компа и запись его в AVI файл юзал на весьма не быстрой машине. Все работало крайне отлично. Можно было регулировать кол-во кадров, степень сжатия и.т.п. А вот как называлась... кажется screenCam, но не уверен. Позже скажу название.
Здравствуйте, Аноним, Вы писали:
А>Я подобную программу по захвату экрана или части экрана компа и запись его в AVI файл юзал на весьма не быстрой машине. Все работало крайне отлично. Можно было регулировать кол-во кадров, степень сжатия и.т.п. А вот как называлась... кажется screenCam, но не уверен. Позже скажу название.
Да ScreenCam.
Она стоит у меня... Как и куча других. За конкурентами я слежу.
Стоит ScreenCam $200.
У меня будет в разы дешевле и вряд ли хуже...
Здравствуйте, silamantex, Вы писали:
7C>>Насчет flush'а я не решил использовать его или нет. То что он не ускоряет понятно, но с помощью него я пытаюсь регулировать фактическую запись на винт, ведь насколько я понимаю, вызов WriteFile не гарантирует что данные окажутся на винте. Мне крайне нежелательно, чтоб программа работала-работала, а потом, бац, встала и ждет когда винт запишет.
S>Можно попробовать решить проблему используя нити и собственный буффер. S>В одной нитке генерируются данные, она же помещает их в буффер. S>Задача другой производить запись данных на диск, а главное вызывать с некотором интервалом flush, не через время, а после записи определённого объема данных.
А почему именно нити? (имеются в виду fibers?) А не потоки? Лично я не могу понять, чем в данном случае использование нитей отличается от однопотоковой работы.
S>вызывать с некотором интервалом flush
Главная проблема: как узнать этот интервал?
Здравствуйте, 7C, Вы писали:
S>>Можно попробовать решить проблему используя нити и собственный буффер. S>>В одной нитке генерируются данные, она же помещает их в буффер. S>>Задача другой производить запись данных на диск, а главное вызывать с некотором интервалом flush, не через время, а после записи определённого объема данных.
7C>А почему именно нити? (имеются в виду fibers?) А не потоки? Лично я не могу понять, чем в данном случае использование нитей отличается от однопотоковой работы.
Нити — threads.
Использование нитей позволит избежать блокировок на WriteFile. Когда 2-я нитка будет висеть на записи на диск, 1-я может выполнять копирование экрана, производить сжатие.
S>>вызывать с некотором интервалом flush 7C>Главная проблема: как узнать этот интервал?
Ммм, не стоит терять времени на его поиск, это всё равно не константа. Достаточно того, что можно самому подсказать OS когда данные нужно сбросить на диск.
Стоит посмотреть опции CreateFile, с их помощью можно вообще отключить буфферизацию.
Здравствуйте, WoldemaR, Вы писали:
WR>Здравствуйте, 7C, Вы писали:
7C>>Здравствуйте, silamantex, Вы писали:
S>>>Какая скорость потока данных? МБ/с? 7C>>Максимально возможная для данного компа. 7C>>Мне нужно выжать всё, что можно выжать. Дело втом, что современные компьютеры слишком слабы для моей программы и я пытаюсь выжать из них все на что они способны. Чтоб не ходить вокруг да около скажу: это программа для захвата экрана компьютера (например, пять раз в секунду) и запись всего этого в видеофайл (avi). Отсюда требование к "ровной" работе программы (у avi ведь framerate — величина постояная). Узкое место в этом: сохранение на винт каждого кадра. Кстати, я не пишу прямо в avi, а программо пакую каждый массив и только после этого записываю на винт — получается быстрее, т.к. пакуется в разы, а меньшее количество данных намного быстрее сохраняется на винт.
WR>Присоединяясь к тому что сказал silamantex, добавлю, что можно добится большего эффекта компрессии кадров, если их паковать некими группами похожих кадров. В крайнем случае можно совместно паковать например, по 5 кадров и записывать каждую секунду.
7С, какие данные могут быть на экране?
Видео? Окна 'обычных' приложений?
В последнем случае модификации экрана очень небольшие.
Вот только переменный bitrate предпочтительнее
Думаю, улучшив алгоритм сжатия можно добиться многого.
Как никак, это только нагрузка на процессор. От пользователя ничего не требуется
Здравствуйте, silamantex, Вы писали:
S>Использование нитей позволит избежать блокировок на WriteFile. Когда 2-я нитка будет висеть на записи на диск, 1-я может выполнять копирование экрана, производить сжатие.
Да я уже пришел к двум потокам.
S>Стоит посмотреть опции CreateFile, с их помощью можно вообще отключить буфферизацию.
Да, я уже нарыл флаги: FILE_FLAG_WRITE_THROUGH и FILE_FLAG_NO_BUFFERING.
S>Удачи!
Спасибо за все!
Здравствуйте, silamantex, Вы писали:
S>7С, какие данные могут быть на экране? S>Видео? Окна 'обычных' приложений? S>В последнем случае модификации экрана очень небольшие. S>Вот только переменный bitrate предпочтительнее
На экране может быть все что угодно (разве оверлеи захватывать пока не умею...). К сожалению, определить хорошо или плохо сожмется изображение определить очень трудно (разве что вести статистику по сжатию предыдущих кадров и по ей регулировать сжатие). Сейчас пользуюсь библиотекой zlib, сжимаю с параметром fastest.
S>Думаю, улучшив алгоритм сжатия можно добиться многого. S>Как никак, это только нагрузка на процессор. От пользователя ничего не требуется
Хуже дело обстоит когда сильно загружен процессор (другими приложениями). Тут уже начинаешь задумываться: ускорит сжатие захват или наоборот...
Кстати, заметил что почти все программы-конкуренты совсем не способны захватывать игры (такие как Counter-Strike). Виснут, либо ругаются, что захват менее 1 кадра в секунду и привет. Но все как один захватывают напрямую в avi, еще и сжимают на ходу указанным в настройках кодеком (моя практика показала, что многие кодеки жмут ужасно медленно).
Здравствуйте, 7C, Вы писали:
7C>Здравствуйте, silamantex, Вы писали:
S>>7С, какие данные могут быть на экране? S>>Видео? Окна 'обычных' приложений? S>>В последнем случае модификации экрана очень небольшие. S>>Вот только переменный bitrate предпочтительнее 7C>На экране может быть все что угодно (разве оверлеи захватывать пока не умею...). К сожалению, определить хорошо или плохо сожмется изображение определить очень трудно (разве что вести статистику по сжатию предыдущих кадров и по ей регулировать сжатие). Сейчас пользуюсь библиотекой zlib, сжимаю с параметром fastest.
Сколько времени занимает сжатие одного экрана, на каком процессоре?
Стоит использовать комбинированный метод: разбивать экран на участки, переупорядочивать данные для сжатия, проводить проверку изменений и сжимать только изменившуюся часть.
Здравствуйте, 7C, Вы писали:
S>>Стоит посмотреть опции CreateFile, с их помощью можно вообще отключить буфферизацию. 7C>Да, я уже нарыл флаги: FILE_FLAG_WRITE_THROUGH и FILE_FLAG_NO_BUFFERING.
Не уверен, что FILE_FLAG_WRITE_THROUGH приведет к увеличению скорости записи. Ведь диск -- медленное устройство, а с этим флагом ты будешь напрямую дергать диск для каждой записи. Лучще поэкспериментируй.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, silamantex, Вы писали:
S>Сколько времени занимает сжатие одного экрана, на каком процессоре?
S>Стоит использовать комбинированный метод: разбивать экран на участки, переупорядочивать данные для сжатия, проводить проверку изменений и сжимать только изменившуюся часть.
О времени. На сжатие всего экрана (1024x768x16 на P4 1500 MHz (на экране окно IE с форумом RSDN )) уходит около 86 мс (меряю через QueryPerformanceCounter). Размер сжимается с 1572864 байт до 46632 байт (нехило?). Записывает на винт это от 15 до 60 мс (все делает пока в одном потоке).
Кстати, эти исследование мне показало, что в данном тесте не винт самое узкое место, а функция GetDIBits (получение самих захваченных битов как массив). 200 мс!!! Не ожидал. Так. Роем здесь...
Насчет анализа. Как можно быстро провести проверку изменений ? Не побайтово же... Или котрольными суммами... Впрочем, есть над чем подумать...
Здравствуйте, 7C, Вы писали:
7C>Здравствуйте, silamantex, Вы писали:
S>>Сколько времени занимает сжатие одного экрана, на каком процессоре?
S>>Стоит использовать комбинированный метод: разбивать экран на участки, переупорядочивать данные для сжатия, проводить проверку изменений и сжимать только изменившуюся часть.
7C>О времени. На сжатие всего экрана (1024x768x16 на P4 1500 MHz (на экране окно IE с форумом RSDN )) уходит около 86 мс (меряю через QueryPerformanceCounter). Размер сжимается с 1572864 байт до 46632 байт (нехило?). Записывает на винт это от 15 до 60 мс (все делает пока в одном потоке).
7C>Кстати, эти исследование мне показало, что в данном тесте не винт самое узкое место, а функция GetDIBits (получение самих захваченных битов как массив). 200 мс!!! Не ожидал. Так. Роем здесь...
7C>Насчет анализа. Как можно быстро провести проверку изменений ? Не побайтово же... Или котрольными суммами... Впрочем, есть над чем подумать...
7C>Thx
Советую задуматься над переделкой способа грабления экрана, т.к чтения из видео памяти любым способом, хоть используя DirectDraw, очень медленная операция. Приходилось решать данную задачу. Могу сказать, что таким способом программа не будет работать многих видоадаптерах, скорость на считывания видеобуфйера может быть и 500mc.
Примерные ориентиры по скорости и сжатию:
При использоваании алгоритма компенсайии вектором перемещения, скорость на такой машине не менне 30 кадров в секунду.
Сжатие зависит от картинки на стандартный USER интерфейс, 1500-3000 байт на кадр. Запись на винт сотвествет объему данных.
Для гарантированной работы такого рода программ необходимо писать Mirror Driver, и собственно в эту сторону советую копать.