2012-06-09 3 views
2

У меня проблема с моим многопоточным приложением. Когда в одном потоке выполняется синхронная команда popen() - другие приложения сильно замедляются. Поток с popen() выполнить ffmpeg, который генерирует высокую нагрузку.popen pipe замедляет другие темы

Обычно время выполнения других потоков составляет 0,0007 мс. И когда используется popen, некоторые потоки увеличивают время выполнения до 14-20 секунд.

Как решить эту проблему?

Система FreeBSD 6,4

FILE *pipe; 
    char buff[512]; 
    if (!(pipe = popen(command.c_str(), "r"))) 
    { // if pipe is NULL 
     return false; 
    } 

    while (fgets(buff, sizeof(buff), pipe) != NULL) 
    { 
     ptr_output->append(buff); 
    } 

здесь новый код POPEN может это не поможет: Correct Code - Non-blocking pipe with popen

ответ

2

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

+0

вау, спасибо, вы уверены, что блокирование читать 'fgets' все потоки ждут, а не только поток, который сделал вызов 'fgets'? этот код 'pipe' используется только в одном потоке ... можете ли вы добавить примеры кода, как это решить? – abrahab

+0

Этот вопрос будет представлять собой точную проблему, которую вы ищете для решения: http://stackoverflow.com/q/149860/282531. – Specksynder

+0

Почему fgets() блокирует потоки, отличные от текущего? Это действительно блокирующий вызов, но только для текущего потока, правильно? – Brady

2

Какая связь между различными потоками? Если они зависят друг от друга, то есть они отправляют данные назад и вперед, тогда, если один поток идет медленнее, имеет смысл, что другие будут также.

Что-то еще, чтобы рассмотреть, как поток, выполняющий ffmpeg, влияет на остальную часть системы. Например, если его одноядерный процессор и этот конкретный поток генерируют высокую нагрузку на процессор, то это оставит меньше циклов для остальных потоков, что замедлит их. Конечно, изменение от 0,0007 мсек до 14-20 секунд действительно экстремально!

Есть ли другие ресурсы, совместно используемые (stdin, mutexes и т. Д.) Между потоками, которые могут быть использованы в потоке с высокой нагрузкой (слишком длинный/слишком длинный), что вызывает голод для других потоков?

Кроме того, я бы предложил профилировать приложение (или, по крайней мере, некоторые из потоков), чтобы понять, почему он намного медленнее. Im почти уверен, что вы узнаете, что некоторые потоки заблокированы в ожидании общего ресурса, например мьютекса или чего-то подобного.

Если это линукс, вот 2 Stack Overflow вопросы, которые могут помочь:

+0

Спасибо за ответ, да, в первую очередь, я думаю, что проблема связана с мьютексами, но я сделал изменения кода для целей тестирования, и вот только один мьютекс для 4 рабочих + 1 основной поток, которые принимают() подключения и управляют запросом для рабочих , И другая нить с трубкой и 'ffmpeg' не использует ее. И проблема все еще там ... (2-ядерный процессор, не очень хороший, но не очень плохой). – abrahab

+0

idle около 0-10%, когда ffmpeg работает, но другие приложения, такие как nginx, apach и mysql, не замедляются. и да, похоже, проблема не в 'fgets', я переписываю ее как NONBLOCKING, а ее не помогает :(http://stackoverflow.com/questions/10962044/correct-code-non-blocking-pipe-with-popen new код popen call .. – abrahab

+1

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