用例:
我正在尝试改进我的应用程序来渲染 Mandelbrot 集。我正在使用 HashSets 来检测集合中某个点的轨道的周期性。
例如,-1 的轨道是 0、-1、0、-1...如果我将到达的每个数字放入 HashSet 中,只需将 HashSet 的大小与迭代计数。这样做可以使渲染速度加快几个数量级。
当前实现:
就我的程序而言,执行迭代的方法接收一个使用默认构造函数构造的 HashSet(Integer 类型)。这是 Java Mission Control 向我展示的内容(典型输出,无论渲染的复杂性或深度如何): 迭代方法的运行时间很小,几乎总是小于 0.1 毫秒。 (在高变焦时,有时为 10 毫秒)。结果,创建了很多这样的哈希集,填充了约 10-100k 条目,然后立即转储。这会产生大量开销,因为必须经常调整 HashSet 的大小。
我尝试过但不起作用的事情:
- 创建一个 HashSet 并清除它:通过后备映射进行 O(n) 迭代绝对会降低性能。
- 使用 initalCapacity 参数使 HashSet 足够大以包含迭代:我尝试了从 1024 到 524288 的每个 2 的幂,所有这些都会使程序变慢。我的猜测是这样的:由于我们有这么多的 HashSet,java 更快地用完新集合的大块,因此我们触发了非常频繁的 GC,或一些类似的问题。
理想情况下,我希望两全其美:制作一个足够大的对象,然后清除它。但是,我似乎无法找到这样的数据结构。存储这些数据的最佳方法是什么?
最佳答案
根据我的经验,周期序列相当短,因此您应该使用数组并向后进行顺序搜索。您可以做一些实验,例如,如果您只与 60 次迭代前的元素进行比较,那么您已经捕获了长度为 2、3、4、5、6、12、15 和 30 的周期序列。计算曼德尔布罗轨道通常比在哈希集中查找(以及插入)元素快得多。
在这种情况下,进一步调整此方法也更容易,例如忽略前 n 个元素或使用一些 epsilon 来避免舍入错误。根据我的理解,使用您的方法您将检查双值是否严格相等。
祝你好运!
关于java - 分形渲染器中的 HashSet 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45559230/