由java web性能测试想到的C,C++内存碎片的问题

一千年前的人 发布于 2013/11/14 13:06
阅读 1K+
收藏 0
最近产品在做性能测试, Web应用部署在WebSphere上。 发现高并发下,对性能和稳定性影响最大的参数是:
  1,各个内存块大小的分配    2,线程数    3,线程栈大小   4,DB连接池大小
这几个参数并不是越大约好,也不是越小约好,需要在压力测试下,找到合适的值。

对比java内存垃圾回收机制, 我就想问问:C/C++里面对于malloc、delete形成的内存碎片是怎么处理的?

是程序员处理吗?还是内部有什么机制?  


声明: 我没有C,C++经验,出于程序员的好奇,学习一下C、C++里面的机制而已,请有经验的大牛谈谈。

  @宏哥   @中山野鬼       @马太航   @CheckStyle  @擅长被美女推倒 
          

加载中
0
宏哥
宏哥

malloc 本质是向操作系统申请内存. free就是由操作系统来释放内存.

操作系统都是分页管理的. 产生碎片也无所谓, 基本上都可以做得非常有效率. 可以不需要特别处理, 除非有非常大量的小块内存分配释放.

如果需要自己处理, 一次分配大块内存, 自己管理.

java 是有一个堆, 来放置废弃的对象. 集中处理的."貌似"更不容易产生碎片, 实际情况是一样的.

至于性能这个东西, 最终还得落到磁盘上.

逝水fox
逝水fox
Java的堆在gc的时候会一边回收一边做碎片整理,所以不会有太多的碎片
hecaptain
hecaptain
free的话最终都是由操作系统来完成的,是否存在少许的延迟? 如果对数据吞吐量很大的话(每秒几个G的接收,处理,发送), 重写free能否有所改善, 求指点
1
宏哥
宏哥

引用来自“一千年前的人”的答案

引用来自“宏哥”的答案

malloc 本质是向操作系统申请内存. free就是由操作系统来释放内存.

操作系统都是分页管理的. 产生碎片也无所谓, 基本上都可以做得非常有效率. 可以不需要特别处理, 除非有非常大量的小块内存分配释放.

如果需要自己处理, 一次分配大块内存, 自己管理.

java 是有一个堆, 来放置废弃的对象. 集中处理的."貌似"更不容易产生碎片, 实际情况是一样的.

至于性能这个东西, 最终还得落到磁盘上.

1,关于C的malloc 和 free 确实 解惑了。 最终申请、释放、碎片整理都是OS完成的,OS完成这些工作确实是可靠和理所当然的, 这就是宏哥的 “原语” 理论。

2, java的堆 貌似 就是java自己一次性向OS申请了 大块内存,  然后java自己管理,给程序员带了方便,肯定有别的代价... 

3, 性能,确实归根到底是 IO 问题... 

OS不做碎片整理

OS 用分页来管理内存分配. 你申请1byte, 实际上, 它可能在一个64k的地方做记录

分页降低了内存使用率, 但是能将 碎片 的 碎化程度控制在一定程度上.

堆, 有个问题, 就是java做整理的时候, 会Block住其他行为

性能和IO相关主要指非"computing intensive" 的. 有些计算密集型, CPU也非常重要.

1
宏哥
宏哥

引用来自“一千年前的人”的答案

@宏哥   在批判java,但是也是对java理解很好的情况下。其实我也觉得java开发效率不高,笨重,过度设计。 但是老板不care工作量的问题,或许老板要的就是这个效果.... java的好处是各种API太丰富了...

像php、python, 他们在内存管理的模式上接近于C的方式(委托给OS)?
还是接近于Java呢(自己来垃圾回收,回收线程会有block其他线程..)?

和 C 一致的模式. PHP和python都有destruct.  即时交由操作系统释放. java没有destruct.

确切的说, PHP, Python是语言, java是平台, 这个区别很大.所以java自己托管内存.

而oracle这种, 则是可以做到自己分配大块内存空间, 也是自己显式管理. 

显式管理可以做到, 只标记内存可用, 并不实际交还操作系统.

很多时候, "减少工作量"并不是商业目标, 甚至, "增加工作量"才是商业目标.

hour rate base的商业, 肯定是增加工作量,才是目标了.

1
马太航
马太航

引用来自“一千年前的人”的答案

@宏哥   在批判java,但是也是对java理解很好的情况下。其实我也觉得java开发效率不高,笨重,过度设计。 但是老板不care工作量的问题,或许老板要的就是这个效果.... java的好处是各种API太丰富了...

像php、python, 他们在内存管理的模式上接近于C的方式(委托给OS)?
还是接近于Java呢(自己来垃圾回收,回收线程会有block其他线程..)?

研究这么细,工作也用不到何必呢。


本来就是很简单的问题,程序员自己申请开辟连续内存,碎片问题自己找个机制解决。OS常见的解决方案就是内存分页,只能减少碎片不能消灭分页,你分页空间大于可分配空间就没办法用分页,归根还是需要定期回收,像Windows 你不重启很难彻底消灭碎片问题。Java的方案归根就是申请个大堆做内存池。当然你可以在没有分页的OS上申请个大堆自己处理,比如嵌入式系统。像php、python这些无非是对调用环境api的包装或调用,大同小异。

1
小耶果
小耶果

