Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用访问器/获取器可以更快吗? >背景>:>我计划从C++到java。代码处理大小为n的d维点列表,需要计算标量积等。我想让我的代码独立于点的存储格式,并为此目的引入了一个接口 公共接口点集访问器 { 浮动坐标(INTP、INTC); }_Java_Performance_Jvm Hotspot - Fatal编程技术网

使用访问器/获取器可以更快吗? >背景>:>我计划从C++到java。代码处理大小为n的d维点列表,需要计算标量积等。我想让我的代码独立于点的存储格式,并为此目的引入了一个接口 公共接口点集访问器 { 浮动坐标(INTP、INTC); }

使用访问器/获取器可以更快吗? >背景>:>我计划从C++到java。代码处理大小为n的d维点列表,需要计算标量积等。我想让我的代码独立于点的存储格式,并为此目的引入了一个接口 公共接口点集访问器 { 浮动坐标(INTP、INTC); },java,performance,jvm-hotspot,Java,Performance,Jvm Hotspot,这允许我得到第c坐标(0≤ c

这允许我得到第c坐标(0≤ c 问题:由于代码必须非常快,我想知道这是否会降低性能,与像
points[p][c]
这样的直接访问模式相比,
points
是一个由n个数组组成的数组,每个数组都保持d点坐标

令人惊讶的是,情况正好相反:通过
PointSetAccessor
的“间接”访问,代码(见下文)的速度提高了20%。(我使用
timejava-server-XX:+AggressiveOpts-cp bin Speedo测量了这个值,前者得到14秒左右,后者得到11秒左右。)

问题:知道为什么会这样吗?似乎Hotspot决定更积极地进行优化,或者在后一版本中有更大的自由度进行优化

代码(用于计算无意义):

公共级Speedo
{
公共接口点集访问器
{
浮动坐标(INTP、INTC);
}
公共静态最终类ArrayPointSetAccessor实现PointSetAccessor
{
专用最终浮点[][]数组;
公共阵列点集访问器(浮点[][]阵列)
{
this.array=数组;
}
公共浮动坐标(整数点,整数dim)
{
返回数组[点][dim];
}
}
公共静态void main(字符串[]args)
{
最终整数n=50000;
最终积分d=10;
//在维度d中生成n个点
final java.util.Random r=new java.util.Random(314);
最终浮动[][]a=新浮动[n][d];
对于(int i=0;i
如果这些短方法是热的(使用默认设置调用超过10000次),它们将由hotspot内联,因此您不应该注意性能的差异(测量性能的方式忽略了许多影响,例如预热时间,这可能会导致错误的结果)

当运行代码并要求hotspot显示什么是内联的(
-server-XX:+UnlockDiagnosticVMOptions-XX:+PrintCompilation-XX:+PrintInline
)时,您会得到以下输出,这表明
coord
product
都是内联的:

 76    1 %           javaapplication27.Speedo::main @ -2 (163 bytes)   made not entrant
 77    6             javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes)
 78    7             javaapplication27.Speedo::product (45 bytes)
                        @ 18   javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes)   inline (hot)
                        @ 27   javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes)   inline (hot)
 80    2 %           javaapplication27.Speedo::main @ 101 (163 bytes)
                        @ 118   javaapplication27.Speedo::product (45 bytes)   inline (hot)
                          @ 18   javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes)   inline (hot)
                          @ 27   javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes)   inline (hot)

如果您真的担心性能,那么您应该研究去掉二维数组(用一维数组替换)会给您带来什么

java中的多维数组比大多数其他语言中的多维数组成本更高,因为java将它们实现为数组数组(即N维的数组,任何小于N维的数组都是对下一维的引用数组)

对于浮点数[50000][10],这意味着有一个包含50000个浮点数[10]引用的数组。因为每个数组也是一个对象(有几个字节的头)。由于最后一个维度非常小(10),因此在内存使用方面,开销非常大(反向大小写float[10][50000]的内存占用空间非常小)

尝试这样的内存布局:

public static final class ArrayPointSetAccessor implements PointSetAccessor {
    private final int dimSize;
    private final float[] array;

    public ArrayPointSetAccessor(float[] array, int dimSize) {
        this.dimSize = dimSize;
        this.array = array;
    }

    public float coord(int point, int dim) {
        return array[dim * dimSize + point];
    }
}

我希望访问器在一个非平凡的场景中(例如,当接口有多个实现时)会降低一点性能。但无论如何还是要使用访问器界面——灵活性和可维护性通常比性能的几%更重要。

最有可能的是,您的微基准存在缺陷。切换测试顺序和直接/间接,看看它对结果的影响有多大。为了避免预热问题,在测量之前至少执行一次整个测试套件。正确!在扩展程序以运行两次测试(在同一个VM中)并测量第二次调用的CPU时间之后,我确实看到有时这两个变量的速度相等。然而,有时并非如此——在这些情况下,
PointSetAccessor
更快(在我的实验中)。我还没有发现为什么有时候“直接”方法会慢一些。谢谢,@Durandal。在此期间,我们了解了更多关于JVM基准测试的知识,应该使用类似的方法。感谢您的评论,我验证了这一点:使用一维数组确实会稍微快一点是的,内存占用更好。事实上,内联可以在编译之前发生,请参见。