Влияет ли длина имени объекта на производительность программы в случае отражения? - PullRequest
0 голосов
/ 08 ноября 2018

в случае использования отражения мы получаем доступ к сущностям по их именам, закодированным в такие строки, как эта m = getMethod("someMethod"). Чтобы найти запрошенный объект, необходимо выполнить сравнение строк. Означает ли это, что длина имени объекта влияет на производительность. Если это так, насколько это влияет на производительность?

1 Ответ

0 голосов
/ 08 ноября 2018

Ответ сильно зависит от используемой вами виртуальной машины Java. Я написал тестовую программу, просто чтобы получить некоторые цифры для JVM 1.8.0_05 (да, он старый; -):

import java.lang.reflect.Method;


public class ReflectionAccessTest {

    public final static void main(String[] args) throws Exception {
        for (int i = 0; i < 100000; i++) {
            // do some "training"
            ReflectionTarget.class.getMethod("a", Integer.TYPE, Integer.TYPE);
            ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
            ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
        }

        Method method = null;;
        long start;

        start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            // do some "training"
            method = ReflectionTarget.class.getMethod("a", Integer.TYPE, Integer.TYPE);
        }
        System.out.println("Time to get method with short name " + (System.currentTimeMillis() - start) + " ms");
        start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            method.invoke(null, Integer.MAX_VALUE, Integer.MIN_VALUE);
        }
        System.out.println("Time to execute method with short name " + (System.currentTimeMillis() - start) + " ms");

        start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            // do some "training"
            method = ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
        }
        System.out.println("Time to get method with medium name " + (System.currentTimeMillis() - start) + " ms");
        start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            method.invoke(null, Integer.MAX_VALUE, Integer.MIN_VALUE);
        }
        System.out.println("Time to execute method with medium name " + (System.currentTimeMillis() - start) + " ms");

        start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            // do some "training"
            method = ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
        }
        System.out.println("Time to get method with long name " + (System.currentTimeMillis() - start) + " ms");
        start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            method.invoke(null, Integer.MAX_VALUE, Integer.MIN_VALUE);
        }
        System.out.println("Time to execute method with long name " + (System.currentTimeMillis() - start) + " ms");
    }

    private static class ReflectionTarget {
        public static void a(int a, int b) {
            // do nothing
        }

        public static void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(int a, int b) {
            // do nothing
        }

        public static void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(int a, int b) {
            // do nothing
        }
    }
}

Вывод выглядит следующим образом:

Time to get method with short name 1012 ms
Time to execute method with short name 58 ms
Time to get method with medium name 3690 ms
Time to execute method with medium name 177 ms
Time to get method with long name 6279 ms
Time to execute method with long name 180 ms

Время на самом деле зависит от длины имени (это меня сначала удивило, но с другой стороны, это очевидно, потому что должен быть какой-то тест на равенство, который зависит от длины).

Но вы также можете видеть, что воздействие незначительно. Вызов getMethod занимает 0,1 наносекунды для метода с именем, содержащим только один символ, и 0,6 наносекунды для метода с сумасшедшим длинным именем (не считая число a с).

Если это различие действительно актуально для вас, вы можете попробовать механизмы кэширования полученного вами метода. Но в зависимости от времени, которое занимает вызываемый метод, это может быть совершенно бесполезно, если время его выполнения также не находится в диапазоне суб-наносекунд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...