2015-04-16 17 views
5

Tôi thừa hưởng đoạn mã sau:bộ nhớ bản sao hiệu quả

void *buf1 = calloc(1,total_buf_size); 
//build buf1 up with memcpy 
int index; 
void *buf2 = buf1; 

for (index = 0; index < log->numentries; index++) 
{ 
    logentry_t *entry = (logentry_t*)&log->entries[index]; 

    memcpy(buf2,entry->entryname,sizeof(entry->entryname)); 
    buf2 = buf2 + (int)sizeof(entry->entryname); 
    memcpy(buf2,&entry->entrysize,sizeof(entry->entrysize)); 
    buf2 = buf2 + (int)sizeof(entry->entrysize); 
    memcpy(buf2,&entry->updatesize,sizeof(entry->updatesize)); 
    buf2 = buf2 + (int)sizeof(entry->updatesize); 
    memcpy(buf2,&entry->numupdates,sizeof(entry->numupdates)); 
    buf2 = buf2 + (int)sizeof(entry->numupdates); 

    int j; 
    for (j = 0; j < entry->numupdates; j++) 
    { 
    memcpy(buf2,&entry->offsets[j],sizeof(entry->offsets[j])); 
    buf2 = buf2 + (int)sizeof(entry->offsets[j]); 
    } 

    int k; 
    for (k = 0; k < entry->numupdates; k++) 
    { 
    memcpy(buf2,&entry->sizes[k],sizeof(entry->sizes[k])); 
    buf2 = buf2 + (int)sizeof(entry->sizes[k]);  
    } 


    memcpy(buf2,entry->data,entry->updatesize); 
} 

Tôi có một nhật ký giao dịch mà tôi đang lặp lại qua và cần phải viết các dữ liệu cho mỗi mục đăng nhập vào một dòng trong một tập tin. Hiện nay nó đang sử dụng memcpy để xây dựng một bộ đệm của tất cả các mục và viết tất cả cùng một lúc vào tập tin. Có cách nào tốt hơn để sao chép và mở rộng bộ nhớ vào buf2?

+0

Văn bản có phải là văn bản không? Bạn có thể 'fprintf' một dòng cho mỗi mục nhập nhật ký? –

+0

nhập-> dữ liệu là một khoảng trống, vì vậy tôi không thể đảm bảo nó sẽ là một chuỗi, mặc dù trong trường hợp này, tôi nghĩ rằng sẽ làm việc. Cám ơn vì sự gợi ý. – dhysong

+1

Tôi nghĩ rằng bất kỳ loại sao chép nào cũng đủ hiệu quả để ghi nhật ký trên đĩa. Nếu bạn đang nói về khả năng đọc mã, thì có một số phòng để cải thiện. Ngoài ra, ngay cả khi nó không phải là văn bản (và nó có vẻ là không), bạn có thể không thu thập các bộ đệm mình, nhưng để cho 'fwrite()' làm đệm công việc cho bạn. – user3125367

Trả lời

0

Tôi không chắc chắn chính xác loại tìm kiếm hiệu quả của bạn nhưng đây là ví dụ về cách viết từng bản ghi mục nhập nhật ký vào tệp và sau đó đặt lại bộ đệm buf2 cho mỗi lần lặp. do đó bạn có thể giảm kích thước buf1 (được định nghĩa bởi total_buf_size) để cái gì đó sẽ phù hợp chỉ là một bản ghi kỷ lục nhập:

void *buf1 = calloc(1,total_buf_size); 
//With this method total_buf_size can be reduced to fit just one log entry record 

//build buf1 up with memcpy 
int index; 
void *buf2 = buf1; 

FILE * pFile; 
pFile = fopen ("myfile.txt","w"); 

