【问题标题】:popen pipe slows down other threadspopen 管道减慢其他线程
【发布时间】:2012-06-13 04:59:40
【问题描述】:

我的多线程应用程序有问题。当在一个线程执行同步popen() 命令时 - 其他应用程序线程显着减慢。带有popen() 的线程执行ffmpeg,会产生高负载。

正常情况下,其他线程执行时间为 0.0007 ms。而当使用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 can 的新代码,但无济于事:Correct Code - Non-blocking pipe with popen

【问题讨论】:

    标签: c++ multithreading pthreads popen


    【解决方案1】:

    fgets 是一个阻塞读取,所以当上面的线程等待从管道读取数据时,其他线程被阻塞。在发出读取之前,您将希望将 select/poll for 与文件描述符一起使用以查看管道上是否有数据。这样,您可以抢占该线程,并让其他线程运行以做有用的工作。

    【讨论】:

    • 哇,谢谢,你确定fgets 阻塞读取时所有线程都在等待,而不仅仅是调用fgets 的线程?这个pipe 代码只在一个线程中使用...你能添加一些代码示例如何解决这个问题吗?
    • 这个问题看起来正是您要解决的问题:stackoverflow.com/q/149860/282531
    • 为什么 fgets() 会阻塞当前线程以外的线程?确实是阻塞调用,但只针对当前线程,对吧?
    • @Brady 我也在等待答案,但似乎是它的 IO 调用,并且与系统行为有关。
    【解决方案2】:

    不同线程之间的关系是什么?如果它们相互依赖,这意味着它们来回发送数据,那么如果一个线程变慢,那么其他线程也会变慢是有道理的。

    另外需要考虑的是正在执行ffmpeg 的线程如何影响系统的其余部分。例如,如果它是一个单核 CPU 并且该特定线程正在产生高 CPU 负载,那么这将为其余线程留下更少的周期,从而减慢它们的速度。当然,从 0.0007 毫秒到 14 - 20 秒的变化确实是极端的!

    高负载线程可能滥用(持有/锁定时间过长)的线程之间是否有任何其他资源共享(stdin、互斥锁等),从而导致其他线程的饥饿?

    此外,我建议对应用程序(或至少一些线程)进行分析,以了解它为什么慢得多。我几乎肯定你会发现一些线程被阻塞等待一个公共资源,比如互斥锁或类似的东西。

    如果这是 linux,这里有 2 个 Stack Overflow 问题可能会有所帮助:

    【讨论】:

    • 谢谢你的回答,是的,首先我猜这个问题出在互斥体上,但我为了测试目的做了代码更改,这里只有一个互斥体供 4 个工作人员 + 1 个主线程接受( ) 连接和管理工作人员的查询。而其他带有管道和ffmpeg 的线程不使用它。而且问题仍然存在……(2核cpu,不太好,但也不错)。
    • idle 在 ffmpeg 工作时接近 0-10%,但 nginx、apach 和 mysql 等其他应用程序并没有减慢速度。是的,似乎问题不在于fgets,我将其重写为NONBLOCKING,它没有帮助:(stackoverflow.com/questions/10962044/… popen 调用的新代码..
    • @abrahab,好的,那么我认为你能做的最好的事情就是分析应用程序并查看这些线程在做什么。我的回答中提到的那个问题有几个很好的选择。
    • 从“How to profile pthread mutex in linux”这个问题中尝试使用 valgrind drd 工具。 ffmpeg 线程从哪里读取?
    • @abrahab,为什么线程会在pthread_testcancel()?你是这么叫的吗?如果是这样,为什么?关于 Shiny 分析器等,您可以考虑将分析信息转储到文件中。
    猜你喜欢
    • 2020-06-16
    • 2013-06-22
    • 2021-09-28
    • 2016-11-23
    • 2021-03-27
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多