为什么写一个用 stdout 重新打开的文件会更快?
Why it is faster writing a file which is freopened with stdout?
在Windows上执行时,此测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <assert.h>
int main() {
// The clock() function returns an approximation of processor time used by the program.
// The value returned is the CPU time used so far as a clock_t;
// to get the number of seconds used, divide by CLOCKS_PER_SEC.
auto buf = new char[1048576]; // 1MB
auto cache = new char[512 * 1024];
// initialize the buffer
for (int i = 0; i < 1048576; ++i)
buf[i] = i;
auto fp_reopen = freopen("data_freopen.bin", "wb", stdout);
assert(fp_reopen != nullptr);
setvbuf(fp_reopen, cache, _IOLBF, 512 * 1024);
auto clock_begin = clock();
for (int i = 0; i < 1000; ++i) {
auto n = fwrite(buf, 1048576, 1, fp_reopen);
assert(n == 1);
}
fflush(fp_reopen);
auto clock_end = clock();
#ifdef _WIN32
freopen("CONOUT$", "w", stdout);
#else
freopen("/dev/tty", "w", stdout);
#endif
printf("write with freopen clocks elapsed: %zu\n", clock_end - clock_begin);
auto fp = fopen("data_fopen.bin", "wb");
assert(fp != nullptr);
setvbuf(fp, cache, _IOLBF, 512 * 1024);
clock_begin = clock();
for (int i = 0; i < 1000; ++i) {
auto n = fwrite(buf, 1048576, 1, fp);
assert(n == 1);
}
fflush(fp);
clock_end = clock();
fclose(fp);
printf("write with fopen clocks elapsed: %zu\n", clock_end - clock_begin);
delete[] buf;
delete[] cache;
getchar();
}
生成这些结果:
write with freopen clocks elapsed: 2767
write with fopen clocks elapsed: 8337
为什么?
您的问题很有趣,但高度针对系统:
- 在 Linux 上使用 gcc 和 Glibc,两次运行的时间非常相似
- 在 OS/X,使用 clang 和 Apple Libc,
fopen
计时似乎始终比 freopen
快一点。
- 你是 运行 你在 Windows 上的测试,正如对
getchar()
的最后一次调用所暗示的那样...不幸的是,我无法测试这个系统来尝试交叉检查你的观察结果。
Microsoft 可能在他们的运行时库中做了一些奇怪的事情,但更有可能的是您真的在对创建 2 个单独的 1GB 文件进行基准测试。由于文件系统状态、缓存或其他 OS 特定原因,第二个文件的创建时间可能比第一个文件长。您应该尝试通过在关闭文件后删除每个文件来消除这种潜在的副作用,或者尝试 运行 以不同的顺序进行测试。
在Windows上执行时,此测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <assert.h>
int main() {
// The clock() function returns an approximation of processor time used by the program.
// The value returned is the CPU time used so far as a clock_t;
// to get the number of seconds used, divide by CLOCKS_PER_SEC.
auto buf = new char[1048576]; // 1MB
auto cache = new char[512 * 1024];
// initialize the buffer
for (int i = 0; i < 1048576; ++i)
buf[i] = i;
auto fp_reopen = freopen("data_freopen.bin", "wb", stdout);
assert(fp_reopen != nullptr);
setvbuf(fp_reopen, cache, _IOLBF, 512 * 1024);
auto clock_begin = clock();
for (int i = 0; i < 1000; ++i) {
auto n = fwrite(buf, 1048576, 1, fp_reopen);
assert(n == 1);
}
fflush(fp_reopen);
auto clock_end = clock();
#ifdef _WIN32
freopen("CONOUT$", "w", stdout);
#else
freopen("/dev/tty", "w", stdout);
#endif
printf("write with freopen clocks elapsed: %zu\n", clock_end - clock_begin);
auto fp = fopen("data_fopen.bin", "wb");
assert(fp != nullptr);
setvbuf(fp, cache, _IOLBF, 512 * 1024);
clock_begin = clock();
for (int i = 0; i < 1000; ++i) {
auto n = fwrite(buf, 1048576, 1, fp);
assert(n == 1);
}
fflush(fp);
clock_end = clock();
fclose(fp);
printf("write with fopen clocks elapsed: %zu\n", clock_end - clock_begin);
delete[] buf;
delete[] cache;
getchar();
}
生成这些结果:
write with freopen clocks elapsed: 2767
write with fopen clocks elapsed: 8337
为什么?
您的问题很有趣,但高度针对系统:
- 在 Linux 上使用 gcc 和 Glibc,两次运行的时间非常相似
- 在 OS/X,使用 clang 和 Apple Libc,
fopen
计时似乎始终比freopen
快一点。 - 你是 运行 你在 Windows 上的测试,正如对
getchar()
的最后一次调用所暗示的那样...不幸的是,我无法测试这个系统来尝试交叉检查你的观察结果。
Microsoft 可能在他们的运行时库中做了一些奇怪的事情,但更有可能的是您真的在对创建 2 个单独的 1GB 文件进行基准测试。由于文件系统状态、缓存或其他 OS 特定原因,第二个文件的创建时间可能比第一个文件长。您应该尝试通过在关闭文件后删除每个文件来消除这种潜在的副作用,或者尝试 运行 以不同的顺序进行测试。