自己写的cp工具

闲来无聊,想自己重写一些Command line tools,于是就先瞄准了cp。
写得也比较简陋,只能复制一个文件,主要是想先看看和系统实现的cp在性能上有多大差距。
写完之后,运行测试,复制同一个1KB文件1000次,复制一个11.5MB文件10次,和复制一个550MB的文件一次。 (文件大小均按1000进制计算)


测试环境及编译优化选项
MacBook Pro 13' Mid 2012
8GB DDR3 1333MHz
120GB SSD
编译器是Apple LLVM 6.0
优化开关-Os
于是还是先贴上测试结果(单位为秒),再附上源代码。

Result

测试项

系统

Mine

1KB (1000)

2.068

2.660

11.5MB (10)

3.027

2.212

550MB (1)

6.293

6.209

下面就附上源代码,肯定还有很多需要改进的地方,比如在复制小文件的时候,明显效率略低。也许应该把default_buf_size的值再改小一点?

Code

//

//  main.c

//  cp

//

//  Created by Ryza 14-7-23.

//  Copyright (c) 2014年 Ryza. All rights reserved.

//

 

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <unistd.h>

#include <sys/stat.h>

#include <sys/fcntl.h>

#include <sys/types.h>

#include <string.h>

 

#define min(x,y)  ( x>y?y:x )

 

int main(int argc, const char * argv[]) {

if (argc != 3) {

        exit(EXIT_FAILURE);

    }else{

struct stat buf;

stat(argv[1], &buf);

if (S_ISDIR(buf.st_mode)) {

            perror("Could't copy dir");

            exit(EXIT_FAILURE);

}

        //先取得文件的类型和存取的权限

int from = open(argv[1], O_RDONLY, S_IROTH);

int to = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, buf.st_mode);

        //保留原来的存取权限

#define default_buf_size 8192 * 4

#define max_buf_size 8192 * 16

        //设置默认和最大缓冲区大小

#define magic_number 88

#define split_size (80 * default_buf_size)

        // 80 is another magic number

long long bufsize = default_buf_size;

if (buf.st_size > split_size) {

bufsize = min(buf.st_size / magic_number,max_buf_size);

}

        //找一个合适的缓冲大小

char *filebuf = (char *)malloc(bufsize);

ssize_t readcount;

while (( readcount = read(from, filebuf, bufsize) ) > 0) {

if (write(to, filebuf, readcount) != readcount) {

                perror("Could't write whole file");

            }

}

//复制文件

memset(filebuf, 0, bufsize);

//清空文件

        free(filebuf);

        exit(EXIT_SUCCESS);

    }

}

后记,将改成了8192之后,复制1KB的文件1000次仍然需要2.632秒,不知道怎么继续优化了。也许要mmap?

Leave a Reply

Your email address will not be published. Required fields are marked *

5 × five =