这是一个奇怪的案例,最近在分析我一直在研究的一个专门集合时出现。
该集合几乎只是两个数组,一个是 int[]
键数组,另一个是 Object[]
值数组,并提供哈希函数快速查找。一切都运行良好,但我开始分析代码并得到一些奇怪的结果;对于分析,我决定采用老式方法,通过抓取 System.currentTimeMillis() 一遍又一遍地运行测试,然后检查已经过去了多少时间,如下所示:
long sTime = System.currentTimeMillis();
for (int index : indices)
foo.remove(index);
long took = System.currentTimeMillis() - sTime;
在我的测试中,我准备了 200,000 个条目的 foo
,以及预先生成的我将删除的索引
列表。我使用循环重置并运行测试一千次,并将 take
添加到运行总数中。
现在,对于命令,与其他数据类型相比,我得到了非常好的结果,除了我的 remove(int)
方法。但是,我一直在努力找出原因,因为我的删除方法与我的 get(int)
方法相同(显然除了删除之外),如下所示:
public Object get(int key) {
int i = getIndex(key); // Hashes key and locates it
return (i >= 0) ? this.values[i] : null;
}
public Object remove(int key) {
int i = getIndex(key); // Does exactly the same as above
if (i >= 0) {
--this.size;
++this.modifications; // For concurrent access behaviour
this.keys[i] = 0; // Zero indicates null entry
Object old = this.values[i];
this.values[i] = null;
return old;
}
return null;
}
虽然我预计删除需要更长的时间,但它们的执行时间是 get(int)
的 5 倍以上。但是,如果我注释掉 this.keys[i] = 0
行,那么性能几乎与 get(int)
相同。
我是否正确地观察到这是为我的 int[]
数组分配值的问题?我尝试注释掉所有 this.values
操作并经历同样的缓慢时间,但在注释 this.keys[i] 时保留
始终如一地解决问题;我完全不知道发生了什么,有什么办法吗?this.values
= 0
考虑到删除相对较少,性能仍然不错,但在 int[]
中设置值似乎会产生如此大的影响,这似乎很奇怪,所以我很想知道为什么。
最佳答案
所编写的代码不能同时工作。如果没有显示其他并发代码,则很可能是源时序差异。除此之外,最可能的原因是除了values[] 数组之外,访问keys[] 数组也改变了内存访问模式。例如,从寄存器切换到内存位置,从 L1 缓存切换到 L2 缓存,或从 L3 缓存或主内存切换。 “错误共享”是退化模式的一个例子。 “机械同情”是一个用于调整当前硬件架构的名称。
关于java - 设置整数数组值的异常性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24355894/