测试代码
测试方法比较笨,每修改一次线程数,就重新编译一次,再运行。在程序运行过程中,查看到进程 pid,然后通过以下命令查看进程的运行状态信息输出到以线程数为名字的日志文件中,最后用 vimdiff 对比文件来查看内存上的差异。
cat /proc/查询到的pid/status
#include <pthread.h>
#include <unistd.h>
void *test(void *arg) {
while(1) {
sleep(1);
}
return NULL;
}
int main(int argc, char *argv[])
{
const int NUM = 76; // 线程数
pthread_t arr[NUM];
for (int i = 0; i < NUM; ++i) {
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, test, NULL);
pthread_attr_destroy(&attr);
arr[i] = tid;
}
for (int i = 0; i < NUM; ++i) {
pthread_join(arr[i], NULL);
}
//test(NULL);
return 0;
}
测试结果
- 每多创建一个线程,虚拟内存增长 8M 左右(这大概是匹配 linux 线程/进程的栈空间大小),对于 64 位操作系统来说,虚拟内存是远大于物理内存的,所以不用担心虚拟内存不够,实际更应该关心物理内存的占用情况。
- 由于从 glibc 库到操作系统,再到物理内存硬件都有着复杂的内存管理机制,有两点要意识到,一是分配了多大的虚拟内存,并不一定会分配相应大小的物理内存,二是进程向操作系统申请 n 字节空间,操作系统并不是刚好给该进程分配 n 字节物理内存。我在测试中发现,创建一个线程,占用的物理常驻内存(VmRss)是 392kb,然后我逐渐增加线程数,一直到14个线程,VmRss 都还是 392 kb。
- 测试下来发现:
- 1 ~ 14 个线程,VmRss 约等于 392kb
- 15 ~ 45 个线程,VmRss 约等于 652kb addMem = 652 - 392 = 260kb
- 46 ~ 76 个线程,VmRss 约等于 916kb addMem = 916 - 652 = 264kb
- 77 ~ ? 个线程,VmRss 约等于 1180 kb
- 大致得出平均一个线程的基础内存开销 = 260/30 = 8.6kb