c - 使用 CreateThread() 在 Windows 中创建线程的时间很荒谬
问题描述
因此,我创建了以下简单程序来测量在我的机器上创建进程或线程的平均时间:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
DWORD WINAPI ThreadFunc(void* data) {
return 0;
}
int main(int argc, char** argv) {
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
clock_t begin, end;
double cpu_time_used;
for(int i = 0; i <= 1000000;i++){
begin = clock();
CreateProcess(NULL, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
end = clock();
cpu_time_used += ((double) (end - begin)) / CLOCKS_PER_SEC;
TerminateProcess(pi.hProcess, 0);
}
/* since we're running 1 000 000 (1 million) times we divide by 1
* million and since to get the time in ns instead of ns we multiply by
* 1 billion we simply multiply by 1000 since 1 billion / 1 million = 1000.
*/
printf("Average time to create a process = %f ns\n", cpu_time_used * 1000);
cpu_time_used = 0;
for(int i = 0; i < 1000000;i++){
begin = clock();
CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
end = clock();
cpu_time_used += ((double) (end - begin)) / CLOCKS_PER_SEC;
}
/* since we're running 1 000 000 (1 million) times we divide by 1
* million and since to get the time in ns instead of ns we multiply by
* 1 billion we simply multiply by 1000 since 1 billion / 1 million = 1000.
*/
printf("Average time to create a Thread = %f ns\n", cpu_time_used * 1000);
return (EXIT_SUCCESS);
}
以下结果:
Average time to create a process = 89.000000 ns
Average time to create a Thread = 112055.000000 ns
创建一个进程的时间似乎很合理,但为什么创建一个线程的时间比创建一个全新的进程要长一千倍呢?
解决方案
好的,我的方法有几个错误,我将在这里解释,最后附上完整的最终代码。
- CreateProcess() 调用什么都不做,而不是启动一个什么都不做的程序。为了解决这个问题,我们
CreateProcess(NULL, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
更改CreateProcess("C:\\Windows\\System32\\rundll32.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
并暂停该过程。 - Windows 将程序限制为 2048 个线程。这意味着在第 2048 个线程之后发生了一个额外的瓶颈,因为程序等待线程关闭以打开一个新线程。为了避免这种情况,我将循环减少到只有 1000 个。
- 正如@Some程序员老兄指出的那样,clock() 对于多线程程序是不准确的,相反,我们使用 QueryPerformanceCounter()。请记住,根据您的 IDE 和其他因素,QueryPerformanceFrequency 可能会错误地返回 10 MHz(NetBeans 有此问题,因此更改为 Visual Studio),因此请先进行测试。
固定的最终代码是:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
DWORD WINAPI ThreadFunc(void* data) {
return 0;
}
int main(int argc, char** argv) {
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
LARGE_INTEGER begin, end, cpu_time_used;
LARGE_INTEGER Frequency;
cpu_time_used.QuadPart = 0;
QueryPerformanceFrequency(&Frequency);
for (int i = 0; i <= 1000; i++) {
QueryPerformanceCounter(&begin);
CreateProcess("C:\\Windows\\System32\\rundll32.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
QueryPerformanceCounter(&end);
cpu_time_used.QuadPart += end.QuadPart - begin.QuadPart;
TerminateProcess(pi.hProcess, 0);
}
cpu_time_used.QuadPart *= 1000000;
cpu_time_used.QuadPart /= Frequency.QuadPart;
printf("Average time to create a process = %lld us\n", cpu_time_used.QuadPart / 1000);
cpu_time_used.QuadPart = 0;
HANDLE hThread;
for (int i = 0; i <= 1000; i++) {
QueryPerformanceCounter(&begin);
hThread = CreateThread(NULL, 0, ThreadFunc, NULL, CREATE_SUSPENDED, NULL);
QueryPerformanceCounter(&end);
cpu_time_used.QuadPart += end.QuadPart - begin.QuadPart;
}
cpu_time_used.QuadPart *= 1000000;
cpu_time_used.QuadPart /= Frequency.QuadPart;
printf("Average time to create a Thread = %lld us\n", cpu_time_used.QuadPart / 1000);
return (EXIT_SUCCESS);
}
返回:
Average time to create a process = 8289 us
Average time to create a Thread = 26 us
推荐阅读
- google-fabric - “组织”可以拥有的应用程序数量是否有限制?
- mysql - Error when switching user in mysql client
- pytest - 目前在pytest中测试文件名
- wordpress - Wordpress ContactForm7 不向电子邮件发送消息
- c++ - 使用 cmake 编译 iOS 动态库(.framework)
- jenkins - 如何在 Jenkins 上创建多个性能测试结果报告?
- java - 使用 Jersey 和 Moxy 编组 java POJO
- unix - pthread_cond_timedwait() 在 FreeBSD 上不起作用,返回 EPERM
- r - dplyr R中汇总函数中的ifelse()嵌套语句
- react-native - 可能未处理的承诺拒绝/错误:请求失败,状态码为 400