2012-06-09 26 views
2

我有我的多線程應用程序的問題。當一個線程執行同步popen()命令時 - 其他應用程序線程顯着減慢。用popen()執行ffmpeg,產生高負載。POPEN管減慢其他線程

通常情況下,其它線程執行時間爲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'的線程?這個「管道」代碼只用於一個線程......你可以添加一些代碼示例如何解決這個問題? – abrahab

+0

這個問題看起來是你正在尋求解決的確切問題:http://stackoverflow.com/q/149860/282531。 – Specksynder

+0

爲什麼fgets()會阻止當前線程以外的線程?這確實是一個阻塞呼叫,但只適用於當前線程,對嗎? – Brady

2

有什麼不同的線程之間的關係?如果它們互相依賴,意味着它們來回發送數據,那麼如果一個線程變慢,那麼其他線程就會有意義。

別的東西要考慮的是正在執行ffmpeg線程如何影響系統的其餘部分。例如,如果其單核CPU和該特定線程產生較高的CPU負載,那麼對於其餘線程而言,這會留下較少的週期,從而減慢它們的速度。當然,從0.0007毫秒到14-20秒的變化確實是極端的!

是否有在線程之間共享的任何其他資源(標準輸入,互斥,等等),高負載線程可能會濫用(保持/鎖定太長),從而導致飢餓其他線程?

此外,我建議分析應用程序(或至少一些線程),看看它爲什麼這麼慢得多。我幾乎肯定你會發現一些線程被阻塞,等待一個公共資源,比如互斥體或類似的東西。

如果這是Linux,這裏有2度堆棧溢出的問題,可以幫助:

+0

感謝您的回答,是的,首先我想這個問題是互斥的,但我爲測試目的的代碼更改,這裏是4名工人+ 1個主線程只接受一個互斥體()連接和管理人員查詢。而其他使用管道和'ffmpeg'的線程不使用它。問題仍然存在......(2核CPU,不太好,但不是那麼糟糕)。 – abrahab

+0

當ffmpeg正在工作時,空閒接近0-10%,但其他應用程序如nginx,apach和mysql不會減慢。是的,看來問題不在'fgets',我把它改寫爲非阻塞和它沒有幫助:(http://stackoverflow.com/questions/10962044/correct-code-non-blocking-pipe-with-popen新POPEN調用的代碼.. – abrahab

+1

@abrahab,好吧,那麼我認爲你能做的最好的事情是配置文件中的應用程序,看看這些線程在做什麼。在我的回答中引用這個問題有幾個很好的選擇這樣做。 – Brady