再高并发的服务端程序和游戏客户端程序,通常都自己实现内存管理,其中大部分都有合并小块的功能.参见"小内存分配器的实现",但大多数的非特殊应用情况下,malloc已经工作的够好,一般应用层面无需担心碎片化问题.当然如果你精益求精,这里推荐几个"通用性"的内存分配优化器,有比malloc更好的分配策略来加快你的应用程序.TCMalloc,nedmalloc,memory-mgr...

但还是那句话,搞Java的就关心上层应用,不必关心内存碎片问题.好比老牛拉大车,真出现速度瓶颈,你考虑的是应该把牛换掉而不仅仅是大车上的轮胎.否则收效甚微.

一千年前的人
一千年前的人
回复 @小耶果 : 汗, 我的意思是 有利于帮助理解 jvm参数调整的原理。
小耶果
小耶果
回复 @一千年前的人 : 我不懂java,更不懂jvm,但调整参数只能调整GC的策略吧,比如适合一般应用,适合服务端的后台程序等.难道现在jvm的参数调整还能调gc中非常细节的东西了?
一千年前的人
一千年前的人
学习这些机制有利于 jvm参数的调整, 相比 自己实现内存管理,这已经是非常低级的要求了。但是这点低级的要求 对于java应用来说 已经够了...
0
马太航
马太航

自己处理,尽量用静态开辟,少用动态申请,常见方案比较多,像你可以弄个内存池。


至于碎片是肯定产生的跟磁盘碎片一个道理,不过磁盘可以整理,内存无法整理,单靠C/C++本身是无法实现,最多系统内核机制会小帮你一下。

一千年前的人
一千年前的人
谢谢! 方案是:自己实现内存管理...
0
一千年前的人
一千年前的人

引用来自“宏哥”的答案

malloc 本质是向操作系统申请内存. free就是由操作系统来释放内存.

操作系统都是分页管理的. 产生碎片也无所谓, 基本上都可以做得非常有效率. 可以不需要特别处理, 除非有非常大量的小块内存分配释放.

如果需要自己处理, 一次分配大块内存, 自己管理.

java 是有一个堆, 来放置废弃的对象. 集中处理的."貌似"更不容易产生碎片, 实际情况是一样的.

至于性能这个东西, 最终还得落到磁盘上.

1,关于C的malloc 和 free 确实 解惑了。 最终申请、释放、碎片整理都是OS完成的,OS完成这些工作确实是可靠和理所当然的, 这就是宏哥的 “原语” 理论。

2, java的堆 貌似 就是java自己一次性向OS申请了 大块内存,  然后java自己管理,给程序员带了方便,肯定有别的代价... 

3, 性能,确实归根到底是 IO 问题... 

0
一千年前的人
一千年前的人

@宏哥   在批判java,但是也是对java理解很好的情况下。其实我也觉得java开发效率不高,笨重,过度设计。 但是老板不care工作量的问题,或许老板要的就是这个效果.... java的好处是各种API太丰富了...

像php、python, 他们在内存管理的模式上接近于C的方式(委托给OS)?
还是接近于Java呢(自己来垃圾回收,回收线程会有block其他线程..)?

0
一千年前的人
一千年前的人

引用来自“宏哥”的答案

引用来自“一千年前的人”的答案

@宏哥   在批判java,但是也是对java理解很好的情况下。其实我也觉得java开发效率不高,笨重,过度设计。 但是老板不care工作量的问题,或许老板要的就是这个效果.... java的好处是各种API太丰富了...

像php、python, 他们在内存管理的模式上接近于C的方式(委托给OS)?
还是接近于Java呢(自己来垃圾回收,回收线程会有block其他线程..)?

和 C 一致的模式. PHP和python都有destruct.  即时交由操作系统释放. java没有destruct.

确切的说, PHP, Python是语言, java是平台, 这个区别很大.所以java自己托管内存.

而oracle这种, 则是可以做到自己分配大块内存空间, 也是自己显式管理. 

显式管理可以做到, 只标记内存可用, 并不实际交还操作系统.

很多时候, "减少工作量"并不是商业目标, 甚至, "增加工作量"才是商业目标.

hour rate base的商业, 肯定是增加工作量,才是目标了.

哎,hour rate base的商业,痛处。
0
一千年前的人
一千年前的人

引用来自“马太航”的答案

引用来自“一千年前的人”的答案

@宏哥   在批判java,但是也是对java理解很好的情况下。其实我也觉得java开发效率不高,笨重,过度设计。 但是老板不care工作量的问题,或许老板要的就是这个效果.... java的好处是各种API太丰富了...

像php、python, 他们在内存管理的模式上接近于C的方式(委托给OS)?
还是接近于Java呢(自己来垃圾回收,回收线程会有block其他线程..)?

研究这么细,工作也用不到何必呢。


本来就是很简单的问题,程序员自己申请开辟连续内存,碎片问题自己找个机制解决。OS常见的解决方案就是内存分页,只能减少碎片不能消灭分页,你分页空间大于可分配空间就没办法用分页,归根还是需要定期回收,像Windows 你不重启很难彻底消灭碎片问题。Java的方案归根就是申请个大堆做内存池。当然你可以在没有分页的OS上申请个大堆自己处理,比如嵌入式系统。像php、python这些无非是对调用环境api的包装或调用,大同小异。

你讲的也很细致,谢谢。 现在回想起来,这些都是操作系统的基本原理,不过当初学的时候,没法理解, 也不知道有啥用途。

在java里面, JVM参数不合理,就有可能发生这些情况:响应慢,Out Of Memory,Cup利用率很高..    理解这些基本原理,还是客户帮助理解调整JVM参数,WebSphere参数。

返回顶部
顶部