我正在编写一个程序,其中性能非常重要,但并不重要。目前我正在FILE*
逐行阅读文本,并fgets
用于获取每一行。在使用了一些性能工具之后,我发现我的应用程序有 20% 到 30% 的时间在运行,它在fgets
.
有没有更快的方法来获取一行文本?我的应用程序是单线程的,无意使用多个线程。输入可以来自标准输入或文件。提前致谢。
我正在编写一个程序,其中性能非常重要,但并不重要。目前我正在FILE*
逐行阅读文本,并fgets
用于获取每一行。在使用了一些性能工具之后,我发现我的应用程序有 20% 到 30% 的时间在运行,它在fgets
.
有没有更快的方法来获取一行文本?我的应用程序是单线程的,无意使用多个线程。输入可以来自标准输入或文件。提前致谢。
你没有说你在哪个平台上,但如果它是类 UNIX,那么你可能想尝试 read() 系统调用,它不会执行 fgets() 等人所做的额外缓冲层。这可能会稍微加快速度,另一方面它可能会减慢速度 - 找出答案的唯一方法是尝试并查看。
使用 fgets_unlocked(),但先仔细阅读它的作用
使用 fgetc() 或 fgetc_unlocked() 而不是 fgets() 获取数据。使用 fgets(),您的数据被复制到内存中两次,首先由 C 运行时库从文件复制到内部缓冲区(流 I/O 被缓冲),然后从该内部缓冲区复制到程序中的数组
一口气将整个文件读入缓冲区。
处理该缓冲区中的行。
这是最快的解决方案。
您可以尝试通过将大量数据读入 RAM 然后进行处理,从而最大限度地减少从磁盘读取的时间。从磁盘读取速度很慢,因此通过读取(理想情况下)整个文件一次,然后处理它来最大限度地减少您花费的时间。
类似于 CPU 缓存最小化 CPU 实际返回 RAM 的时间的方式,您可以使用 RAM 来最小化实际进入磁盘的次数。
如果数据来自磁盘,您可能会受到 IO 限制。
如果是这种情况,请获得更快的磁盘(但首先检查您是否充分利用了现有磁盘......某些 Linux 发行版没有优化开箱即用的磁盘访问(hdparm
)),将数据暂存到提前内存(比如将其复制到 RAM 磁盘),或者准备等待。
如果您不受 IO 限制,则可能会浪费大量时间进行复制。您可以从所谓的零拷贝方法中受益。像内存这样的东西映射文件并且只能通过指针访问它。
这有点超出我的专业知识,所以你应该做一些阅读或等待更多知识渊博的帮助。
顺便说一句——你可能会投入比问题价值更多的工作;也许更快的机器会解决你所有的问题......
NB-- 尚不清楚您是否可以对标准输入进行内存映射...
根据您的环境,使用 setvbuf() 来增加文件流使用的内部缓冲区的大小可能会也可能不会提高性能。
这是语法 -
setvbuf (InputFile, NULL, _IOFBF, BUFFER_SIZE);
其中 InputFile 是刚刚使用 fopen() 打开的文件的 FILE*,而 BUFFER_SIZE 是缓冲区的大小(由此调用为您分配)。
您可以尝试各种缓冲区大小,看看是否有积极影响。请注意,这完全是可选的,您的运行时可能对这个调用完全没有任何作用。
如果操作系统支持,你可以尝试异步文件读取,即在 CPU 忙于做其他事情的同时将文件读入内存。所以,代码是这样的:
start asynchronous read
loop:
wait for asynchronous read to complete
if end of file goto exit
start asynchronous read
do stuff with data read from file
goto loop
exit:
如果您有多个 CPU,则一个 CPU 读取文件并将数据解析为行,另一个 CPU 获取每一行并处理它。