【问题标题】:Number to String conversion performance with java on ARM v6在 ARM v6 上使用 java 的数字到字符串转换性能
【发布时间】:2014-04-01 17:00:18
【问题描述】:

我在 ARM v6 处理器上运行 Java 软件。这个程序的性质要求我将一些数字(int 或 float)转换为 String。处理器以 850Mhz 运行。 Java Runtime 是 OpenJDK Zero VM 1.7.0_21-b02。

我并不期待这里有坚如磐石的性能,但我希望比我在下面的代码 sn-p 看到的更有效。

    long time1, time2;

    float[] src = new float[2000000];
    for (int i = 0; i < src.length; i++) {
        src[i] = (float)Math.random()* 2.56454512f * (float) Math.random();
    }
    time1 = System.nanoTime();
    for (int j = 0; j < src.length; j++) {
        String test = String.valueOf(src[j]);
    }
    time2 = System.nanoTime();
    logTimeDelay("String.valueOf", time1, time2);

    time1 = System.nanoTime();
    for (int j = 0; j < src.length; j++) {
        String test = Float.toString(src[j]);
    }
    time2 = System.nanoTime();
    logTimeDelay("Float.toString", time1, time2);


    StringBuilder sb = new StringBuilder(50);
    time1 = System.nanoTime();
    for (int j = 0; j < src.length; j++) {
        sb.setLength(0);
        sb.append(src[j]);
    }
    time2 = System.nanoTime();
    logTimeDelay("StringBuilder.append, setLength", time1, time2);

    time1 = System.nanoTime();
    for (int j = 0; j < src.length; j++) {
        String test = "" + src[j];
    }
    time2 = System.nanoTime();
    logTimeDelay("\"\" + ", time1, time2);

    private static void logTimeDelay(String message, long time1, long time2){
        System.out.println(String.format(message + ": %.5f s", (float) (time2 - time1) / 1.0e9));
    }

在我的 i7 电脑上运行这段代码 sn-p 会返回以下结果:

String.valueOf: 0.39714 s
Float.toString: 0.33295 s
StringBuilder.append, setLength: 0.33277 s
"" + : 0.37581 s

在 ARMv6 处理器上运行完全相同的代码 sn-p 会返回以下值:

String.valueOf: 204.78758 s
Float.toString: 200.79659 s
StringBuilder.append, setLength: 180.81551 s
"" + : 267.63036 s

关于如何在此设备上优化我的数字到 int 转换的任何线索?

提前致谢。

【问题讨论】:

  • 对arm了解不多...L1/L2指令/数据缓存的大小是多少?
  • 该处理器是双 CPU ARM11MPcore,运行频率为 850MHz,具有 32KB 指令缓存和 32KB 数据缓存。
  • 这是L1;如果有的话,L2 呢?
  • 有一个 LEON2 协处理器可用,但我不相信有任何 L2 缓存。

标签: java string arm type-conversion armv6


【解决方案1】:

“凭空出现”的假设,但您在此处观察到的性能差异似乎与 CPU 缓存有关;您的 ARM CPU 的缓存远少于台式机的 i7。

您的浮点数组中有两个 millions 元素;这使得至少 8 MB 的存储空间。这 8 MB 需要到达 CPU。

我这里也有一个i7,缓存大小是:32kb (L1), 256kb (L2), 6MB (L3);四分之三的浮点数组可以放入 L3!在您的情况下,似乎一次只能有 32kb ......因此有很多缓存抖动并且内存总线流量非常高。

我怀疑如果您将数组大小减小到适合 32kb 的大小(例如,尝试仅使用 1000 个浮点数),性能数据会更接近。

编辑:您的 CPU 也没有 FPU;正如@Voo 所提到的,这占了性能损失的大部分。

所以:

  • 缺少 FPU,
  • 小缓存,
  • 大量数据。

要进行更“真实”的比较,您应该对较小的数据子集进行测试;这至少会缓解(但不能完全消除)缓存问题。

【讨论】:

  • 考虑到一开始的内存访问量很少,不太可能。更有可能的是,并非所有 ARMv6 合唱团都具有 hw float 协处理器,考虑到除法重字符串转换的程度,这相当糟糕。此外,基准测试(通常)一开始就完全被打破,不同的 JVM 处理得也不同(OSR 活跃?)
  • 感谢您对此的意见。我知道我的 ARM 处理器和 i7 的缓存和处理能力存在显着差异。这是不言而喻的。但是,我对各种数据处理中的性能有多好感到困惑……但是当涉及到数字到字符串的转换时,性能却很糟糕。尤其是浮点数和双精度数。显然,整数并没有那么糟糕。使用 200000 int 的 int[] 进行相同的测试会产生 String.valueOf: 27.49648 s Integer.toString: 25.84437 s StringBuilder.append, setLength: 11.58025 s "" + : 96.30360 s
  • @Voo 也许是这样,但在我看来它仍然是的一个因素;当您的缓存只有 32 KiB 时,我不会考虑访问 8MB 的“低成本”操作
  • @crazy 首先阅读了如何在 Java 中正确地对代码进行基准测试,这将为您在未来节省许多惊喜。然后检查你的 CPU 是否有浮点单元。
  • @crazydread18 那么 Voo 可能对这里缺少 FPU 有意见
猜你喜欢
  • 1970-01-01
  • 2011-03-25
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多