使用C ++进行大文件读/写的性能问题

时间:2012-12-12 18:14:35

标签: c++ linux qt sockets io

我正在开发一个关于Qt的应用程序。

在此应用程序中,主线程是Web服务器。另一个线程有时从大文件(250mb)读取数据并将它们写入输出文件(~2gb)。

该线程对文件执行高I / O操作,CPU iowait约为70%。

我的问题是,当写入文件时,Web服务器没有快速响应。我所理解的是服务器的qt套接字(在Linux上)由连接到poll或select事件系统的系统套接字表示。所以Qt仅在poll发出事件时才向我的应用程序发送信号。

我认为用文件写入太大的io操作可能会阻止轮询系统,所以我的qt服务器不会收到套接字事件。当线程完成写入数据时,一切都变得正常了。

文件写作如下:

while(dataToRead){
    // context has the list of files to read and current step
    dataToRead = extractData(context, &pBuffer, &sizeBuf);

    fwrite (pBuffer, 1, sizeBuf, pOutFile);

    free(pBuffer);
    pBuffer = NULL;

    // usleep(100000);
}

如果我使用usleep功能添加休息时间,这有助于避免问题,但如果我不使用足够大的睡眠则不完全。但是太大的睡眠会破坏性能,而且我是尽可能快地生成的文件。

我做错了什么?尽可能快地读/写文件是否安全?在上述功能中是否必须进行睡眠?但我们怎么知道好的时间片?

我正在使用英特尔酷睿i5 2500和标准硬盘驱动器的Mint LMDE,Linux 3.2.0 64位。

编辑: 此处提供了一个重现问题的示例程序:https://bugreports.qt-project.org/secure/attachment/30436/TestQtBlocked.zip。需要qt的qmake来编译它。如果你运行它,它将创建一个空的3GB文件,工作线程将在启动时启动,并将在几秒钟内创建该文件。在此期间,如果您尝试连接到http:// localhost:8081 /并且运行多个F5来刷新页面,您将看到有时它没有快速响应。 如果有人可以通过我的示例程序重现我的问题,那么可能会有所帮助,并告诉我。

2 个答案:

答案 0 :(得分:1)

如果您正在使主线程的select调用处于饥饿状态,请创建一个单独的线程来执行文件I / O.当事件来自Qt时,触发某种类型的IPC唤醒你的工作线程来执行大文件I / O并立即从事件处理程序返回。

(这假设异步写入文件对你的程序逻辑有意义。只有你能弄清楚是否属实。)

答案 1 :(得分:0)

来自手册页:       size_t fwrite(const void * ptr,size_t size,size_t nmemb,                      FILE * stream);

你想写sizeBuf,1个元素。

您可能希望使用setvbuf调整缓冲。

setvbuf(pOutfile,NULL,_IONBF,0) - 禁用缓冲。

完整示例: http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frtref%2Fsetvbuf.htm

更好地切换到使用文件descritors,而不是文件流。

使用文件描述符可以使用sendfile和slice。 man sendfile 男人切片