Bob*_*Gee 31 java optimization performance memory-management
在值得重用之前,缓冲区需要有多大的缓冲区?
或者,换一种方式:我可以重复分配,使用和丢弃byte []对象或运行池来保存和重用它们.我可能会分配很多经常被丢弃的小缓冲区,或者一些不会被丢弃的大缓冲区.汇集它们的大小比重新分配要便宜,小分配与大分配相比如何?
好的,具体参数.说英特尔酷睿2双核CPU,最新的虚拟机版本,适用于操作系统.这个问题并不像听起来那么模糊......一些小代码和一个图表可以回答它.
你发布了很多很好的一般规则和讨论,但这个问题确实要求数字.发布'em(和代码)! 理论很棒,但证据就是数字.如果各个系统的结果有所不同并不重要,我只是在寻找一个粗略的估计(数量级).似乎没有人知道性能差异是1.1,2,10或100+的因素,这是重要的.对于使用大型阵列的任何Java代码来说都很重要 - 网络,生物信息学等.
建议获得良好的基准:
我知道这是一个模糊且有点苛刻的问题.我会定期查看这个问题,答案会得到评论并持续评分.懒惰的答案不会(见下面的标准).如果我没有任何彻底的答案,我会附上一笔赏金.无论如何,我可能会额外奖励一个非常好的答案.
我正在开发一个库,为Java添加LZF压缩支持.该库通过添加额外的压缩级别(更多压缩)以及与来自C LZF库的字节流的兼容性来扩展H2 DBMS LZF类.我正在考虑的一件事是,是否值得尝试重用用于压缩/解压缩流的固定大小的缓冲区.缓冲器可以是~8kB,或~32kB,并且在原始版本中它们是~128kB.可以为每个流分配缓冲器一次或多次.我正在试图找出我想如何处理缓冲区以获得最佳性能,并着眼于将来可能的多线程.
是的,如果有人有兴趣使用它,库将作为开源发布.
Ste*_*n C 26
如果你想要一个简单的答案,那就是没有简单的答案.没有任何呼叫答案(并暗示人们)"懒惰"会有所帮助.
我期望在标准的现代CPU上运行(MB/s)内存分配的速度有多快?
以JVM可以使内存为零的速度,假设分配不会触发垃圾回收.如果它确实触发了垃圾收集,则无法在不知道使用什么GC算法,堆大小和其他参数的情况下进行预测,并且在应用程序的生命周期内分析应用程序的非垃圾对象的工作集.
分配大小如何影响分配率?
往上看.
分配数量/大小与池中重用的收支平衡点是什么?
如果你想要一个简单的答案,那就是没有简单的答案.
黄金法则是,堆越大(可用的物理内存量),GC垃圾对象的摊销成本越小.使用快速复制垃圾收集器,随着堆变大,释放垃圾对象的摊销成本接近零.GC的成本实际上由(简单来说)GC必须处理的非垃圾对象的数量和大小决定.
在您的堆很大的假设下,分配和GC大型对象(在一个GC循环中)的生命周期成本接近分配对象时将内存归零的成本.
编辑:如果你想要的只是一些简单的数字,写一个简单的应用程序,分配和丢弃大缓冲区并在你的机器上使用各种GC和堆参数运行它,看看会发生什么.但要注意,这不会给你一个现实的答案,因为真正的GC成本取决于应用程序的非垃圾对象.
我不会为你写一个基准,因为我知道它会给你一些假的答案.
编辑2:回应OP的评论.
所以,我应该期望分配的运行速度与System.arraycopy一样快,或者完全JITed数组初始化循环(在我的最后一个工作台上大约1GB/s,但我怀疑结果)?
理论上是的.实际上,很难以将分配成本与GC成本分开的方式进行衡量.
根据堆大小,您是说为JVM使用分配更大量的内存实际上会降低性能吗?
不,我说它可能会提高性能.显著.(前提是您没有遇到OS级别的虚拟内存效果.)
分配只适用于数组,我的代码中的其他几乎所有内容都在堆栈上运行.它应简化测量和预测性能.
也许.坦率地说,我认为你不会通过回收缓冲来获得很大的改善.
但是如果您打算沿着这条路走下去,请创建一个包含两个实现的缓冲池接口.第一个是真正的线程安全缓冲池,可以循环缓冲区.第二个是虚拟池,每次alloc
调用时都会简单地分配一个新的缓冲区,并将其视为dispose
无操作.最后,允许应用程序开发人员通过setBufferPool
方法和/或构造函数参数和/或运行时配置属性在池实现之间进行选择.应用程序还应该能够提供自己制作的缓冲池类/实例.
aku*_*uhn 13
当它比年轻的空间大.
如果您的数组大于线程本地年轻空间,则直接在旧空间中分配.旧空间上的垃圾收集比年轻空间慢.因此,如果您的数组大于年轻空间,则重用它可能是有意义的.
在我的机器上,32kb超过了年轻的空间.因此重用它是有意义的.
归档时间: |
|
查看次数: |
7256 次 |
最近记录: |