linux - fork 似乎在不必要时复制
问题描述
我正在尝试 CoW fork
(有关更详细的背景,请参阅编辑,这可能完全不相关)
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#define N 262144
struct {
int n;
int padding[1023];
} arr[N];
int main() {
int i, sp = 0, t, tx = clock();
for (i=0; i<N; ++i) arr[i].n = i;
printf ("Init Time: %d\n", clock()-tx);
#if 1
sp = fork();
if(!sp) _exit(0);
waitpid(sp, &sp, 0);
#endif
// 5045 without fork
// 104192 with fork
t = clock();
for (i=0; i<N; ++i) arr[i].n = -i;
printf ("Runner %d Time: %d\n", sp, clock() - t);
getchar();
return 0;
}
这fork
使以后的内存访问变慢。
fork
复制会变慢吗?如果是这样,为什么?我在 Ubuntu 20.04.3 LTS 上运行
解决方案
尝试在下面运行它/usr/bin/time -v
并观察 Minor (reclaiming a frame) page faults:
线路。
即使孩子立即退出,叉子也会使其翻倍。
增加的时间似乎完全是由于这些页面错误。
据推测,在分叉时,内核在写入时将页面设置为错误,以期需要复制。如果在这样的页面错误时孩子已经死了,则复制的需要被取消(该页面不再与任何人共享,因此无需费心复制它),但您仍然需要为页面错误命中付费。
现在,如果您让孩子保持活动状态,那么页面错误处理程序也应该需要进行复制,实际上,保持孩子活动会增加循环持续时间几次。那应该是完整的写时复制。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#define N 262144
struct {
int n;
int padding[1023];
} arr[N];
int main() {
int i, t, tx = clock();
pid_t sp=0;
for (i=0; i<N; ++i) arr[i].n = i;
printf ("Init Time: %ld\n", clock()-tx);
#if 1
if(0>(sp = fork())) return 1;
enum { KEEP_THE_KID_EH = 1 };
if(!sp){ if(KEEP_THE_KID_EH){ for(;;) pause(); } exit(0); }
#endif
t = clock();
for (i=0; i<N; ++i) arr[i].n = -i;
printf ("Runner %ld Time: %ld\n", (long)sp, clock() - t);
/*getchar();*/
if(sp) kill(sp,SIGTERM);
return 0;
}
我的时间是:
7371 without fork
189073 with fork
1092145 with fork and the kid kept
推荐阅读
- python - tkinter create_image 不打印
- flutter - 从一个屏幕调用小部件时出错,而从另一个屏幕调用相同的小部件时没有错误
- python - matplotlib barh:如何在两组条形之间制作视觉差距?
- java - Socket Net Exception - 我想与 mer 服务器同时接收对象和数组列表
- flutter - Flutter:对象作为listview的一个元素
- shell - 如何根据某些条件使用 shell 脚本从文本文件中删除几行数据
- oauth-2.0 - 标头管理器缺少授权不记名令牌
- github - Travis-CI 不会构建新的 GitHub 存储库
- java - 从另一个 JSP 提交表单时,JSP DAO 未在 JSP 中获取对象
- fork - 你如何在不改变标准输入缓冲的情况下 fork-then-execve?