Могу ли я использовать один метод в Java в качестве таймера для других методов? - PullRequest
2 голосов
/ 08 апреля 2011

При тестировании среды выполнения я использую System.nanotime () следующим образом:

startTime = System.nanotime();

// some statements

System.out.println("Runtime: " + (System.nanoTime() - startTime));

Есть ли способ повторно использовать эту тестовую модель для других блоков кода в моих программах?Другими словами, могу ли я создать это как метод и передать ему другие методы во время тестирования?

Ответы [ 4 ]

3 голосов
/ 08 апреля 2011

Да, вы можете, но это даже сложнее, чем ваш подход:

time(new Runnable() {
    public void run() {
        System.out.println("statements");
    }
});

static void time(Runnable r) {
    long startTime = System.nanoTime();
    r.run();
    System.out.println("Runtime: " + (System.nanoTime() - startTime));
}

В Java 7 это станет немного проще (я пропустил реализацию 'Measure'):

try (Measure m = new Measure()) {
    System.out.println("statements");
}

Кстати, лучше использовать System.nanoTime(), чем System.currentTimeMillis(), не только потому, что первое является более точным, но и потому, что позднее произойдет сбой вокруг летнего изменения (или других системных изменений).

3 голосов
/ 08 апреля 2011

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

См. http://dhruba.name/2008/12/16/spring-aop-timing-aspect/

2 голосов
/ 08 апреля 2011

Профилировщик: Я действительно предпочитаю запускать код через профилировщик.Я действительно заинтересован в узких местах, и я предполагаю, что это то, что вы после.

Существуют и другие альтернативы.

JUnit и JPerf: Если у вас есть тесты junit, то использование jperf - это очень просто.

Динамический прокси: Если в вашем приложении есть интерфейсы и если вас интересуют только вызовы интерфейса, создайте динамический прокси и используйте его для отметки времени.

Объект секундомера: Более простой подход, чем ваш, - создать объект секундомера (у apache commons есть один), с методами start, pause, resume, lap stop и использовать его.Это работает лучше, чем ваш код, так как экземпляры секундомера могут использоваться с обратными вызовами, событиями и потоками.

AOP: Кроме профилировщиков почти все вышеперечисленные опции могут быть реализованы с использованием пользовательского кода, ноесли вы достаточно любопытны, чтобы изучить АОП, это было бы здорово.

0 голосов
/ 08 апреля 2011

Три дополнительных ответа.Сначала (относительно) очевидный:

for (long t = start(); end(t);) {
    System.out.println("statement");
}

static long start() {
    return System.nanoTime();
}

static boolean end(long startTime) {
    System.out.println("Runtime: " + (System.nanoTime() - startTime));
    return false;
}

Странный, с тем недостатком, что вы получаете предупреждение (переменная v никогда не читается).Интересно, можно ли это улучшить:

for (Void v : time()) {
    System.out.println("statement");
}

static Iterable<Void> time() {
    return new Iterable<Void>() {
        long startTime = System.nanoTime();
        boolean done;
        public Iterator<Void> iterator() {
            return new Iterator<Void>() {
                public boolean hasNext() {
                    if (!done) {
                        done = true;
                        return true;
                    }
                    System.out.println("Runtime: " + (System.nanoTime() - startTime));
                    return false;
                }
                public Void next() {
                    return null;
                }
                public void remove() {
                }
            };
        }
    };
}

И обман:

while(time()) {
    System.out.println("statement");
}

static boolean stop;
static long startTime;
static boolean time() {
    if (!stop) {
        startTime = System.nanoTime();
    } else {
        System.out.println("Runtime: " + (System.nanoTime() - startTime));
    }
    return stop = !stop;
}
...