返回信息流在jvm里,堆上分配内存相当于cpu加法运算的什么量级?
这是一条镜像帖。来源:北邮人论坛 / java / #26773同步于 2013/9/5
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
堆上分配内存会很慢么?
yangshi980
2013/9/5镜像同步5 回复
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
内存的时间开销差别主要不在分配时~而是在访存时,栈内存的访存是直接的,而堆则需要至少一次间指,例如同样对数组元素置零(esp是栈顶指针,eax是循环变量,var_a、var_b是编译器决定的一固定值):
;栈内存
mov [esp+eax*4+var_a], 0 ; 直接移动栈指针并赋值
;堆内存
lea edx, ds:0[eax*4] ; edx暂存元素的偏址
mov eax, [esp+var_b] ; [esp+var_c]中储存的是堆内存的首地址,此处开始eax被重新赋值,不再是循环变量
add eax, edx ; 基址+偏址,并放入eax
mov dword ptr [eax], 0 ; 取地址,赋值
【 在 yangshi980 的大作中提到: 】
: 在jvm里,堆上分配内存相当于cpu加法运算的什么量级?
和内存管理有关。
对于semi-space和mark-compact垃圾回收器来说,每次回收都会把对象连续地放在一起,整理碎片。所以,可用的内存总是一段连续的内存。所以,分配内存就是bump pointer(保存指针,指针增加对象长度,然后返回原指针)。
对于mark-sweep来说,它不会移动对象。所以空闲的空间是一个个的“空洞”。用一个free list链表保存下一块空闲内存的位置。有时候,你要分配的内存空间太大,所以必须遍历一个个的空余空间,以找到一个足够大的。有些策略会找到大小和要分配的对象最接近的那块空间,这就复杂度更高了。
对于immix这样的mark-region垃圾回收算法来说,内存被分成等大的“页”,每个线程会拿到一系列空闲的页,每个页内用bump pointer;但是如果自己的页用完了,就要像全局管理器索取更多的页,这就涉及到在有空洞的页表中找空闲页,也有类似链表的算法,但是这种情况发生得不频繁。所以大多数情况是快的。
对于generational GC,内存也会分成两块,一块比较小的内存叫nursery,用于分配新的对象,就是用bump pointer;一旦nursery满了,就进行一遍跟踪,把nursery中还活着的对象放到另一块更大的空间。实际应用中,绝大多数对象都是“早死”的。那个较大的空间可以使用上述任何一种策略。大空间再满了,就进行一次全堆的垃圾回收。如果还满,就真的满了。实际上可以使用多级的generational GC,就是将对象分为很多“代”。越年老的对象越不容易死,这也是事实。
HotSpot据说(我没读过源代码)是使用3代的generational GC,最高代使用mark-compact。所以,内存分配比较快,但是全堆回收的时候可能会慢一些,但是毕竟这种事很少发生,慢一些也无所谓。
JikesRVM是研究型虚拟机,你可以选择上述的策略进行测试。
这篇论文讨论了不同策略对分配、回收、内存占用率的影响。注意有时候不仅是内存访问次数,cache miss的次数也会影响效率。 http://dl.acm.org/citation.cfm?doid=1375581.1375586
果然还是通过内存管理模型来解答这个问题更高端、大气、上档次!
另外不同领域的工程师关注点确实有很大不同~
再另外mark-sweep确实是一种较为糟糕的策略...因此需要较高的代码质量来解决alloc出来大片无力内存的问题~
【 在 nuanyangyang 的大作中提到: 】
: 和内存管理有关。
: 对于semi-space和mark-compact垃圾回收器来说,每次回收都会把对象连续地放在一起,整理碎片。所以,可用的内存总是一段连续的内存。所以,分配内存就是bump pointer(保存指针,指针增加对象长度,然后返回原指针)。
: 对于mark-sweep来说,它不会移动对象。所以空闲的空间是一个个的“空洞”。用一个free list链表保存下一块空闲内存的位置。有时候,你要分配的内存空间太大,所以必须遍历一个个的空余空间,以找到一个足够大的。有些策略会找到大小和要分配的对象最接近的那块空间,这就复杂度更高了。
: ...................
问问你用什么汇编器。最近开始学x64汇编(呵呵,现在才开始),我用gnu as,但是默认是at&t语法。但是你写的是intel语法(我觉得intel语法看上去舒服一些),是不是有某个汇编器默认用的就是intel语法呢?
【 在 tonyjansan 的大作中提到: 】
: 果然还是通过内存管理模型来解答这个问题更高端、大气、上档次!
: 另外不同领域的工程师关注点确实有很大不同~
: 再另外mark-sweep确实是一种较为糟糕的策略...因此需要较高的代码质量来解决alloc出来大片无力内存的问题~
: ...................
Linux下intel系的汇编器不是有NASM的吗?可以用的...
不过我一般搞汇编或者逆向都是在Win下~有IDA这个犀利的工具系统平台神马滴都问题ない...(支持pe、elf)
【 在 nuanyangyang 的大作中提到: 】
: 问问你用什么汇编器。最近开始学x64汇编(呵呵,现在才开始),我用gnu as,但是默认是at&t语法。但是你写的是intel语法(我觉得intel语法看上去舒服一些),是不是有某个汇编器默认用的就是intel语法呢?
: