Надо ускорить запись 200-300Мб данных в файл, для этого подойдет такое решение:
— в основном потоке данные будут быстро добавляться в очередь, во вспомогательном — медленно писаться на диск,
когда данные заканчиваются, основной поток информирует об этом вспомогательный, но не ждет конца записи.
Есть ли для этого какие-то готовые библиотеки\функции WinAPI ?
Здравствуйте, Abyx, Вы писали:
A>Надо ускорить запись 200-300Мб данных в файл, для этого подойдет такое решение: A>- в основном потоке данные будут быстро добавляться в очередь, во вспомогательном — медленно писаться на диск, A>когда данные заканчиваются, основной поток информирует об этом вспомогательный, но не ждет конца записи.
A>Есть ли для этого какие-то готовые библиотеки\функции WinAPI ?
Наследуем класс там где необходимо иметь параллельный поток с обработкой:
public CObjectQueueImpl<XXX>, где ХХХ — тип данных который будет передаваться в поток.
Переопределяем в классе метод OnQueueNewObject — вызывается из параллельного потока когда в него поступает новый объект.
В вашем случае пишем на диск. Если очередь предполагается очень большой то можно добавить в метод проверку на завершение потока, если не надо ждать пока вся очередь обработается в случае закрытия программы.
Есть недостатки у данного класса, но допиливать уже нет необходимости в тех задачах где он используется у меня.
Здравствуйте, Abyx, Вы писали:
A>Есть ли для этого какие-то готовые библиотеки\функции WinAPI ?
тег [win] в названии темы означает только что меня устроит платформозависимое решение,
но не означает что решение обязательно должно быть на голом WinAPI.
кроме того, в этой задаче мне важнее всего быстродействие добавления данных в основном потоке,
и у меня есть подозрения что любые решения использующие WinAPI будут проигрывать кроссплатформенным решениям не взаимодействующим с ОС.
A>Здравствуйте, Temnikov, Вы писали: T>> m_cs.Lock(); A>... T>> m_cs.Unlock(); T>> SetEvent(m_hPutEvent);
A>есть подозрение что захват критической секции и установка события будут создавать огромный оверхед на добавление данных в очередь.
Прямо таки огромный? Используйте lock-free контейнер, останется оверхед только от вызова события. Хотя можно и от него отказаться, если данные будут доставаться из очереди, постоянно в вечном цикле, только с проверкой завершения потока.
Вы ни слова не сказали какие требования предъявляются.
Re[2]: upd: [win] запись в файл в фоновом потоке
От:
Аноним
Дата:
30.04.11 12:12
Оценка:
A> кроме того, в этой задаче мне важнее всего быстродействие добавления данных в основном потоке,
возьмите наивный локфри стек отсюда http://en.wikipedia.org/wiki/ABA_problem. Для одного производителя и одного потребителя АБА не проявится, кода строк 15 там. Тормозов будет минимум.
Но вообще вместо фразы 'есть подозрения' обычно лучше написать бенчмарк.
A>кроме того, в этой задаче мне важнее всего быстродействие добавления данных в основном потоке, A>и у меня есть подозрения что любые решения использующие WinAPI будут проигрывать кроссплатформенным решениям не взаимодействующим с ОС.
а вот здесь ваша логика в корне ошибочна
Как много веселых ребят, и все делают велосипед...
Re[3]: upd: [win] запись в файл в фоновом потоке
От:
Аноним
Дата:
30.04.11 12:20
Оценка:
Здравствуйте, ononim, Вы писали:
A>>кроме того, в этой задаче мне важнее всего быстродействие добавления данных в основном потоке, A>>и у меня есть подозрения что любые решения использующие WinAPI будут проигрывать кроссплатформенным решениям не взаимодействующим с ОС. O>а вот здесь ваша логика в корне ошибочна
А Вы точно ускоряете там где надо ?
Скорость записи на диск все равно постоянна, и не зависит от разделения логики
программы на сигнальный и пишущий потоки, ну разве что время отклика уменьшается.
Если запись в файл ведется интенсивно и маленькими порциями, то тут лучше
поработать над файловым кэшем, чтобы накапливать записи, а затем время от время
сбрасывать их на диск. Иногда это дает огромный прирост производительности.
И еще тут не зря посоветовали асинхронные операции и порты завершения ввода-вывода — в
Windows вряд ли существуют более эффективные и расширяемые механизмы для подобных задач.
Например, пишущий поток (или пул потоков) может брать поступившие данные, ставить их в
очередь ввода-вывода и сразу же переходить к следующим, не дожидаясь фактического
завершения операции. Работа с файлами асинхронна по своей природе, потому что
ее выполняет жесткий диск, а не процессор.
Могу посоветовать asio из boost — там вроде эти же самые механизмы и используются.
Здравствуйте, Abyx, Вы писали:
A>да, я это читал, только как это применить к моей проблеме?
тогда мне не ясно что вам не ясно. там вполне доходчиво все объясняется
коротко : система взяла на себя функции обслуживать асинхронную запись и вместо создания своих потоков можно воспользоваться уже готовыми механизмами:
while (данные есть)
{
писатель берет порцию данных (например, 100 Кб) и пихает в систему, используя асинхронное API
система берет данные и обязуется их однажды записать на диск.
далее управление передается клиенту и он, не дожидаясь окончания записи, уходит в цикл
}
Здравствуйте, Аноним, Вы писали:
A>>>кроме того, в этой задаче мне важнее всего быстродействие добавления данных в основном потоке, A>>>и у меня есть подозрения что любые решения использующие WinAPI будут проигрывать кроссплатформенным решениям не взаимодействующим с ОС. O>>а вот здесь ваша логика в корне ошибочна
А>нет там логики, есть подозрения
я знаю что генерация данных для записи происходит очень быстро (сотни тактов) и я знаю что функции WinAPI в лучшем случае работают примерно столько же (критические секции — порядка сотни тактов; SetEvent, HeapAlloc — порядка тысячи тактов)
считайте что код, генерирующий данные выглядит так
for(int i = 0; i != 100*1000*1000; ++i)
{
char buf[16];
_itoa(rand(), buf, 16);
write_data(buf, strlen(buf));
}
желательно чтобы время работы write_data было не более 10% от времени работы rand() + itoa()
Здравствуйте, uzhas, Вы писали:
U> писатель берет порцию данных (например, 100 Кб) и пихает в систему, используя асинхронное API
чтобы накопить эти 100 Кб, нужен какой-то код, наверное класс потока, где такой взять?
U>Wait(система все скинула на диск)
а вот этого в основном потоке не должно быть вообще, по условию задачи
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, uzhas, Вы писали:
U>> писатель берет порцию данных (например, 100 Кб) и пихает в систему, используя асинхронное API A>чтобы накопить эти 100 Кб, нужен какой-то код, наверное класс потока, где такой взять?
в программе лишь один поток, второй не нужен, и класс потока вам не нужен
U>>Wait(система все скинула на диск) A>а вот этого в основном потоке не должно быть вообще, по условию задачи
Wait делается в самом-самом конце всей записывающей программы (когда заветные 500Mb будут отправлены на запись и данных для записи больше не будет)
вам нужно внимательнее все прочитать и осмыслить, в том числе документацию на msdn, куда ведут вышеупомянутые ссылки
зы: я даже боюсь вам советовать в boost::io_service из-за странных вопросов
Здравствуйте, uzhas, Вы писали:
A>>чтобы накопить эти 100 Кб, нужен какой-то код, наверное класс потока, где такой взять? U>в программе лишь один поток, второй не нужен, и класс потока вам не нужен
здесь под потоком имелся ввиду "stream"
U>>>Wait(система все скинула на диск) A>>а вот этого в основном потоке не должно быть вообще, по условию задачи U>Wait делается в самом-самом конце всей записывающей программы (когда заветные 500Mb будут отправлены на запись и данных для записи больше не будет)
не понял насчет "записывающей программы" %)
еще раз повторю, поток который выдает данные для записи, окончания записи ждать не должен. по условию задачи.
то что процесс перед завершением должен ждать завершения фоновых потоков — это отдельный вопрос.
U>зы: я даже боюсь вам советовать в boost::io_service из-за странных вопросов
такого нет. есть boost::asio::io_service
Здравствуйте, Abyx, Вы писали:
A>считайте что код, генерирующий данные выглядит так A>
A>for(int i = 0; i != 100*1000*1000; ++i)
A>{
A> char buf[16];
A> _itoa(rand(), buf, 16);
A> write_data(buf, strlen(buf));
A>}
A>
Если так, то здесь налицо проблема маленького буфера.
Никакие алгоритмы и распараллеливания не помогут, если данные пишутся в файл по нескольку
байт за один присест. Тут нужно расширять файловый буфер (хотя бы в виде обертки над WriteFile).
Положительный результат наблюдался неоднократно.
A>еще раз повторю, поток который выдает данные для записи, окончания записи ждать не должен. по условию задачи.
то есть вам важна скорость генерации данных, а не запись их в файл
тогда вам нужна lock-free очередь для переброски данных из главного потока в дополнительный (пишущий)
у вас один писатель в очередь и один потребитель, поэтому задача очень упрощается
покопайте буст\гугл. WinAPI вряд ли вам поможет
Здравствуйте, okman, Вы писали:
O>Тут нужно расширять файловый буфер (хотя бы в виде обертки над WriteFile).
так в этом и есть вопрос — какая штука будет накапливать данные и потом в фоновом потоке писать в файл.