简体   繁体   中英

Why is Java reflection invokation faster than method call?

I made the discovery and tested it with my application. I'm calling and invoking the same method.

I tried different consecutive executions and also different methods (encryption, sorting, etc...) and got the following results.

Executions|Invoke-Call ratio

1         | 62,78%

10        | 107,58%

100       | 76,74%

1000      | 80,01%

10000     | 116,88%

100000    | 82,80%

1000000   | 91,67%

I checked if it might be the use of multiple threads but it's not from what I can tell. What could be the explanation?

For further clarification an excerpt of my benchmark: The invoke part:

Executable executable = new Executable();
Method execute = executable.getClass().getMethod("execute");
System.out.println("# Startup finished.");
for (float i = 0; i <= 6; i++)
{
    int executions = (int) Math.pow(10, i);
    long start = System.nanoTime();
    for (int j = 0; j <= executions - 1; j++)
    {
        execute.invoke(executable);
    }
    long stop = System.nanoTime();
    long delta = stop - start;
    System.out.println("Invoke;" + executions + ";" + delta);
}
System.out.println("# Shutdown finished.");

The call part:

Executable executable = new Executable();
System.out.println("# Startup finished.");
for (float i = 0; i <= 6; i++)
{
    int executions = (int) Math.pow(10, i);
    long start = System.nanoTime();
    for (int j = 0; j <= executions - 1; j++)
    {
        executable.execute();
    }
    long stop = System.nanoTime();
    long delta = stop - start;
    System.out.println("Invoke;" + executions + ";" + delta);
}
System.out.println("# Shutdown finished.");

For this example of Executable class I have taken extra caution to exclude all preparation work from the execute method.

public class Executable
{
    private int index = 0;
    private int testsize = 1111111;
    private byte[][] plain = new byte[testsize][];
    private byte[][] hashed = new byte[testsize][];
    private SecureRandom securerandom;
    private MessageDigest messagedigest;

    public Executable()
    {
        this.securerandom = new SecureRandom();
        this.messagedigest = MessageDigest.getInstance("SHA-256");
        for (int i = 0; i <= testsize - 1; i++)
        {
            this.plain[i] = new byte[8];
            this.securerandom.nextBytes(this.plain[i]);
        }
    }

    public void execute()
    {
        messagedigest.update(this.plain[index]);
        this.hashed[index] = messagedigest.digest();
        index++;
    }
}

Just for sake of interested persons the code works as expected and the call is faster than invoke.

# Startup finished.
Invoke  1   1683969
Invoke  10  1876447
Invoke  100 23376245
Invoke  1000    29035955
Invoke  10000   55816067
Invoke  100000  209290359
# Shutdown finished.
# Startup finished.
Call    1   64587
Call    10  18820
Call    100 209160
Call    1000    1656594
Call    10000   17318746
Call    100000  167565824
# Shutdown finished.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM