Микробенчмаркинг: как тестировать программы шаг за шагом
Микробенчмаркинг - модное понятие в программировании в 2021 году. Представляет собой программу или действия по оценке и тестированию функциональности как отдельного компонента, так и задачи. В то же время, не все признают его эффективность. Как провести микробенчмаркинг с наибольшей пользой для продукта и наименьшей потерей ресурсов, поговорим в материале.
Микробенчмаркинг позволяет измерить такие параметры, как затраченное время, скорость операции, пропускная способность и задержка. Как правило, микробенчмаркинг ассоциируется с тестированием подпрограмм ПО или аппаратного обеспечения более низкого уровня, например, оперативной памяти, за короткий промежуток времени.
Например, микробенчмаркинг поможет измерить влияние криптографического шифрования на аппаратное обеспечение, с использованием VPN и набора протоколов для защиты данных IPsec.
Что касается сферы больших данных, здесь микробенчмаркинг включает в себя кластер - группу компьютеров, подключенных к одной сети. Эти машины действует как одна система, Интернет вещей. В таком случае микробенчмаркинг подразумевает тестирование фреймворков, алгоритмов, логических и дистрибутивных компонентов, в течение длительного периода времени.
Как проводить микробенчмаркинг?
Микробенчмаркинг помогает определить, как поведет себя ход после релиза программы.
Сложно оценить полноценное приложение и его возможное поведение после выведения на рынок. Ведь профайлинг не укажет на проблему с конкретной частью кода. Более того, профайлинг учитывает внешние факторы, например, логи, и предоставляет довольно реалистичные результаты. Но, в свою очередь, микробенчмаркинг концентрируется на определенной части кода.
Находятся критики, которые считают микробенчмаркинг субъективной деятельностью. Указывают, что можно запутаться, проделав оптимизацию кода и обобщив полученные результаты. Кроме того, машинная архитектура сервера продукции может полностью отличаться от того устройства, которое используется непосредственно для микробенчмаркинга.
В то же время, микробенчмаркинг поможет ответить на два вопроса при обзоре кода:
- Могу ли я прервать цикл?
- Можно ли упростить алгоритм?
Как правило, разработчик тестирует приложение традиционным способом. Но порой привычные вещи невозможно осуществить. Например, вы создаете базовую вспомогательную инфраструктуру для ряда приложений или целую библиотеку. При этом, нельзя оптимизировать код, воспользовавшись специфическими сценариями. В этом случае, вам поможет микробенчмаркинг.
Проведём микробенчмаркинг вместе
Попробуем проанализировать часть кода. Цель - написать программу, чтобы подсчитать число Армстронга, а именно, натуральное число, равное сумме цифр, возведенный в число, равносильное количеству цифр.
Для начала определим isNarNumber(), чтобы проверить, является ли конкретное число числом Армстронга.
public class NarcissisticNumber {
2
3
public static boolean isNarNumber(int number) {
4
int length = String.valueOf(number).length();
5
int sum = 0;
6
7
for (int i = number; i > 0; i = i / 10) {
8
sum += pow(i % 10, length);
9
}
10
11
return sum == number;
12
}
13
14
}
Дальше определим метод findNarcissisticNumber() для получения дальнейших результатов.
public class NarcissisticNumber {
2
...
3
4
public static int findNarcissisticNumber(int n) {
5
int pointer = 0;
6
int i;
7
8
for (i=1; i<Integer.MAX_VALUE && pointer < n; i++) {
9
if (isNarNumber(i)) {
10
pointer = pointer+1;
11
}
12
}
13
14
return i;
15
}
16
}
После этого быстро определим время выполнения findNarcissisticNumber, используя System.currentTimeMillis().
1
public class NarcissisticNumber {
2
...
3
public static void main(String[] args) {
4
int result;
5
long before = System.currentTimeMillis();
6
7
for (int i = 0; i < cycles; i++) {
8
result = findNarcissisticNumber(20);
9
}
10
11
long after = System.currentTimeMillis();
12
System.out.println("Time elapsed: " + (after-before)/cycles
+ "
seconds"
);
13
}
14
}
Учимся избегать ловушек
Описанный подход к микробенчмаркингу может не сочетаться с виртуальной машиной JVM.
Java Virtual Machine является довольно сложным механизмом и способна сама по себе оптимизировать код. Такие параметры JVM, как JIT-компиляция и сборка мусора (garbage collection), затрудняют процесс самостоятельного обзора кода. Поэтому, проводя микробенчмаркинг, учитывайте несколько факторов.
Во-первых, JVM оптимизирует код с каждым новым спринтом. Чем быстрее выполняется код, тем дольше его анализирует виртуальная машина. Есть риск отказа от периода разогрева. Поэтому, проводя микробенчмаркинг, учитывайте цикл разогрева, прежде чем позволить JVM оптимизировать код.
1
for (int i = 0; i < warmupCycles; i++) {
2
result = findNarcissisticNumber(20);
3
}
4
5
6
for (int i = 0; i < cycles; i++) {
7
result = findNarcissisticNumber(20);
8
}
Во-вторых, даже если вы приняли во внимание цикл разогрева, время выполнения может обозначиться как нулевое. Так как результат нигде не используется, JVM может отменить цикл. Также компилятор может выполнить частичную итерацию, что приведет к необъективному результату. Чтобы устранить возможные проблемы на этой стадии, стоит уделять больше внимания результату.
Затем, даже если код использует переменную результата, можно столкнуться с неверной интерпретацией. Так, код всегда подсчитывает двадцатое число Армстронга. А компилятор, в свою очередь, может сократить количество итераций. Более того, код высчитает число Армстронга по параметрам range в функциях input. Поэтому также необходимо анализировать код подходящим количеством значений input в параметрах range.
Наконец, проводя микробенчмаркинг, вы не всегда можете владеть информацией о том, какие процессы происходят внутри вашей системы. Допустим, на заднем плане работают приложения, влияющие на функционирование центрального процессора или оперативной памяти. Так что на этой стадии важно создать подходящую атмосферу для микробенчмаркинга, где вам ничто не помешает.