for (index = 0; index < log->numentries; index++) 
{ 
    logentry_t *entry = (logentry_t*)&log->entries[index]; 

    memcpy(buf2,entry->entryname,sizeof(entry->entryname)); 
    buf2 = buf2 + (int)sizeof(entry->entryname); 
    memcpy(buf2,&entry->entrysize,sizeof(entry->entrysize)); 
    buf2 = buf2 + (int)sizeof(entry->entrysize); 
    memcpy(buf2,&entry->updatesize,sizeof(entry->updatesize)); 
    buf2 = buf2 + (int)sizeof(entry->updatesize); 
    memcpy(buf2,&entry->numupdates,sizeof(entry->numupdates)); 
    buf2 = buf2 + (int)sizeof(entry->numupdates); 

    int j; 
    for (j = 0; j < entry->numupdates; j++) 
    { 
    memcpy(buf2,&entry->offsets[j],sizeof(entry->offsets[j])); 
    buf2 = buf2 + (int)sizeof(entry->offsets[j]); 
    } 

    int k; 
    for (k = 0; k < entry->numupdates; k++) 
    { 
    memcpy(buf2,&entry->sizes[k],sizeof(entry->sizes[k])); 
    buf2 = buf2 + (int)sizeof(entry->sizes[k]);  
    } 


    memcpy(buf2,entry->data,entry->updatesize); 

    fwrite(buf2, sizeof(logentry_t), sizeof(buf2), pFile); 

    memset(&buf2, 0, sizeof(buf2)); //clear it out 
    buf2 = buf1; //reset the pointer 
} 

fclose(pFile); 
free(buf2); 
+0

Bất cứ khi nào bạn đưa đĩa I/O vào một hoạt động bộ nhớ, bạn đã làm chậm nó xuống theo thứ tự độ lớn. Điều đó rất có thể là lý do để thu thập bộ đệm trong bộ nhớ và tạo thành một bản ghi duy nhất để bắt đầu. –

+0

@ DavidC.Rankin OTOH stdio của BUFSIZ có nghĩa là để được điều chỉnh tốt và syscall hình phạt nên được nhỏ khi thực hiện chỉ một lần cho mỗi BUFSIZ số byte.Bạn * có * để 'viết' chúng tại một thời gian anyway và nếu nó không syscall-per-byte, bạn đang sử dụng tốt. Nếu OP muốn thực hiện điều đó rất nhanh, anh ta nên cân nhắc sử dụng loại hàng đợi không đồng bộ. – user3125367

0

Trong nhận xét của tôi bên dưới câu hỏi Tôi có nghĩa là một cái gì đó như:

FILE *file = fopen("log.file", "a"); // assert(file != NULL); 

for (int i = 0; i < log->numentries, i++) { 
    logentry_t *e = (logentry_t*)&log->entries[i]; 

#define OUT(x) do { fwrite(x, sizeof(x), 1, file) } while (0) 
    OUT(e->entryname); 
    OUT(e->entrysize); 
    OUT(e->updatesize); 
    OUT(e->numupdates); 

    for (int j = 0; j < e->numupdates; j++) 
     OUT(&e->offsets[j]); 

    for (int k = 0; k < e->numupdates; k++) 
     OUT(&entry->sizes[k]); 

    fwrite(e->data, e->updatesize, 1, file); 
#undef OUT 
} 
fflush(file); 

... 

Tức là bạn không cần bufs chút nào vì fwrite đã thực hiện bộ đệm tại lớp stdio.h. Mã này không được kiểm tra và có thể chứa bất kỳ lỗi nào. Cũng cần lưu ý rằng việc ghi dữ liệu thô vào tệp nhật ký có thể dẫn đến các vấn đề kích thước nhỏ hoặc lớn trên các nền tảng khác nhau hoặc thậm chí là trình biên dịch (mặc dù sau này ít có khả năng hơn, tùy thuộc vào loại trường logentry_t thực tế). Bạn có thể xem xét các trường dữ liệu số nguyên định dạng trước đến biểu diễn kích thước cố định di động qua một số thứ như htons/htonl hoặc thậm chí printf("%ld", (long)x) chúng dưới dạng văn bản.

Các vấn đề liên quan