为什么系统调用unlink这么慢?
why system call unlink so slow?
#include <unistd.h>
#include <stdio.h>
void dump_log(int size){
char cmd[1024];
snprintf(cmd, sizeof(cmd)/sizeof(cmd[0]), "dd if=/dev/zero of=from.bin bs=1024 count=%d", size);
int ret = system(cmd);
if (ret<0){
perror("system");
}
}
int main(){
const char *filepath = "from.bin";
while(1){
dump_log(1024*100);
sleep(10);
unlink(filepath);
}
return 0;
}
strace -T ./a.out
显示:
unlink("from.bin") = 0 <0.019916>
unlink a file(100M) 花费19ms,unlink一个文件会发生什么?为何这么慢?
系统信息:
linux 3.13.0-57-通用,Ubuntu 14.04.2 LTS,ext4
如果你有一个巨大的文件要 unlink(2) 内核不会解锁 inode 直到所有的块指针都是 return编辑到空闲块列表。您可以通过创建第二个 link 来检查时间差异(这将使 unlink 仅释放您正在删除的 link,而不会释放任何块)。根据规范,释放所有这些块的代码是您的进程(好吧,运行 在内核模式下,而不是用户模式,但是没有保留进程来 return 空闲列表中的块)并且它不会return 直到它释放所有块。
示例:(编辑)
以下代码将说明这一点:
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define D(X) "%s:%d:%s: " X, __FILE__, __LINE__, __func__
int main(int argc, char **argv)
{
int opt, i;
while ((opt = getopt(argc, argv, "")) != EOF) {
switch (opt) {
} /* switch */
} /* while */
argc -= optind; argv += optind;
for (i = 0; i < argc; i++) {
struct timespec now, then;
int res;
res = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
if (res < 0) {
fprintf(stderr,
D("ERROR: %s (errno = %d)\n"),
strerror(errno), errno);
exit(EXIT_FAILURE);
} /* if */
unlink(argv[i]);
res = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &then);
if (res < 0) {
fprintf(stderr, D("ERROR: %s (errno = %d)\n"),
strerror(errno), errno);
exit(EXIT_FAILURE);
} /* if */
then.tv_nsec -= now.tv_nsec;
then.tv_sec -= now.tv_sec;
if (then.tv_nsec < 0) {
then.tv_nsec += 1000000000L;
then.tv_sec--;
} /* if */
printf(D("%s: %d.%09d s. (CPU time)\n"),
argv[i], then.tv_sec, then.tv_nsec);
} /* for */
exit(EXIT_SUCCESS);
} /* main */
然后我用这个命令构建了一个 2Gb 的文件:
$ yes | dd of=pepe bs=1M iflag=fullblock count=2048
然后我对这个文件做了 32 links:
i=0
while [ "$i" -lt 32 ]
do ln pepe pepe$i
i=$(expr $i + 1)
done
然后我运行下面的命令(只显示CPU次):
$ unlink pepe[0-9]* pepe
unlink.c:47:main: pepe0: 0.000074272 s. (CPU time)
unlink.c:47:main: pepe1: 0.000022722 s. (CPU time)
unlink.c:47:main: pepe10: 0.000015034 s. (CPU time)
unlink.c:47:main: pepe11: 0.000013254 s. (CPU time)
unlink.c:47:main: pepe12: 0.000012827 s. (CPU time)
unlink.c:47:main: pepe13: 0.000012462 s. (CPU time)
unlink.c:47:main: pepe14: 0.000012241 s. (CPU time)
unlink.c:47:main: pepe15: 0.000012753 s. (CPU time)
unlink.c:47:main: pepe16: 0.000012517 s. (CPU time)
unlink.c:47:main: pepe17: 0.000012245 s. (CPU time)
unlink.c:47:main: pepe18: 0.000013104 s. (CPU time)
unlink.c:47:main: pepe19: 0.000012491 s. (CPU time)
unlink.c:47:main: pepe2: 0.000012662 s. (CPU time)
unlink.c:47:main: pepe20: 0.000012606 s. (CPU time)
unlink.c:47:main: pepe21: 0.000012803 s. (CPU time)
unlink.c:47:main: pepe22: 0.000012597 s. (CPU time)
unlink.c:47:main: pepe23: 0.000012391 s. (CPU time)
unlink.c:47:main: pepe24: 0.000012582 s. (CPU time)
unlink.c:47:main: pepe25: 0.000012557 s. (CPU time)
unlink.c:47:main: pepe26: 0.000012386 s. (CPU time)
unlink.c:47:main: pepe27: 0.000012261 s. (CPU time)
unlink.c:47:main: pepe28: 0.000012245 s. (CPU time)
unlink.c:47:main: pepe29: 0.000012351 s. (CPU time)
unlink.c:47:main: pepe3: 0.000011940 s. (CPU time)
unlink.c:47:main: pepe30: 0.000013003 s. (CPU time)
unlink.c:47:main: pepe31: 0.000012231 s. (CPU time)
unlink.c:47:main: pepe4: 0.000012777 s. (CPU time)
unlink.c:47:main: pepe5: 0.000012546 s. (CPU time)
unlink.c:47:main: pepe6: 0.000012461 s. (CPU time)
unlink.c:47:main: pepe7: 0.000013129 s. (CPU time)
unlink.c:47:main: pepe8: 0.000012311 s. (CPU time)
unlink.c:47:main: pepe9: 0.000012446 s. (CPU time)
unlink.c:47:main: pepe: 0.195457587 s. (CPU time)
如您所见,除最后一个 link 外,其他所有执行都需要大约 12 微秒,但最后一个几乎是十分之二秒的执行时间。
#include <unistd.h>
#include <stdio.h>
void dump_log(int size){
char cmd[1024];
snprintf(cmd, sizeof(cmd)/sizeof(cmd[0]), "dd if=/dev/zero of=from.bin bs=1024 count=%d", size);
int ret = system(cmd);
if (ret<0){
perror("system");
}
}
int main(){
const char *filepath = "from.bin";
while(1){
dump_log(1024*100);
sleep(10);
unlink(filepath);
}
return 0;
}
strace -T ./a.out
显示:
unlink("from.bin") = 0 <0.019916>
unlink a file(100M) 花费19ms,unlink一个文件会发生什么?为何这么慢?
系统信息: linux 3.13.0-57-通用,Ubuntu 14.04.2 LTS,ext4
如果你有一个巨大的文件要 unlink(2) 内核不会解锁 inode 直到所有的块指针都是 return编辑到空闲块列表。您可以通过创建第二个 link 来检查时间差异(这将使 unlink 仅释放您正在删除的 link,而不会释放任何块)。根据规范,释放所有这些块的代码是您的进程(好吧,运行 在内核模式下,而不是用户模式,但是没有保留进程来 return 空闲列表中的块)并且它不会return 直到它释放所有块。
示例:(编辑)
以下代码将说明这一点:
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define D(X) "%s:%d:%s: " X, __FILE__, __LINE__, __func__
int main(int argc, char **argv)
{
int opt, i;
while ((opt = getopt(argc, argv, "")) != EOF) {
switch (opt) {
} /* switch */
} /* while */
argc -= optind; argv += optind;
for (i = 0; i < argc; i++) {
struct timespec now, then;
int res;
res = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
if (res < 0) {
fprintf(stderr,
D("ERROR: %s (errno = %d)\n"),
strerror(errno), errno);
exit(EXIT_FAILURE);
} /* if */
unlink(argv[i]);
res = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &then);
if (res < 0) {
fprintf(stderr, D("ERROR: %s (errno = %d)\n"),
strerror(errno), errno);
exit(EXIT_FAILURE);
} /* if */
then.tv_nsec -= now.tv_nsec;
then.tv_sec -= now.tv_sec;
if (then.tv_nsec < 0) {
then.tv_nsec += 1000000000L;
then.tv_sec--;
} /* if */
printf(D("%s: %d.%09d s. (CPU time)\n"),
argv[i], then.tv_sec, then.tv_nsec);
} /* for */
exit(EXIT_SUCCESS);
} /* main */
然后我用这个命令构建了一个 2Gb 的文件:
$ yes | dd of=pepe bs=1M iflag=fullblock count=2048
然后我对这个文件做了 32 links:
i=0
while [ "$i" -lt 32 ]
do ln pepe pepe$i
i=$(expr $i + 1)
done
然后我运行下面的命令(只显示CPU次):
$ unlink pepe[0-9]* pepe
unlink.c:47:main: pepe0: 0.000074272 s. (CPU time)
unlink.c:47:main: pepe1: 0.000022722 s. (CPU time)
unlink.c:47:main: pepe10: 0.000015034 s. (CPU time)
unlink.c:47:main: pepe11: 0.000013254 s. (CPU time)
unlink.c:47:main: pepe12: 0.000012827 s. (CPU time)
unlink.c:47:main: pepe13: 0.000012462 s. (CPU time)
unlink.c:47:main: pepe14: 0.000012241 s. (CPU time)
unlink.c:47:main: pepe15: 0.000012753 s. (CPU time)
unlink.c:47:main: pepe16: 0.000012517 s. (CPU time)
unlink.c:47:main: pepe17: 0.000012245 s. (CPU time)
unlink.c:47:main: pepe18: 0.000013104 s. (CPU time)
unlink.c:47:main: pepe19: 0.000012491 s. (CPU time)
unlink.c:47:main: pepe2: 0.000012662 s. (CPU time)
unlink.c:47:main: pepe20: 0.000012606 s. (CPU time)
unlink.c:47:main: pepe21: 0.000012803 s. (CPU time)
unlink.c:47:main: pepe22: 0.000012597 s. (CPU time)
unlink.c:47:main: pepe23: 0.000012391 s. (CPU time)
unlink.c:47:main: pepe24: 0.000012582 s. (CPU time)
unlink.c:47:main: pepe25: 0.000012557 s. (CPU time)
unlink.c:47:main: pepe26: 0.000012386 s. (CPU time)
unlink.c:47:main: pepe27: 0.000012261 s. (CPU time)
unlink.c:47:main: pepe28: 0.000012245 s. (CPU time)
unlink.c:47:main: pepe29: 0.000012351 s. (CPU time)
unlink.c:47:main: pepe3: 0.000011940 s. (CPU time)
unlink.c:47:main: pepe30: 0.000013003 s. (CPU time)
unlink.c:47:main: pepe31: 0.000012231 s. (CPU time)
unlink.c:47:main: pepe4: 0.000012777 s. (CPU time)
unlink.c:47:main: pepe5: 0.000012546 s. (CPU time)
unlink.c:47:main: pepe6: 0.000012461 s. (CPU time)
unlink.c:47:main: pepe7: 0.000013129 s. (CPU time)
unlink.c:47:main: pepe8: 0.000012311 s. (CPU time)
unlink.c:47:main: pepe9: 0.000012446 s. (CPU time)
unlink.c:47:main: pepe: 0.195457587 s. (CPU time)
如您所见,除最后一个 link 外,其他所有执行都需要大约 12 微秒,但最后一个几乎是十分之二秒的执行时间。