2013-04-21 129 views
4

我需要讀取文件並將它們存儲在mainbuff和mainbuff2中。優化我的read()循環C(一個循環中的兩個循環)

我應該只使用像系統調用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個字符。更好的方法是這樣的文件計數個字符後的alloc 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個循環(首先會讀取並計數,其次會讀取)對於大型文件來說效率並不高並且很慢。需要在一個或其他更有效的工作中做到這一點。請幫忙!不知道!

+1

優化前的配置文件! – qdii 2013-04-21 09:49:12

+0

你應該考慮到你對'read'的調用結果。你需要處理不同的'-1','0'和'1'可能的結果。你可以在讀取緩衝區的同時增加緩衝區(通過分配一個新緩衝區並複製到舊緩衝區)。順便說一句,如果你想提高效率,你應該一次「讀取」多於一個字節(通常一次讀取幾千字節塊)。 – 2013-04-21 09:49:43

+0

你見過mmap(2)嗎? – 2013-04-21 09:59:01

回答

7

您可以使用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); 
} 

但是,真的,不用擔心效率的時間是工作後太慢。

+0

如果有時我需要從終端(fd = 0)從STDIN讀取它,該怎麼辦? – 2013-04-21 09:38:50

+0

要求用戶提供尺寸。 – 2013-04-21 09:48:56

4

stat et al。允許您獲取文件大小。 http://linux.die.net/man/2/fstat

或者,如果你不能使用,lseekhttp://linux.die.net/man/2/lseek(特別注意的返回值)

如果您不能使用,要麼,你可以隨時realloc您的緩衝區,當您去。

我把它留給你來實現它,因爲這顯然是一項任務。 ;)

+2

如果你使用'realloc()',你可以以對數的方式做到這一點,而不是一次一個字節地擴展緩衝區。 – 2013-04-21 09:29:57

+0

如果有時我需要從終端(fd = 0)從STDIN讀取它,該怎麼辦? – 2013-04-21 09:40:19

+1

@AlexZern那麼你沒有多少選擇,你必須在你去的時候'realloc':因爲stdin是一個流,你不能得到它的大小,也不會回頭。 – syam 2013-04-21 09:42:43

5

如果這確實是在需要優化的地方,那麼你真的應該優化是以下兩點:

  • 緩衝區分配
  • 號碼的呼叫來read()write()

對於100到1000字節的小緩衝區,沒有理由使用malloc()之類的東西,只是在堆棧上分配緩衝區,它將是最快的。當然,除非你想從函數返回指向這些緩衝區的指針,在這種情況下,你可能應該使用malloc()。否則,你應該考慮使用全局/靜態數組,而不是動態分配的數組。

至於I/O調用,調用read()write()整個緩衝區大小。不要調用它們讀取或寫入單個字節。轉向內核和後退確實有成本。此外,如果您希望需要在RAM中處理相當大的文件,請考慮使用文件映射。

0

爲什麼你需要記憶中的一切?你可以有大塊的讀取,處理,讀下一個塊等等,除非你有足夠的內存,否則你不能把所有的東西都放在你的buff裏。你的目標是什麼?

2

優化之前,你必須配置您的代碼。很多工具都可以做到這一點:

  • 的valgrind
  • 英特爾VTune
  • AQTime
  • AMD CodeAnalyst
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的庫函數,Kablooey!

brksbrk函數使您可以直接訪問malloc使用的相同堆。但沒有任何malloc的「開銷」。並且沒有任何malloc的特徵,如free,realloc。以字節爲單位調用sbrk,並返回void *。用指針值調用brk(也就是說,你只需要想象指針存在,並且聲明它以brk的方式),並返回void *

通過使用brksbrk分配內存,它使用相同的空間的malloc將嘗試安裝和使用上的第一次調用mallocrealloc。許多庫函數在底層下使用malloc ,所以這個代碼有很多方法可以打破。這是一個非常奇怪和有趣的領域。

這裏的信號處理程序也是非常危險的。它給你自動無限的空間,但是當然,如​​果遇到任何其他類型的分割違例,例如解引用NULL指針,處理程序無法修復它,並且它不能再崩潰。因此,這可以將程序發送到令人討厭的循環:重試內存訪問,分配更多空間,重試內存訪問,分配更多空間。

+0

您能解釋一下您寫的內容嗎? – 2013-04-21 10:03:12

+0

編輯一些解釋。 – 2013-04-21 10:06:41

+1

我覺得如果你真的不知道自己在做什麼,這會很危險。如果你隨時使用'malloc'相關的函數(甚至是'new'),那麼它會攪亂堆。 – TrueY 2013-04-21 10:12:10

1

定義了一個自動直接擴展的數組。 這樣的

#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; 
}