我得到了我提出的问题的答案。
应用程序内存分配器:
C和C++开发人员必须手动管理内存分配和释放。默认的内存分配器在libc库中。
libc
请注意,在执行free()后,释放的空间将可供应用程序进一步分配使用,而不会返回给系统。只有当应用程序终止时,内存才会返回给系统。这就是为什么应用程序的进程大小通常永远不会减小。但对于长时间运行的应用程序,应用程序进程大小通常保持稳定状态,因为释放的内存可以被重复使用。如果不是这种情况,则很可能应用程序泄漏内存,即在不再使用时未释放已分配的内存,并且应用程序未跟踪已分配内存的指针--基本上是丢失了。
在多线程应用程序中频繁发生并发malloc或free操作时,默认的libc内存分配器不适用于多线程应用程序,特别是对于多线程C++应用程序。这是因为创建和销毁C++对象是C++应用程序开发风格的一部分。当使用默认的libc分配器时,堆由单个堆锁保护,导致默认分配器在malloc或free操作期间由于重量级锁争用而不可扩展。可以使用Solaris工具轻松检测此问题,如下所示。
首先,使用prstat -mL -p查看应用程序是否在锁上花费了大量时间;查看LCK列。例如:
-bash-3.2
PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID
14052 root 0.6 0.7 0.0 0.0 0.0 35 0.0 64 245 13 841 0 test_vector_/721
14052 root 1.0 0.0 0.0 0.0 0.0 35 0.0 64 287 5 731 0 test_vector_/941
14052 root 1.0 0.0 0.0 0.0 0.0 35 0.0 64 298 3 680 0 test_vector_/181
14052 root 1.0 0.1 0.0 0.0 0.0 35 0.0 64 298 3 1K 0 test_vector_/549
....
这表明该应用程序约花费35%的时间等待锁。
然后,使用plockstat(1M)工具查找应用程序正在等待的锁。例如,使用进程ID 14052跟踪应用程序5秒钟,然后使用c++filt实用程序过滤输出以解码C ++符号名称。 (c++filt实用程序随附于Sun Studio软件中。)如果应用程序不是C ++应用程序,则不需要通过c++filt进行过滤。
-bash-3.2# plockstat -e 5 -p 14052 | c++filt
Mutex block
Count nsec Lock Caller
-------------------------------------------------------------------------------
9678 166540561 libc.so.1‘libc_malloc_lock libCrun.so.1‘void operator
delete(void*)+0x26
5530 197179848 libc.so.1‘libc_malloc_lock libCrun.so.1‘void*operator
new(unsigned)+0x38
......
从上面的内容可以看出,堆锁 libc_malloc_lock 被大量争夺,这很可能是导致扩展问题的原因。解决 libc 分配器的扩展问题的方法是使用一个改进的内存分配器,比如 libumem 库。
另外请访问:
http://developers.sun.com/solaris/articles/solaris_memory.html
感谢所有试图回答我的问题的人,
Santhosh.