如何优化C中读取的二进制文件(超过1MB)?

时间:2018-04-22 19:10:46

标签: c file optimization binary low-level

我需要逐字节读取两个1MB +二进制文件,比较它们 - 如果它们不相等,则从不等字节开始打印下16个字节。要求是它只运行5毫秒。目前,如果不等位位于两个文件的末尾,我的程序将花费19毫秒。关于如何优化它,有什么建议吗?

#include <stdio.h>  //printf
#include <unistd.h> //file open
#include <fcntl.h>  //file read
#include <stdlib.h> //exit()
#include <time.h>   //clock

#define SIZE 4096

void compare_binary(int fd1, int fd2)
{   
    int cmpflag = 0;
    int errorbytes = 1;
    char c1[SIZE], c2[SIZE];
    int numberofbytesread = 1;

    while(read(fd1, &c1, SIZE) == SIZE && read(fd2, &c2, SIZE) == SIZE && errorbytes < 17){
        for (int i=0 ; i < SIZE ; i++) {
            if (c1[i] != c2[i] && cmpflag == 0){
                printf("Bytes not matching at offset %d\n",numberofbytesread);
                cmpflag = 1;
            }
            if (cmpflag == 1){
                printf("Byte Output %d: 0x%02x 0x%02x\n", errorbytes, c1[i], c2[i]);
                errorbytes++;
            }
            if (errorbytes > 16){
                break;
            }
            numberofbytesread++;
        }
    }
}

int main(int argc, char *argv[])
{
    int fd[2];
    if (argc < 3){
        printf("Check the number of arguments passed.\n");
        printf("Usage: ./compare_binary <binaryfile1> <binaryfile2>\n");
        exit(0);
    }
    if (!((access(argv[1], F_OK) == 0) && (access(argv[2], F_OK) == 0))){
        printf("Please check if the files passed in the argument exist.\n");
        exit(0);
    }

    fd[0] = open(argv[1], O_RDONLY);
    fd[1] = open(argv[2], O_RDONLY);

    if (fd[0]< 0 && fd[1] < 0){
        printf("Can't open file.\n");
        exit(0);
    }
    clock_t t;
    t = clock();
    compare_binary(fd[0], fd[1]);
    t = clock() - t;
    double time_taken = ((double)t)/(CLOCKS_PER_SEC/1000);
    printf("compare_binary took %f milliseconds to execute \n", time_taken);
}

基本上需要优化的方式来读取超过1MB的二进制文件,这样它们可以在5毫秒内完成。

2 个答案:

答案 0 :(得分:3)

首先,尝试阅读更大的块。当你可以一次阅读所有内容时,执行如此多的读取调用毫无意义。现在使用2 MB的内存并不是一件好事。磁盘I / O调用本身就很昂贵,它们的开销也很大,但可以减少。

其次,尝试在每次迭代中比较整数(甚至64位长)而不是字节,这样可以显着减少需要执行的循环次数。一旦找到错配,您仍然可以切换到每字节字节的实现。 (当然,如果文件长度不是4或8的倍数,则需要一些额外的技巧)。

答案 1 :(得分:0)

首先引起我注意的是这个

 if (cmpflag == 1){
            printf("Byte Output %d: 0x%02x 0x%02x\n", errorbytes, c1[i], c2[i]);
            errorbytes++;
        }
        if (errorbytes > 16){
            break;
        }

你的cmpflag检查没用,也许这件事做了一点点的反思

  if (c1[i] != c2[i] && cmpflag == 0){
            printf("Bytes not matching at offset %d\n",numberofbytesread);
            printf("Byte Output %d: 0x%02x 0x%02x\n", errorbytes, c1[i], c2[i]);
            errorbytes++;
            if (errorbytes > 16){
                break;
            }
        }

你可以做内置函数的数组比较,或者增加你的缓冲区