English README: README.en.md
让任意程序整体放慢运行:程序内部一切照常运转、最终照常达成目标, 只是它的"主观时间"比现实世界慢了若干倍。
灵感场景:在一台电脑里模拟一个大脑。模拟速度被放慢后,大脑内部的 思维流速与外部现实世界对不上——它自己感知的每 1 秒,现实里过去了 很多秒。本工具就是把这件事做成通用机制,覆盖 PC 主流系统。
| 模式 | 机制 | 适用 | 平台 |
|---|---|---|---|
| 时钟膨胀 clock | 拦截并缩放进程的时钟读取与睡眠等待 | 一切"按主观时间运转"的程序(模拟器、游戏循环、实时仿真、机器人控制、音视频节拍) | Linux / macOS |
| CPU 节流 cpu | 限制进程只能获得 rate 份额的 CPU |
一切程序,含纯计算、静态链接、闭源二进制 | Linux / macOS / Windows |
两种模式可叠加。
程序对时间的全部认知来自两件事:读时钟(clock_gettime /
gettimeofday / mach_absolute_time…)和睡眠/限时等待
(nanosleep / select / poll / pthread_cond_timedwait…)。
shim 在进程加载时把这两类函数全部拦截,按统一比例缩放:
主观时间 = 锚点 + (真实时间 - 锚点) × RATE
于是程序"睡主观 10ms"实际睡 10ms/RATE,读到的"经过时间"也只有 真实的 RATE 倍。整个虚拟世界的时间流速被一致拉慢,内部逻辑 (节拍、超时、相对时限)完全自洽,最终目标照常达成,只是变慢。
实测(brain 演示,目标=放电率稳态收敛,四档速率):
| RATE | 主观耗时 | 真实耗时 | 结果 |
|---|---|---|---|
| 1.00 | 1236 ms | 1236 ms | 达成,放电 218721 |
| 0.50 | 1236 ms | 2471 ms | 达成,放电 218721 |
| 0.25 | 1236 ms | 4942 ms | 达成,放电 218721 |
| 0.10 | 1236 ms | 12355 ms | 达成,放电 218721 |
放电数完全一致:只变慢,不改变结果。
对任意现有程序同样有效(无需修改一行代码)。Python 实测:
SLOWMO_RATE=0.25 下程序自感 3.00 s,真实耗时 12.47 s。
- Linux / macOS:监护进程对整个进程组做占空比控制
(运行
quantum秒 → 暂停quantum×(1/rate-1)秒循环)。 - Windows:Job Object CPU Rate Control(Win8+,Win10+ 自动尝试 HARD_CAP),由内核调度器强制份额,GUI 不冻结。
实测(brain --mode free,纯计算不受主观钟约束):
| RATE | 真实耗时 | 结果 |
|---|---|---|
| 1.00 | 663 ms | 达成,放电 51409 |
| 0.50 | 1316 ms | 达成,放电 51409 |
| 0.25 | 2805 ms | 达成,放电 51409 |
| 0.10 | 6549 ms | 达成,放电 51409 |
make # 生成 libslowmo_time.so(macOS 为 .dylib)和 brain 演示
make test # 跑完整验证# Linux
SLOWMO_RATE=0.25 LD_PRELOAD=$PWD/libslowmo_time.so ./你的程序 参数...
# macOS
SLOWMO_RATE=0.25 DYLD_INSERT_LIBRARIES=$PWD/libslowmo_time.dylib ./你的程序 参数...python3 src/slowmo.py --rate 0.25 -- ./你的程序 参数...
python3 src/slowmo.py --rate 0.1 --time-report -- python train.py # 任何解释器程序
python3 src/slowmo.py --rate 0.5 -- app.exe # Windows测试环境:Ubuntu 22.04 / gcc 11.4 / Python 3.10 / x86_64(3 核沙箱)。
探针 src/probe.c 五维度探测:读钟、睡眠、限时等待、多线程绝对期限、纯计算。
| 测试对象 | 时钟膨胀模式 | CPU 节流模式 | 叠加模式 |
|---|---|---|---|
| C(gcc 动态链接) | 生效,比值 0.500 / 0.250 / 0.100 零误差 | 生效,计算减速 2.06× / 3.98× | 生效,时间维 0.25 且计算再叠 2× |
| C++(std::chrono + sleep_for) | 生效,外层实测 ≈3.96× | 生效 | — |
| Python 3.10(time.* + sleep) | 生效,外层实测 ≈4.0× | 生效 | — |
| C(静态链接) | 不生效(LD_PRELOAD 无法注入,符合设计边界) | 生效,与动态链接完全一致(3.97×) | — |
| 模式 | 设定 | 实测减速比 | 误差 |
|---|---|---|---|
| 时钟 0.50 | 慢 2× | 2.000× | 0.0% |
| 时钟 0.25 | 慢 4× | 4.000× | 0.0% |
| 时钟 0.10 | 慢 10× | 10.00× | 0.0% |
| CPU 0.50 | 慢 2× | 2.064× | 3.2% |
| CPU 0.25 | 慢 4× | 3.980× | 0.5% |
| 叠加 clock 0.25 + cpu 0.5 | 时间慢 4×,机器慢 2× | 时间维 4.0×,计算 8.0× | — |
- 限时等待拉长:
select等限时等待只在进程"运行相"推进, 实际等待时长约为名义值 × 1/rate(等待类 syscall 在 SIGSTOP 期间暂停计时)。 - 睡眠过冲:睡眠可能被停相截断,醒来时刻对齐到运行相边界。 实测 rate=0.25 时 5×100ms 睡眠:quantum=50ms 耗时 1001ms, quantum=20ms 降到 641ms——缩小 quantum 可减轻过冲,代价是调度更频繁。
若需要等待类行为完全自洽,用时钟膨胀模式(或叠加模式, 但叠加后虚拟世界内部的"机器性能"也会变慢——大脑的主观时间里 计算和等待都会显得更久)。
复现全部测试:./run_matrix.sh。
- 时钟模式对纯计算无效:不读钟、不睡眠的程序感知不到缩放, 请用 CPU 节流模式(两者可叠加)。
- 静态链接二进制无法注入 shim → 用 CPU 模式。
- Linux glibc 内部 vDSO 路径、
itimer/timer_create信号定时器、 libc 内部自用时钟不经拦截;绝大多数应用的主循环不受影响。 - macOS SIP 会阻止注入系统二进制(对自己编译的程序无影响)。
pthread_cond_timedwait假定条件变量用默认CLOCK_REALTIME; 使用 monotonic condattr 的程序请改用 CPU 模式。- CPU 时间(
getrusage、CLOCK_PROCESS_CPUTIME_ID)不缩放—— 它度量资源消耗,不是世界时间。 - CPU 模式下程序看到的挂钟时间仍是真实时间,内部"墙钟超时"会相对 提前触发——这正是时间流速错位的表现,介意者请叠加时钟模式。
src/slowmo_time.c POSIX 时钟膨胀 shim(单文件,无依赖)
src/slowmo.py 跨平台 CPU 节流启动器(纯标准库)
src/brain.c 虚拟大脑演示(Izhikevich 网络 + 稳态自调节目标)
src/probe.c 兼容性探针(读钟/睡眠/限时等待/多线程/纯计算)
src/probe_cpp.cpp C++ 探针(std::chrono / sleep_for)
src/probe.py Python 探针(time.* / sleep)
run_matrix.sh 一键兼容性测试矩阵
Makefile 构建与一键验证
README.en.md 英文文档
LICENSE MIT 许可证
MIT,见 LICENSE。欢迎 issue 与 PR。
- Linux 也可用 cgroup v2
cpu.max做 CPU 模式(需 root,更平滑)。 - Windows 时钟膨胀可用 Detours 挂钩
QueryPerformanceCounter等, 思路与 POSIX shim 相同。 - 需要完全确定性(时间与执行序可复现)时可参考 RR、UndoDB、
QEMU
-icount(虚拟时钟绑定指令数)等确定性回放方案。