【问题标题】:Very slow to execute system command执行系统命令很慢
【发布时间】:2011-06-17 07:55:39
【问题描述】:

我有一个 C++ 程序,可以长时间连续记录大量数据到磁盘。因此,我有一个线程来监视可用的磁盘空间,一旦达到一定百分比就会做一些事情。

这是在双四核 x64 CentOS 系统上进行的,并且记录发生在直接连接的 SATA 磁盘上,这些磁盘仅用于使用 ext3 文件系统进行记录。我通过使用system() 发出“df”命令并读取结果来监控磁盘使用情况。

昨晚运行它时,我在日志文件中注意到它花了 整整 39 分钟来运行命令来查找磁盘使用情况。

处理超时的代码是这样的:

int DiskSpaceMonitor::handle_timeout(const ACE_Time_Value& time_, const void* pFunc_)
{
    LOG4CXX_TRACE(m_logger, "DiskSpaceMonitor timer fired");

    ACE_UINT8 usagePercent = m_diskChecker.getDiskSpaceUsagePercentage(m_monitoredDisk);

    m_fileRecorder->notifyDiskUsage(usagePercent);

    return 0;
} 

调用执行“df”的函数:

ACE_UINT8 DiskSpaceChecker::getDiskSpaceUsagePercentage(std::string diskMountPoint)
{
    std::stringstream usageCommand;
    usageCommand << "df -PH " << diskMountPoint << " | grep -v \"^Filesystem\" | awk '{print $5}' | cut -d'%' -f1 > " << m_mountSpaceFile;
    system(usageCommand.str().c_str());

    std::ifstream inFile(m_mountSpaceFile.c_str(), std::ios::in);
    if (!inFile)
    {
        return 0;
    }

    std::string usageStr;
    inFile >> usageStr;
    int usage = atoi(usageStr.c_str());

    inFile.close();

    std::stringstream rmCmd;
    rmCmd << "rm " << m_mountSpaceFile;
    system(rmCmd.str().c_str());

    LOG4CXX_DEBUG(m_logger, "Disk usage for disk: " << diskMountPoint << " = " << usage << "%");

    return  usage;
}

因此,handle_timeout() 中的跟踪记录语句和getDiskSpaceUsagePercentage() 中的调试跟踪语句之间花费了 39 分钟。但是延迟确实在inFile &gt;&gt; usageStr; 之前出现(因为我可以看到读取百分比高于预期 - 它应该上升 1% 或更少,但它跃升超过 16%)。

为什么运行命令和读取命令的处理要花费如此大量的时间?

现在我承认磁盘在被写入时确实会受到一些冲击,但只有一个程序在写入它们,而且它只写入一个数据文件和一个索引文件。所以我不明白这需要这么长时间。

作为替代方案,是否有一种简单的方法可以调用 system() 函数并在超时时间过长时让它返回?

【问题讨论】:

  • 我不确定,但是getrusage 可以选择吗?
  • 在这个缓慢的响应过程中知道 iowait 状态是什么样子会很有趣。

标签: c++ performance file-io system


【解决方案1】:

使用system 的替代方法是特定于操作系统的API 调用,例如statvfs

但我同意花这么长时间很奇怪。你能重现这个吗?

【讨论】:

  • 谢谢,我会试试 statvfs。我的测试运行了几个小时,我只见过一次,所以重新创建它并不容易。但我会尝试这样做。
【解决方案2】:

当安装了一些 NFS fs 但客户端无法访问服务器时,我看到“df”挂起。那么您是否安装了任何网络 fs?

无论如何,正如其他人已经指出的那样,您应该使用 statvfs()/fstatvfs() 而不是 system()。如果挂起的 fs 不是您要在其上运行 statvfs() 的那个,这也可能有助于挂起。

【讨论】:

  • 服务器挂载了 NFS 挂载,但在此录制过程中或 df 命令中未使用它们。也许如果他们变坏了,df 确实会挂断。我会试一试 statvfs() 看看这是否会有所改善。干杯。
  • 是的,如果挂起任何挂载的 fs,df 就会挂起,因为 df 本质上所做的是它为每个挂载的 fs 运行 statvfs()。
【解决方案3】:

也许您可以尝试使用fstatvfs()/statvfs() 系统调用来获取可用磁盘空间量,看看是否有什么不同。

【讨论】:

    猜你喜欢
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2011-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多