Russian Qt Forum
Ноябрь 10, 2024, 22:49 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Правильное использование многопоточности  (Прочитано 24982 раз)
egorsmkv
Гость
« : Январь 11, 2016, 12:22 »

Задача очень простая - распарсить построчно большой лог.

В языке Go существуют легковесные потоки - Gorutines. С их помощью эта задача выполняется довольно быстро.
Но как это сделать в Qt?

Сейчас я создаю список QFuture и добавляю в него задачи парсинга:
Код:
QString line = "hello";
futureList << QtConcurrent::run(this, &ParserThread::parseLine, line);

При таком подходе всё работает, но для не слишком больших логов. Если дать лог на более чем 1 миллион строк, то программа начинает подвисать из-за того, что задачи добавляются в futureList.

В какую сторону мне смотреть, чтобы, так сказать, плавно их ставить в очередь на парсинг?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Январь 11, 2016, 12:48 »

Необязательно, но вполне возможно Вы столкнулись с типовой проблемой "кластер слишком мал". Попробуйте объединять строки в пачки напр по 100 (или 1000, подберете), и их уже скармливать
Записан
egorsmkv
Гость
« Ответ #2 : Январь 11, 2016, 12:57 »

Да, тоже думал, что машина просто не справляется, но о таком решении не догадался. Сейчас буду тестировать.
Записан
egorsmkv
Гость
« Ответ #3 : Январь 11, 2016, 15:14 »

Потребление памяти значительно снизилось из-за уменьшения создания новых QFuture.
Записан
egorsmkv
Гость
« Ответ #4 : Январь 11, 2016, 15:54 »

И того: проблема осталась - программа подвисает.

Попробую сделать через QThreadPool и QRunnable. По результатам отпишусь.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Январь 11, 2016, 16:39 »

И того: проблема осталась - программа подвисает.

Попробую сделать через QThreadPool и QRunnable. По результатам отпишусь.
Может лучше разобраться почему/где подвисает.
Записан
egorsmkv
Гость
« Ответ #6 : Январь 11, 2016, 19:09 »

У меня после парсинга строки идёт её запись на диск. Уверен, что из-за этого программа начитает подвисать.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Январь 11, 2016, 20:30 »

У меня после парсинга строки идёт её запись на диск. Уверен, что из-за этого программа начитает подвисать.
Порядок строк в выходном файле не важен? Он может отличатся от исходного файла.

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

Или разделить исходный файл на несколько кусков, по количеству рабочих потоков, и отдать каждый кусок своему потоку. А поток уже будет вычитывать строку из своего куска, парсить ее и сохранять результат.
Записан
egorsmkv
Гость
« Ответ #8 : Январь 12, 2016, 03:27 »

Не важен.

Второй вариант больше нравится из-за своей простоты. Попробую его тоже сделать.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #9 : Январь 12, 2016, 10:11 »

И того: проблема осталась - программа подвисает.

Попробую сделать через QThreadPool и QRunnable. По результатам отпишусь.

Футура и есть обертка над QRunnable
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Январь 12, 2016, 12:04 »

У меня после парсинга строки идёт её запись на диск. Уверен, что из-за этого программа начитает подвисать.
Это легко проверить отключив запись. Можно каждой нитке дать свой выходной файл, или использовать мутексы для записи (подход тот же, лочится запись "пачки" строк).
Записан
egorsmkv
Гость
« Ответ #11 : Январь 27, 2016, 17:25 »

Докладываю, как и обещал.

Я ошибался говоря, что подвисание окна происходит из-за активной записи на диск (она происходит в другом потоке). Оказалось всё намного прозаичнее: у меня в программе присутствует прогресс-бар, который обновляется, когда парсинг одной строки завершен. Из-за этого программа и подвисала - из-за частого обновления прогресс-бара.

P.S. также сделал с QtConcurrent запуск/остановку/возобновление/остановку потоков. Вот проект, кому интересно - https://yadi.sk/d/qUh0x_rXnprSV https://yadi.sk/d/US55QXNJnr6am
« Последнее редактирование: Январь 28, 2016, 02:22 от egorsmkv » Записан
fdfsdfgjfh
Гость
« Ответ #12 : Январь 27, 2016, 22:59 »

ссылка битая
Записан
egorsmkv
Гость
« Ответ #13 : Январь 28, 2016, 02:22 »

Исправил
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #14 : Январь 28, 2016, 07:34 »

Исправил

Освойте https://github.com/ / https://bitbucket.org/ -- проще же будет проекты хранить, иметь к ним доступ, тут и знания о контролях версий появятся, а они в it-компаниях всегда используются, да и не нужно будет перезаливать Улыбающийся
Не раз было, что в некоторых статья на хабре можно было встретить, выложенный автором проект на файлообменник, ссылка которого, конечно, давно дохлая
Записан

Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.055 секунд. Запросов: 22.