安卓手机上大整数方法'add'的性能



我一直在为我的硕士论文研究Java中的加密(POT)协议。它使用加密配对,因此使用名为jPBC的外部java库(http://gas.dia.unisa.it/projects/jpbc/)。

由于我希望协议的一侧在移动设备上运行,我在Android ADT中制作了一个简单的GUI,其中包含启动协议的单个按钮。然而,该协议在我的手机(三星S2 plus, ARM Cortex A9 32位处理器)上的运行速度比我的笔记本电脑(英特尔酷睿i7,但只使用半核)上的运行速度慢了大约200倍。由于处理器的差异可以解释因子10,但肯定不能解释因子100/200,所以我认为性能差异可能是由于Android上jPBC库的低效率造成的。

jPBC库广泛使用BigInteger进行所有的计算,所以我决定调查BigInteger在android上是否会特别低效(它在普通计算机上也不是超级高效)。我在手机和笔记本电脑上执行了一个1200位BigInteger计算的循环。我得出了一些我无法解释的结果:

加法和减法在笔记本电脑上花费205ms,在手机上花费 48025ms (x 200)

10^5乘法和除法在笔记本电脑上需要814毫秒,在手机上需要13 705ms (× 17)。

10^3模幂运算(modPow)在笔记本电脑上需要5079ms,在手机上需要22153ms (x 4.5)

由于这些结果有很多可说的,我只坚持这个简单的问题:

谁能重现这些结果并确认BigInteger加法在Android上非常慢,或者告诉我我做错了什么?

代码:

Java方法:

public static long bigIntCalculations(){
    System.out.println("starting bigIntCalculations");
    Random random = new Random();
    BigInteger start = new BigInteger(1200, random);
    BigInteger temp = new BigInteger(start.toString());
    long nOfIterations = 1000000L;
    long time1 = System.nanoTime()/1000000;
    for (long i = 0; i < nOfIterations; i++) {
        start = start.add(temp);
        start = start.subtract(temp);
    }
    long result = (System.nanoTime()/1000000)-time1;
    System.out.println(result);
    return result;
}
在Android:

/** Called when the user clicks the button1*/
public void runProtocol(View view) {
long duration = Test.bigIntCalculations();
String result ="Calculations take: " + duration + " ms";    
Intent intent = new Intent(this, DisplayMessageActivity.class);
            intent.putExtra(CALC_RESULT, result);
            startActivity(intent);  
}

多谢!

考虑到性能不足的硬件,仅x4.5进行1200位模块化幂运算是一个了不起的结果。这也证明了JDK的BigInteger实现有多糟糕。

Android标准库使用OpenSSL BigNum进行一些底层操作。我猜模幂和模逆是在本机代码中处理的,而更简单的算术是在Java代码中处理的。

对于加法和乘法的紧密循环,您将生成大量垃圾,并且平台之间的GC性能差异也可能产生很大的影响——我的猜测是一些热身+一个小得多的基准测试将显示更接近的结果。

我的性能痛点是模块化幂,所以我对Android的性能非常满意。如果不是这样,我会考虑将gmp4j或gmp-java(两个同名库)等库移植到Android上。其中两个提供了与biginteger兼容的API。另一个提供了更直接的映射到GMPLib,这在内存管理方面是理想的(GMP编号是可变的)。

最新更新