优化我的read()循环C(两个循环合二为一)
Optimize my read() loop C (two loops in one)
我需要读取文件并将它们存储在mainbuff和mainbuff2中。
我应该只使用系统调用,如open()
, read()
, write()
等
我不想把它们存储在堆栈中,如果它非常大怎么办?堆分配更好。
此代码有效:
...
char charbuf;
char *mainbuff1=malloc(100);
char *mainbuff2=malloc(100);
while (read(file1, &charbuf, 1)!=0)
mainbuff1[len++]=charbuf;
while (read(file2, &charbuf, 1)!=0)
mainbuff2[len2++]=charbuf;
...
但是mainbuff只有100字符。更好的解决方案是在计算文件中的字符后分配mainbuff,如下所示:
...
char charbuf;
while (read(file1, &charbuf, 1)!=0)
len++;
while (read(file2, &charbuf, 1)!=0)
len2++;
char *mainbuff1=malloc(len);
char *mainbuff2=malloc(len2);
...
然后再次重复while
循环并将字节读取到mainbuff中。
但是2个循环(第一个将读取并计数,第二个将读取)对于大文件来说将是低效和缓慢的。需要用一个或其他更有效的方法来完成。请帮助!不知道!
您可以使用fstat
来获取文件大小,而不是读取两次。
#include <sys/stat.h>
int main() {
struct stat sbuf;
int fd = open("filename", O_RDWR);
fstat(fd, &sbuf);
char *buf = malloc(sbuf.st_size + 1);
}
但是,实际上,当 工作太慢时,才需要担心效率。
如果这确实是一个需要优化的地方,那么您真正应该优化的是以下两件事:
- <
- 缓冲区分配/gh>
-
read()
和write()
呼叫数
对于100到1000字节的小缓冲区,没有理由使用malloc()
之类的,只要在堆栈上分配缓冲区,它将是最快的。当然,除非您希望从函数返回指向这些缓冲区的指针,在这种情况下,您可能应该使用malloc()
。否则,你应该考虑使用全局/静态数组,而不是动态分配的数组。
对于I/O调用,使用整个缓冲区大小调用read()
和write()
。不要调用它们来读取或写入单个字节。转换到内核和返回内核是有成本的。
此外,如果您希望在RAM中处理相当大的文件,请考虑使用文件映射。
stat
等允许您获取文件大小。http://linux.die.net/man/2/fstat
或者,如果不能使用,可以使用lseek
http://linux.die.net/man/2/lseek(特别注意返回值)
如果你不能使用它,你可以随时realloc
你的缓冲区。
我把它留给你来实现,因为这显然是一个赋值。div;)
>在优化任何东西之前,您必须配置您的代码。有很多工具可以做到这一点:
- valgrind 英特尔VTune
- AQTime
- AMD CodeAnalyst
定义一个自动直接扩展的数组。这样的
#include <stdio.h>
#include <stdlib.h>
typedef struct dynarray {
size_t size;
size_t capacity;
char *array;
} DynArray;
DynArray *da_make(size_t init_size){
DynArray *da;
if(NULL==(da=(DynArray*)malloc(sizeof(DynArray)))){
perror("memory not enough");
exit(-1);
}
if(NULL==(da->array=(char*)malloc(sizeof(char)*init_size))){
perror("memory not enough");
exit(-1);
}
da->size = 0;
da->capacity=init_size;
return da;
}
void da_add(DynArray *da, char value){
da->array[da->size] = value;
if(++da->size == da->capacity){
da->array=(char*)realloc(da->array, sizeof(char)*(da->capacity += 1024));
if(NULL==da){
perror("memory not enough");
exit(-1);
}
}
}
void da_free(DynArray *da){
free(da->array);
free(da);
}
int main(void) {
DynArray *da;
char charbuf;
int i;
da = da_make(128);
while(read(0, &charbuf, 1)!=0)
da_add(da, charbuf);
for(i=0;i<da->size;++i)
putchar(da->array[i]);
da_free(da);
return 0;
}
为什么需要内存中的所有内容?你可以有读取块,处理,读取下一个块等,
除非你有足够的记忆,否则你不可能把所有的事情都记在脑子里。你的目标是什么?
如果,正如您所说,您只使用系统调用,那么您可以使用整个堆作为缓冲区。
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
size_t sz;
void fix(x){signal(SIGSEGV,fix);sbrk(sz *= 2);}
int main() {
sz = getpagesize();
signal(SIGSEGV,fix);
char *buf = sbrk(sz);
int fd = open("filename", O_RDWR);
read(fd, buf, -1);
}
但是如果你碰巧调用了一个使用malloc的库函数,那就太糟糕了!
brk
和sbrk
函数允许您直接访问malloc使用的堆。但是没有任何malloc的"开销"。没有malloc的特性,像free
, realloc
。sbrk
以字节为单位调用,并返回void *
。brk
使用指针值(即:您只需想象指针存在,并将声明为brk
(某种程度上),并返回void *
。
通过使用brk
或sbrk
来分配内存,它使用了malloc在第一次调用malloc
或realloc
时尝试设置和使用的相同空间。而且许多库函数在底层使用malloc ,所以这段代码有很多可能会出错的地方。这是一个非常奇怪和有趣的领域。
这里的信号处理程序也非常危险。它自动为您提供无限的空间,但当然,如果您遇到任何其他类型的分段冲突,例如解引用null指针,处理程序无法修复它,并且它不会再崩溃。所以这会让程序陷入恶性循环:重新尝试内存访问,分配更多的空间,重新尝试内存访问,分配更多的空间。
- 如何在C++中从两个单独的for循环中添加两个数组
- 如何在for循环中包含两个索引值的测试条件
- 如何使用OpenMP并行这两个循环
- 我可以创建一个包含两个变量的 for 循环,但时间复杂度仍然为 O(n) 吗?
- 嵌套在循环中的两个循环的 big-O 表示法
- 使用一个循环与两个循环
- 如何读取单个字符并在输入两个字符序列时输出? 使用 while 循环和C++
- C++声明双链表,使用两个 for 循环双向遍历列表并打印
- 比较两个字符串后卡在无限循环中
- 如何在循环中打印两个相邻的行,同时在 c++ 中将它们都保留在一行中
- 是否可以在 for 循环中添加两个浮点数?
- 在 for 循环中更新两个变量时遇到问题C++
- SDL GPU 为什么将两个图像分成两个单独的循环更快?
- 当数组位于两个循环之间时,您可以调用数组的 void 函数吗?
- 使用两个 for 循环生成以下星号
- 两个嵌套循环的运行时间复杂性:二次型还是线性
- 比较嵌套 for 循环中的两个 wchar 数组?
- 如何在一个循环中分离两个不同的数组?
- 在 C++ 中使用 OpenMP 并行化两个 for 循环不会提供更好的性能
- 循环两个不同长度的向量时的优化