Что такое микробиблиотека?

Я слышал, что этот термин используется, но я не совсем уверен, что это значит, поэтому:

  • Что это значит и что не означает?
  • Каковы некоторые примеры того, что IS и НЕ является микромаркетинговым?
  • В чем опасность микромаркетинга и как вы его избегаете?
    • (или это хорошо?)

Ответ 1

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

Опасность состоит в том, что люди могут использовать любые результаты, полученные ими из микрообъектива, чтобы диктовать оптимизацию. И как мы все знаем:

Мы должны забыть о небольшой эффективности, скажем, около 97% времени: преждевременная оптимизация - это корень все зло "- Дональд Кнут

Могут быть много факторов, которые искажают результат микрообъектов. Оптимизация компилятора - одна из них. Если измеренная операция занимает настолько мало времени, что все, что вы используете для ее измерения, занимает больше времени, чем сама фактическая операция, ваши микрообъекты также будут искажены.

Например, кто-то может взять микропредметку накладных расходов для циклов for:

void TestForLoop()
{
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each iteration: %d\n", elapsedPerIteration);
}

Очевидно, что компиляторы могут видеть, что цикл абсолютно ничего не делает и вообще не генерирует код для цикла. Таким образом, значение elapsed и elapsedPerIteration в значительной степени бесполезно.

Даже если цикл делает что-то:

void TestForLoop()
{
    int sum = 0;
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
        ++sum;
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each iteration: %d\n", elapsedPerIteration);
}

Компилятор может видеть, что переменная sum не будет использоваться ни для чего и оптимизирует ее, а также оптимизирует цикл for. Но ждать! Что делать, если мы это сделаем:

void TestForLoop()
{
    int sum = 0;
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
        ++sum;
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each iteration: %d\n", elapsedPerIteration);
    printf("Sum: %d\n", sum); // Added
}

Компилятор может быть достаточно умным, чтобы понять, что sum всегда будет постоянным значением, а также оптимизирует все это. Многие были бы удивлены оптимизирующими возможностями компиляторов в эти дни.

Но как насчет того, что компиляторы не могут оптимизировать?

void TestFileOpenPerformance()
{
    FILE* file = NULL;
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
        file = fopen("testfile.dat");
        fclose(file);
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each file open: %d\n", elapsedPerIteration);
}

Даже это не полезный тест! Операционная система может видеть, что файл открывается очень часто, поэтому он может предварительно загрузить его в память для повышения производительности. Практически все операционные системы делают это. То же самое происходит при открытии приложений - операционные системы могут определить наиболее популярные приложения, которые вы открываете, и предварительно загружать код приложения в память при загрузке компьютера!

На самом деле, в систему входят бесчисленные переменные: локальность ссылок (например, массивы и связанные списки), эффекты кэшей и пропускной способности памяти, встраивание компилятора, реализация компилятора, коммутаторы компилятора, количество процессорных ядер, оптимизация на уровень процессора, планировщики операционной системы, фоновые процессы операционной системы и т.д.

Таким образом, во многих случаях микробиблиотека не является во многом полезной метрикой. Это определенно не заменяет целые программные тесты хорошо определенными тестовыми примерами (профилирование). Сначала напишите читаемый код, затем профиль, чтобы узнать, что нужно сделать, если таковые имеются.

Я хотел бы подчеркнуть, что микрообъекты не являются злом как таковыми, но нужно тщательно их использовать (это верно для многих других вещей, связанных с компьютерами).

Ответ 2

Не существует определения микро-бенчмаркинга, но когда я его использую, я имею в виду небольшой искусственный бенчмарк, предназначенный для тестирования производительности некоторого конкретного аппаратного обеспечения 1 или языковой функции. Напротив, лучшим тестом является реальная программа, предназначенная для выполнения реальной задачи. (Проводить жесткую грань между этими двумя делами бессмысленно, ИМО, и я не буду пытаться.)

Опасность микро-бенчмаркинга заключается в том, что легко написать эталон, который дает результаты, которые полностью вводят в заблуждение. Некоторые распространенные ловушки в микро-бенчмарках Java:

  • написание кода, который может вывести компилятор, не является полезной работой, и поэтому полностью оптимизируется,
  • не принимая во внимание "комковатую" природу управления памятью Java, и
  • не принимая во внимание эффекты запуска JVM; например, время, затрачиваемое на загрузку и JIT-компиляцию классов, и (наоборот) ускорение выполнения, которое происходит после компиляции JIT-методов.

Однако даже после того, как вы обратились к вышеупомянутым проблемам, существует системная проблема с сравнительным анализом, которую невозможно решить. Код и поведение эталонного теста обычно мало связаны с тем, что вас действительно волнует; т.е. как ваше приложение будет работать. Слишком много "скрытых переменных" для вас, чтобы можно было обобщать их от эталона до типичных программ, не говоря уже о вашей программе.

