时间:2010-06-01 07:25:17

标签: c linux solaris free

我编写了一个小程序,并在Solaris / Linux平台下编译它,以衡量将此代码应用于我的应用程序的性能。

程序以这样的方式编写,最初使用sbrk(0)系统调用,我已经获取了堆区域的基址。之后,我使用malloc系统调用分配了1.5 GB的内存,然后我使用memcpy系统调用将1.5 GB的内容复制到分配的内存区域。然后,我释放了分配的内存。

释放后,我再次使用sbrk(0)系统调用来查看堆大小。

这是我有点困惑的地方。在Solaris中,即使我释放了分配的内存(接近1.5 GB),但进程的堆大小也很大。但我在Linux中运行相同的应用程序,在释放后,我发现在分配1.5 GB之前,进程的堆大小等于堆内存的大小。

我知道Solaris不会立即释放内存,但我不知道如何调整Solaris内核以在free()系统调用后立即释放内存。

为什么我在Linux下没有同样的问题?

1 个答案:

答案 0 :(得分:3)

我得到了我所问过的问题的答案。

应用程序内存分配器:

C和C ++开发人员必须手动管理内存分配和可用内存。默认内存分配器位于libc库中。

libc的 请注意,执行free()后,释放的空间可供应用程序进一步分配,而不会返回给系统。仅当应用程序终止时,内存才会返回到系统。这就是应用程序的流程大小通常永不减少的原因。但对于长时间运行的应用程序,应用程序进程大小通常保持稳定状态,因为释放的内存可以重用。如果不是这种情况,则很可能应用程序正在泄漏内存,也就是说,使用已分配的内存但在不再使用时从未释放,并且应用程序未跟踪指向已分配内存的指针 - 基本上丢失了。

当经常发生并发malloc或空闲操作时,libc中的默认内存分配器不适合多线程应用程序,尤其是对于多线程C ++应用程序。这是因为创建和销毁C ++对象是C ++应用程序开发风格的一部分。当使用默认的libc分配器时,堆由单个堆锁保护,导致默认分配器不能为多线程应用程序扩展,因为在malloc或free操作期间存在严重的锁争用。使用Solaris工具很容易检测到这个问题,如下所示。

首先,使用prstat -mL -p查看应用程序是否在锁上花费了很多时间;看看LCK专栏。例如:

-bash-3.2# prstat -mL -p 14052
   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。