gpt4 book ai didi

c++ - 文件记录的有效方法

转载 作者:太空宇宙 更新时间:2023-11-04 06:30:50 25 4
gpt4 key购买 nike

我必须在 CSV 文件中记录大量数据,每行有 5 个元素。我使用了一个大缓冲区来存储行,然后在它被填满时使用 fwrite(...) 一次性刷新它并重复直到需要。以下是日志功能的片段:

void logInFile(int a, int b, int c, int d, int e)
{
sprintf(rowInLog,"%d,%d,%d,%d,%d\n",a,b,c,d,e);
int bytesInRow = strlen(rowInLog);
if(bytesInRow + bytesUsedInBuffer <= sizeOfBuffer)
{
strcat(buffer, rowInLog);
bytesUsedInBuffer += bytesInRow;
}
else
{
printf("flushing file to disk\n");
fwrite(buffer, bytesUsedInBuffer, 1, fp);
memset(buffer, 0, sizeOfBuffer);
bytesUsedInBuffer = 0;
strcat(buffer, rowInLog);
bytesUsedInBuffer += bytesInRow;
}
}

但这会使执行速度变慢,这不是因为刷新,因为消息“将文件刷新到磁盘”没有打印在屏幕上。如果不调用此日志记录功能,整个程序会在几分钟内执行,但与此同时,它甚至在 2 小时内也没有完成。还有其他一些根本性的缺陷吗?

最佳答案

我想你的答案就在这里:

if(bytesInRow + bytesUsedInBuffer <= sizeOfBuffer)
{
strcat(buffer, rowInLog); // <--- riiiight here.
bytesUsedInBuffer += bytesInRow;
}

strcat() 函数将扫描整个 buffer 以在您每次调用它时查找结尾。如果 buffer 很大并且几乎已满,那可能会很慢。 buffer 的大小大致为 O(N2)。随着缓冲区大小的增加,性能会迅速下降。这与您想要从缓冲区中得到的几乎相反。 (编辑:您在评论中提到您的缓冲区是 1GB。我希望上面的代码在缓冲区填满时非常、非常慢。)

但是,您已经确切地知道结尾在哪里,以及要复制多少字节。所以改为这样做:

if(bytesInRow + bytesUsedInBuffer <= sizeOfBuffer)
{
memcpy(buffer + bytesUsedInBuffer, rowInLog, bytesInRow + 1);
bytesUsedInBuffer += bytesInRow;
}

请注意,我让 memcpy 复制了一个额外的字节,以便它将 NUL 终止符放在缓冲区上,以防万一你有任何其他 strXXX 函数在 buffer< 上运行。如果不这样做,您可以安全地删除上面的 + 1

您的 else 子句中出现了一个类似但不太严重的错误。您也可以用 memcpy 替换它:

    printf("flushing file to disk\n");
fwrite(buffer, bytesUsedInBuffer, 1, fp);
memcpy(buffer, rowInLog, bytesInRow + 1);
bytesUsedInBuffer = bytesInRow;

您还可以通过组合这些语句来节省一点时间:

sprintf(rowInLog,"%d,%d,%d,%d,%d\n",a,b,c,d,e); 
int bytesInRow = strlen(rowInLog);

sprintf 返回输出字符串的长度,因此您可以简单地说:

int bytesInRow = sprintf(rowInLog,"%d,%d,%d,%d,%d\n",a,b,c,d,e); 

这不是您代码中的主要性能问题,但更改它会进一步改进它。


编辑:一种更好的替代方法:

如果您想完全消除 memcpy(),请考虑以下替代方法:

bytesUsedInBuffer += snprintf( buffer + bytesUsedInBuffer, maximumLineSize, 
"%d,%d,%d,%d,%d\n", a,b,c,d,e );

if (bytesUsedInBuffer >= sizeOfBuffer - maximumLineSize )
{
fwrite(buffer, bytesUsedInBuffer, 1, fp);
bytesUsedInBuffer = 0;
}

maximumLineSize 设置为 5 个整数行的合理值,例如 60。(每个整数 10 个字节,包括符号加上逗号和换行符的 5 个字节是 55,所以 60 是一个不错的值上面的整数。)

关于c++ - 文件记录的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20733385/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com