![]() |
1
26
如果你想要一个简单的答案,那就是没有简单的答案。没有多少打电话的答案(暗示人们)“懒惰”会有帮助。
以JVM可以使内存为零的速度,假设分配不会触发垃圾收集。如果它确实触发了垃圾收集,那么在不知道使用了什么GC算法、堆大小和其他参数,以及在应用程序的整个生命周期内对应用程序的非垃圾对象工作集进行分析的情况下,就无法预测。
见上文。
如果你想要一个简单的答案,那就是没有简单的答案。 黄金法则是,堆越大(达到可用的物理内存量),垃圾对象的分摊成本越小。使用快速复制垃圾收集器,随着堆的增大,释放垃圾对象的摊余成本接近零。GC的成本实际上是由(简单地说)GC必须处理的非垃圾对象的数量和大小决定的。 在假定堆很大的情况下,分配和GC处理大型对象(在一个GC周期内)的生命周期成本接近于在分配对象时将内存归零的成本。 编辑 :如果您只需要一些简单的数字,请编写一个分配和丢弃大型缓冲区的简单应用程序,并使用各种GC和堆参数在您的计算机上运行它,然后看看会发生什么。但要注意,这并不能给您一个实际的答案,因为实际的GC成本取决于应用程序的非垃圾对象。 我不会给你写一个基准,因为 我知道 它会给你虚假的答案。 编辑2 :回应操作人员的意见。
理论上是的。在实践中,很难以将分配成本与GC成本分开的方式进行衡量。
不,我是说很可能 增加 性能。明显地。(前提是您不会遇到操作系统级的虚拟内存效果。)
也许吧。坦率地说,我认为回收缓冲液不会有什么改进。
但是如果您打算沿着这条路径走,请创建一个缓冲池
界面
有两个实现。第一个是一个真正的线程安全缓冲池,它可以回收缓冲区。第二个是虚拟池,它每次只分配一个新的缓冲区。
|
![]() |
2
14
当它比年轻的空间大的时候。 如果数组大于线程本地年轻空间,则直接在旧空间中分配。旧空间的垃圾收集比年轻空间慢得多。因此,如果数组大于年轻空间,那么重用它可能是有意义的。 在我的机器上,32KB超过了年轻的空间。所以重用它是有意义的。 |
![]() |
3
3
您忽略了有关线程安全的任何内容。如果它将被多个线程重用,那么您将不得不担心同步问题。 |
![]() |
4
3
一个完全不同方向的答案:让您的库的用户来决定。 最终,无论您如何优化您的库,它都只是一个更大应用程序的组件。如果较大的应用程序不经常使用您的库,那么就没有理由维护一个缓冲池——即使这个缓冲池只有几百千字节。 因此,将池机制创建为一个接口,并根据一些配置参数选择库使用的实现。将默认值设置为基准测试确定的最佳解决方案。 一 是的,如果您使用一个接口,那么就必须依赖于JVM足够智能地进行内联调用。 二 (1)通过“基准”,我指的是一个长期运行的程序,它可以运行您的库。 在分析器外部 ,传递各种输入。轮廓仪非常有用,但是测量一小时的挂钟时间后的总吞吐量也是如此。在具有不同堆大小的几个不同计算机上,以及在单线程和多线程模式下运行的几个不同的JVM上。 (2)这可以让你进入另一个关于各种 援引 操作码。 |
![]() |
5
2
简短回答:不要缓冲。 原因如下:
回收对象的时间:
|
![]() |
6
1
请记住,缓存效果可能比“new int[size]”及其相应集合的成本更重要。因此,如果具有良好的时间位置,重用缓冲区是一个好主意。重新分配缓冲区而不是重用它意味着每次都可能得到不同的内存块。正如其他人所提到的,当你的缓冲器不适合年轻一代时,情况尤其如此。 如果您分配了但又不使用整个缓冲区,那么重用也会很划算,因为您不会浪费时间将从未使用过的内存清零。 |
![]() |
7
1
比缓冲区大小更重要的是分配的对象数和分配的总内存。
池的真正优点是避免内存碎片。分配/释放内存的开销很小,但缺点是,如果重复分配多个不同大小的对象,则内存会变得更分散。使用池可以防止碎片化。 |
![]() |
8
1
我忘了这是一个管理内存系统。 实际上,你可能有错误的心态。确定它何时有用的适当方法取决于应用程序、运行它的系统以及用户使用模式。 换句话说,只需对系统进行概要分析,确定垃圾收集所花费的时间占典型会话中应用程序总时间的百分比,并查看是否值得对此进行优化。 你可能会发现GC根本没有被调用。因此,编写代码来优化这一点完全是浪费时间。 今天的记忆空间很大,我怀疑90%的时间根本不值得做。你不能根据参数来确定这一点——这太复杂了。只是轮廓-简单和准确。 |
![]() |
9
1
查看一个微基准(下面的代码),无论数组的大小和使用时间如何,我的机器上的时间都没有明显的差异(我不会发布时间,您可以在您的机器上轻松地运行它:-)。我怀疑这是因为垃圾在这么短的一段时间内是活的,清理垃圾没什么可做的。数组分配可能需要调用calloc或malloc/memset。根据CPU的不同,这将是一个非常快速的操作。如果数组存活的时间更长,使其超过初始GC区域(托儿所),那么分配多个数组的时间可能会更长一些。 代码:
|
![]() |
10
1
我遇到了这个问题,自从我实现了 Floyd-Warshall 在一个有一千个顶点的图上,所有对的连接算法,我试图以两种方式实现它(重新使用矩阵或创建新的矩阵),并检查经过的时间。 为了计算,我需要1000个不同的矩阵,大小为1000 x 1000,所以这似乎是一个不错的测试。 我的系统是带以下虚拟机的Ubuntu Linux。
重新使用矩阵大约慢10%(平均运行时间超过5次执行17354ms,而不是15708ms。我不知道如果矩阵大得多,它是否还会更快。 相关代码如下:
|
![]() |
11
0
我认为你需要的答案与“顺序”有关(测量空间,而不是时间!)算法的。 复制文件示例 例如,如果要复制文件,则需要从输入流中读取文件并写入输出流。时间顺序是O(N),因为时间将与文件大小成比例。但是空间顺序将是O(1),因为您需要执行的程序将聚焦固定内存量(您只需要一个固定缓冲区)。在这种情况下,很明显可以方便地重用在程序开始时实例化的缓冲区。 将缓冲区策略与算法执行结构关联起来 当然,如果您的算法需要无限的缓冲区,并且每个缓冲区的大小不同,那么您可能无法重用它们。但它给了你一些线索:
我想说的是:没有固定的答案。如果您实例化了一些可以重用的东西…也许更好地重用它。棘手的部分是找到如何在不引起缓冲区管理开销的情况下完成这项工作。这就是算法分析的用武之地。 希望有帮助…:) |
![]() |
TheKing · 为什么数组的地址可以有负值? 2 年前 |
![]() |
yurnero · MATLAB:“加载”一个快速访问功能 6 年前 |
![]() |
joe · 一页可以同时在两个工作集中吗? 6 年前 |
![]() |
Jaques · “.exe”已触发断点 6 年前 |
![]() |
adn bps · 在函数中修改变量的高效内存方法 6 年前 |
![]() |
Gauraang Khurana · C语言中分段错误的不稳定行为 6 年前 |
![]() |
Rajesh K · 如何查找设备中存在的广告垃圾? 6 年前 |