我正在开发一个关于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来刷新页面,您将看到有时它没有快速响应。 如果有人可以通过我的示例程序重现我的问题,那么可能会有所帮助,并告诉我。
答案 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 男人切片