Измерьте время выполнения асинхронного метода
У меня есть асинхронный метод, где я использую 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 ответ
Я думаю, что лучший способ решить этот вопрос - добавить дополнительные данные в класс 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());
}
}