Как оценить время выполнения метода, когда он вызывается с помощью Java Reflection - PullRequest
0 голосов
/ 07 апреля 2011

привет, может кто-нибудь помочь мне в этом вопросе

Я вызываю метод «add» класса «CustomeMath», теперь я хочу знать время выполнения, затраченное только методом addMe () (это время не включает время выполнения, взятое методом «Invoke ()» рефлексии для вызова некоторого метода.). Я публикую общий код этой проблемы.

import java.lang.reflect. *;

публичный класс CustomeMath { public int addMe (int a, int b) { вернуть a + b; }

 public static void main(String args[])
 {
    try {
      Class cls = Class.forName("CustomeMath");
      Class partypes[] = new Class[2];
       partypes[0] = Integer.TYPE;
       partypes[1] = Integer.TYPE;
       Method meth = cls.getMethod(
         "addMe", partypes);
       CustomeMath methobj = new CustomeMath();
       Object arglist[] = new Object[2];
       arglist[0] = new Integer(37);
       arglist[1] = new Integer(47);
       Object retobj 
         = meth.invoke(methobj, arglist);
       Integer retval = (Integer)retobj;
       System.out.println(retval.intValue());
    }
    catch (Throwable e) {
       System.err.println(e);
    }
 }

}

Теперь я хочу получить время выполнения, взятое методом "addMe ()" . И это время не включает время, затраченное методом "invoke ()" . Как я могу получить это время? ( Помните, я не хочу использовать "System.currentTimeMillis ();" )

Ответы [ 3 ]

1 голос
/ 07 апреля 2011

Чтобы проверить проблемы с производительностью, вы обычно используете профилировщики, затем сделаете несколько вариаций своего алгоритма и сравните их производительность в профилировщике.Это одна из основных целей профилировщиков, я бы сказал, что это гораздо лучше, чем пытаться предложить решение, разработанное собственными силами, которое может дать или не дать вам надежные результаты.Их довольно много, у меня очень хороший опыт работы с YourKit

И - я думаю, что профилировщик является обязательным инструментом для любого серьезного разработчика, независимо от языка программирования в любом случае ...

1 голос
/ 07 апреля 2011

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

public static int addMe(int a, int b) {
    return a + b;
}

public static void main(String args[]) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
    Method addMe = CustomeMath.class.getMethod("addMe", int.class, int.class);
    int result = (Integer) addMe.invoke(null, 37, 47);
    System.out.println(result);

    int runs = 10000000;
    {
        long start = System.nanoTime();
        for (int i = 0; i < runs; i++)
            addMe(i, 10);
        long time = System.nanoTime() - start;
        System.out.printf("The average call time was %.1f ns%n", (double) time / runs);
    }
    {
        long start = System.nanoTime();
        for (int i = 0; i < runs; i++)
            addMe.invoke(null, i, 10);
        long time = System.nanoTime() - start;
        System.out.printf("The average call time using reflections was %.1f ns%n", (double) time / runs);
    }
}

печать

84
The average call time was 1.4 ns
The average call time using reflections was 670.1 ns

Домашнее задание для вас;

  • Можете ли вы предположить, почему существует такая разница?
  • Почему вы можете получить другой результат в более реалистичном примере?
1 голос
/ 07 апреля 2011

Если вы хотите измерить время с некоторой точностью, вы должны использовать System.nanoTime(). Назовите самую первую строку addMe() и снова вызовите последнюю строку, вычислите разницу и напечатайте ее, помните, что это наносекунды.

Если вы хотите измерить время выполнения извне (в main) без учета накладных расходов invoke(), вы просто не сможете.

System.currentTimeMillis() выполняется очень быстро по сравнению с System.nanoTime(), но имеет низкую точность (несколько миллисекунд), поэтому будьте осторожны, если addMe() выполняется быстро, поскольку измеренное время не может быть релевантным. Если вы хотите измерить время выполнения очень быстрого метода, обычно вы выполняете тысячи методов в цикле и измеряете общее время выполнения всего двумя вызовами System.nanoTime(), поскольку накладные расходы, связанные с измерением времени, могут быть больше времени выполнения самого метода.

...