По этим причинам мы регулярно советуем людям НЕ тратить свое время на микротесты. Вместо этого лучше всего написать простой и естественный код и использовать профилировщик для определения областей, которые необходимо оптимизировать вручную. Интересно, что обычно выясняется, что наиболее существенные проблемы с производительностью в реальных приложениях связаны с неправильным проектированием структур данных и алгоритмов (включая узкие места, связанные с сетями, базами данных и потоками), а не с тем, что пытаются сделать типичные микропроцессоры. тестовое задание.

@BalusC предоставил отличную ссылку на материал по этой теме на странице часто задаваемых вопросов Hotspot. А вот ссылка на официальный документ IBM Брайана Гетца.


1 - Эксперты даже не пытались бы проводить аппаратный бенчмаркинг в Java.Между байт-кодами и оборудованием происходит слишком много "сложных вещей", чтобы сделать необработанные/полезные выводы об оборудовании из необработанных результатов.Вам лучше использовать язык, который ближе к аппаратному;например, C или даже ассемблерный код.

Ответ 3

  • Что это значит и что не означает?

Я бы сказал, что микро-бенчмаркинг просто означает измерение чего-то крошечного. Крошечный, вероятно, зависит от контекста, но обычно на уровне единого системного вызова или чего-то подобного. Бенчмаркинг относится ко всему выше.

  • Каковы некоторые примеры того, что IS и НЕ является микромаркетинговым?

В этой статье указано время измерения системного вызова getpid() и измерение времени для копирования памяти с помощью memcpy() в качестве примеров микро -benchmarking.

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

  • В чем опасность микрообнаружения и как вы его избегаете?

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

Обычно люди говорят "не делайте микро-бенчмаркинг", но они, вероятно, означают "не принимать решения по оптимизации на основе микро-тестов".

  • (или это хорошо?)

Это совсем не плохо, как другие, и многие веб-страницы, кажется, предлагают. У него есть места. Я работаю с перекодировкой программ и временем выполнения и т.д. Мы обычно публикуем микро-тесты наших добавленных инструкций, а не для каких-либо оптимизаций, но убедившись, что наш дополнительный код практически не влияет на выполнение перезаписанной программы.

Это искусство, однако, особенно в контексте виртуальной машины с JIT, разминки и т.д. Хорошо описанный подход для Java описывается здесь.

Ответ 4

в книге (Java Performance The Definitive Guide) он имеет это определение и пример без микрообъектов

  • Microbenchmarks

    Микробенчмарк - это тест, предназначенный для измерения очень маленькой единицы производительность: время для вызова синхронизированного метода по сравнению с несинхронизированный метод; накладные расходы при создании потока против пул потоков; время выполнения одного арифметического алгоритма против альтернативная реализация; и т.д.

    Microbenchmarks может показаться хорошей идеей, но они очень трудно писать правильно. согласуйте следующий код, который является попыткой написать mocrobenchmark, который проверяет permorfance od дефференциальная реализация метода вычисления 50-го Фибоначчо номер:

public void doTest(){
double l;
long then = System.currentTimeMillis();

for(int i = 0; i < nLoops; i++){
 l = fibImpl1(50);
}

long now = system.currentTimeMillis();
System.out.println("Elapsed time: " + (now - then))

}

...

private double fibImpl1(int n){
if(n < 0) throw new IllegalArgumentException("Must be > 0");
if(n == 0) return 0d;
if(n == 1) return 1d;
double d = fibImpl1(n - 2) + fibImpl(n - 1);
if(Double.isInfinited(d)) throw new ArithmeticException("Overflow");
return d;
}

Микрообъекты должны использовать свои результаты.

Самая большая проблема с этим кодом заключается в том, что он никогда не меняет какое-либо состояние программы. Поскольку результат вычисления Фибоначчи никогда не используется, компилятор может отказаться от этого вычисления, умный компилятор (включая текущие java 7 и 8 компиляторы)

закончит выполнение этого кода:

long then = System.currentTimeMillis();
long now = System.currentTimeMillis();
System.out.println("Elapsed time: " + (now - then));

В результате, прошедшее время будет всего несколько миллисекунд, независимо от реализации метода fibonaci, или количество циклов, которые предполагается выполнить.

Существует определенная проблема в этой конкретной проблеме: убедитесь, что каждый результат прочитан или просто прописан. На практике изменение определения l от локальной переменной до переменной экземпляра (объявленной с помощью ключевого слова volatile) позволит измерять производительность метода.

Ответ 6

Microbenchmarking - это бенчмаркинг, который я считаю нецелесообразным. Эффективный бенчмаркинг - это бенчмаркинг. Думаю, стоит потратить время.

Вообще говоря, микрообъектив (как в Silico говорит) пытается измерить эффективность какой-то очень гранулированной задачи, что трудно сделать хорошо и обычно бессмысленно в контексте фактических головных болей.