Java 中使用 jna 调用 dll 函数,性能很差

// mydll.c
__declspec(dllexport) double test(double a, double b)
{
    return a / b - 1;
}
// test.java

import com.sun.jna.Native;
import com.sun.jna.Library;

public class test {
    public interface DLL extends Library {
        DLL INSTANCE = (DLL)Native.load("mydll", DLL.class);
        double test(double a, double b);
    }

    public static void main(String[] args) {        
        DLL dll = DLL.INSTANCE;
        long st = System.nanoTime();
        dll._conformance(3.234, 4.234);
        System.out.println("耗时: " + String.valueOf(System.nanoTime() - st));
    }
}
// 耗时: 6795340

import time
from ctypes import *

dll = CDLL("mydll.dll")
dll.test.restype = c_double

def invoke():
    st = time.time_ns()
    dll.test(c_double(3.234), c_double(4.234))
    print("耗时: ", time.time_ns() - st)

invoke()
# 耗时: 0

为什么 jna 调用一次 dll函数,都是 毫秒级的?怎么样能达到 python 那样的调用速度?

JNA 调用 dll 函数是毫秒级的,这主要是因为它将调用转换为 Java Native Interface (JNI)调用,以帮助实现编程语言之间的互操作性。它将功能转换成,当调用dll函数时,它会将操作放入JNI调用并完成,从而大大缩短了调用时间。

要达到与Python一样的调用速度,需要采用类似JNI这样的库,以帮助提高调用速度。此外,可以考虑使用多线程来调用dll函数,充分利用CPU的资源,以便更好地使用现有计算机资源,进一步提高调用速度。

你试试通过接口去调用,感觉你这样写是不是要先去加载库函数,没有加载到缓存里面,这个时间是计算了加载JNI库函数的时间

JNA 与 JNI 调用对比,第一次是慢不少。但 JNI 调用速度还是达不到 python 调用速度

// JNITest.java

public class JNITest {

    static {
        System.loadLibrary("mydllJNI");
    }

    public native double test(double a , double b);
};
// test.java
import com.sun.jna.Native;
import com.sun.jna.Library;
 
public class test {
    public interface DLL extends Library {
        DLL INSTANCE = (DLL)Native.load("mydll", DLL.class);
        double test(double a, double b);
    }
 
    public static void main(String[] args) {        
        DLL dll = DLL.INSTANCE;
        JNITest jt = new JNITest();
        long st, et;
        for (int i = 0; i < 10; i++) {
            st = System.nanoTime();
            dll.test(3.234, 4.234);
            et = System.nanoTime();
            System.out.println(i + "次耗时: " + (et - st));
        }
        for (int i = 0; i < 10; i++) {
            st = System.nanoTime();
            jt.test(3.234, 4.234);
            et = System.nanoTime();
            System.out.println(i + "次耗时: " + (et - st));
        }
    }
}
次数JNA耗时(ns)JNI耗时(ns)
第1次调用64712634976
第2次调用28924623
第3次调用23948622
第4次调用42919311
第5次调用18972311
第6次调用14618622
第7次调用14929623
第8次调用14306311
第9次调用14618311
第10次调用14618311