Tag: 微优化

可以优化arrays访问吗?

也许我被我的探测器(Netbeans)误导了,但我看到了一些奇怪的行为,希望也许有人可以帮助我理解它。 我正在开发一个应用程序,它大量使用相当大的哈希表(键是long,值是对象)。 内置java哈希表(特别是HashMap)的性能非常差,在尝试了一些替代方案 – Trove,Fastutils,Colt,Carrot之后 – 我开始自己开发。 使用双哈希策略的代码非常基础。 这工作得很好,并且显示了迄今为止我尝试过的所有其他选项的最佳性能。 根据分析器的说法,查找哈希表是整个应用程序中最昂贵的方法 – 尽管事实上其他方法被调用了很多次,和/或做了更多的逻辑。 让我感到困惑的是查找仅由一个类调用; 调用方法执行查找并处理结果。 两者的调用次数几乎相同,调用查找的方法在处理查找结果时有很多逻辑,但速度提高了约100倍。 下面是哈希查找的代码。 它基本上只是对数组的两次访问(根据分析,计算哈希码的函数几乎是免费的)。 我不明白这段代码怎么会这么慢,因为它只是数组访问,我没有看到任何使它更快的方法。 请注意,代码只返回与密钥匹配的存储区,调用方应该处理存储区。 ‘size’是hash.length / 2,hash1在哈希表的前半部分进行查找,hash2在后半部分进行查找。 key_index是传递给构造函数的哈希表上的最终int字段,Entry对象上的values数组是一个通常长度为10或更短的long数组。 人们对此有任何想法都非常感激。 谢谢。 public final Entry get(final long theKey) { Entry aEntry = hash[hash1(theKey, size)]; if (aEntry != null && aEntry.values[key_index] != theKey) { aEntry = hash[hash2(theKey, size)]; if (aEntry != null && […]

这个Java代码如何加速?

我正在尝试对Java执行简单任务的速度进行基准测试:将大文件读入内存,然后对数据执行一些无意义的计算。 所有类型的优化都很重要。 无论是以不同方式重写代码还是使用不同的JVM,都会欺骗JIT。 输入文件是由逗号分隔的5亿个32位整数对列表。 喜欢这个: 44439,5023 33140,22257 … 这个文件在我的机器上需要5.5GB 。 该程序不能使用超过8GB的RAM,只能使用一个线程 。 package speedracer; import java.io.FileInputStream; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class Main { public static void main(String[] args) { int[] list = new int[1000000000]; long start1 = System.nanoTime(); parse(list); long end1 = System.nanoTime(); System.out.println(“Parsing took: ” + (end1 – start1) / 1000000000.0); int rs […]

Java:if-return-if-return vs if-return-elseif-return

问一个无关的问题 ,我有这样的代码: public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; // Check property values } 我得到了一条评论,声称这不是最优的,相反(如果我理解正确的话)应该这样做: public boolean equals(Object obj) { if (this == obj) return true; else if (obj == null) return false; else if (getClass() != obj.getClass()) return […]

根据JVM的内存粒度确定数组的最佳大小

为(例如)集合创建支持数组时,您并不真正关心所创建数组的确切大小,它只需要至少与您计算的一样大。 但是由于内存分配和VM的数组头,在某些情况下可以创建一个更大的arrays而不消耗更多的内存 – 对于Oracle 32位VM(至少这是互联网上的几个来源声称),内存粒度为8(意味着任何内存分配向上舍入到下一个8字节边界),并且数组头开销为12个字节。 这意味着在分配Object [2]时,它应该消耗20个字节(12 + 2 * 4),但由于粒度,它实际上需要24个字节。 可以为相同的内存成本创建一个Object [3],这意味着集合必须稍后调整其后备arrays的大小。 相同的原理可以应用于primitve数组,例如用于I / O缓冲区的byte [],字符串生成器中的char []等。 虽然这种优化不会产生明显的效果,但在最极端的情况下,调用静态方法来“优化”数组大小并不会太麻烦。 问题是,JDK中没有这样的“圆形arrays大小直至内存粒度”。 并且自己编写这样的方法需要确定VM的一些关键参数:内存粒度,数组头开销以及最终每种类型的大小(主要是引用的问题,因为它们的大小可能随架构和VM选项而变化)。 那么有没有一种方法来确定这些参数,或通过其他方式实现所需的“向上舍入”?

Java – 在for循环中声明变量

在循环中声明一个变量是不好的做法? 在我看来,这样做,如下面的第一个代码块所示,将使用十倍的内存作为第二个…由于在循环的每次迭代中创建一个新的字符串。 它是否正确? for (int i = 0; i < 10; i++) { String str = "Some string"; } 与 String str; for (int i = 0; i < 10; i++) { str = "Some String"; }

在Java中访问最终局部变量比使用类变量更快吗?

我一直在研究一些java原始集合( trove , fastutil , hppc ),我注意到一个模式,类变量有时被声明为final局部变量。 例如: public void forEach(IntIntProcedure p) { final boolean[] used = this.used; final int[] key = this.key; final int[] value = this.value; for (int i = 0; i < used.length; i++) { if (used[i]) { p.apply(key[i],value[i]); } } } 我做了一些基准测试,看起来这样做的速度稍微快一点,但为什么会这样呢? 我试图理解如果函数的前三行被注释掉,Java将采取哪些不同的做法。 注意:这似乎与这个问题类似,但那是针对c ++的,并没有说明为什么它们被声明为final 。

Java中哪一段代码更快?

a) for(int i = 100000; i > 0; i–) {} b) for(int i = 1; i < 100001; i++) {} 答案就在这个网站上 (问题3)。 我只是想不通为什么? 来自网站: 3. a