Измерьте время выполнения асинхронного метода - PullRequest
0 голосов
/ 31 мая 2018

У меня есть асинхронный метод, в котором я использую DeferredResult в качестве возвращаемого типа.Я хочу написать тест junit для этого метода, где я вызываю этот метод в цикле, например, 100 раз, и мне нужно измерить время выполнения для каждого вызова этого метода.

Вот пример метода:

@Transactional(readOnly = true)
@Override
public DeferredResult foo() {
    DeferredResult dr = new DeferredResult(5000L, "timeout");
    dr.onCompletion(() -> {
        // do some stuff
    });
    deferredResults.add(dr);

    return dr;        
}

создал deferredResult, который я добавляю в коллекцию, и повторяю эту коллекцию в другом методе, в котором я устанавливаю некоторый результат, а затем возвращается dr.

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

@Test
public void executionTimeTest() {
    for (int i = 0; i < 100; i++) {
        asyncService.foo();
    }

    // here I need get execution time for each call
}

Спасибо.

1 Ответ

0 голосов
/ 01 июня 2018

Я думаю, что лучший способ решить этот вопрос - добавить дополнительные данные в класс DeferredResult, как это рекомендовано spring docs .Точно, следующее предложение в весенних документах указывает на эту возможность.

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

Учитывая эту возможность, вы можете расширить DeferredResult и добавить время начала и окончания:

public class MyDeferredResult extends DeferredResult {

    long startTime;
    long endTime;

    public MyDeferredResult(Long timeout, Object timeoutResult) {
        super(timeout, timeoutResult);
        this.startTime = System.currentTimeMillis();
    }

    @Override
    public boolean setResult(Object result) {
        boolean r = super.setResult(result);
        this.endTime = System.currentTimeMillis();
        return r;
    }

    public long totalTime() {
        return (endTime - startTime)/1000;
    }

}

Тогда ваша асинхронная служба может быть похожа на эту:

 public MyDeferredResult foo() {
    MyDeferredResult dr = new MyDeferredResult(5000L, "timeout");
    new Thread(() -> {
        Random r = new Random();
        System.out.println("async task started");
        try {
            Thread.sleep(r.nextInt(4) * 1000 );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("async task finished");
        dr.setResult("test async result");
    }).start();
    deferredResults.add(dr);
    return dr;
}

boolean hasResults() {
    boolean result = true;
    for(MyDeferredResult dr: deferredResults) {
        result = result && dr.hasResult();
    }
    return result;
}

Наконец, в вашем тесте вы можете получить общее время каждого выполнения:

   @Test
    public void executionTimeTest() {
        Service service = new Service();
        for (int i = 0; i < 10; i++) {
            service.foo();
        }

       while (!service.hasResults()) {
            System.out.println("No result yet");
       }

        for(MyDeferredResult dr: service.deferredResults) {
            System.out.println(dr.totalTime());
        }
    }
...