Я работаю над некоторым Java-кодом, который нуждается в высокой оптимизации, поскольку он будет работать в горячих функциях, которые вызываются во многих точках моей основной логики программы. Часть этого кода включает в себя умножение переменных double на 10 на произвольные неотрицательные int exponent s. Один быстрый способ (отредактируйте: но не самый быстрый, см. Обновление 2 ниже), чтобы получить умноженное значение на switch на exponent:
double multiplyByPowerOfTen(final double d, final int exponent) {
   switch (exponent) {
      case 0:
         return d;
      case 1:
         return d*10;
      case 2:
         return d*100;
      // ... same pattern
      case 9:
         return d*1000000000;
      case 10:
         return d*10000000000L;
      // ... same pattern with long literals
      case 18:
         return d*1000000000000000000L;
      default:
         throw new ParseException("Unhandled power of ten " + power, 0);
   }
}
Описанные выше эллипсы показывают, что константы case int продолжают увеличиваться на 1, поэтому в приведенном выше фрагменте кода действительно 19 case. Поскольку я не был уверен, действительно ли мне понадобится все полномочия из 10 в case операторах 10 thru 18, я запустил несколько микробизнесов, сравнивающих время завершения 10 миллионов операций с этим выражением switch по сравнению с switch только с case 0 thru 9 (с exponent, ограниченным 9 или менее, чтобы не нарушить сокращенный switch). У меня есть довольно неожиданное (по крайней мере, для меня!) Результат, что более длинный switch с более case операторами действительно работает быстрее.
На жаворонке я попытался добавить еще больше case, который только что вернул фиктивные значения, и обнаружил, что я могу заставить коммутатор работать еще быстрее с 22-27 объявленными case (хотя эти фиктивные случаи никогда на самом деле ударить, пока выполняется код). (Опять же, case добавлялись смежным образом, увеличивая прежнюю константу case на 1.) Эти разности времени выполнения не очень значительны: для случайного exponent между 0 и 10 фиктивное заполненное выражение switch завершает 10 миллионов исполнений за 1,49 секунды против 1,54 секунды для незакрепленной версии, при общей экономии 5 нс на выполнение. Таким образом, не та вещь, которая делает одержимость излишним отложением выражения switch, которое стоит усилий с точки зрения оптимизации. Но я все еще просто нахожу любопытным и контр-интуитивным, что switch не становится медленнее (или, возможно, в лучшем случае поддерживает постоянное время O (1)) для выполнения, поскольку к нему добавляется больше case.
 
Это результаты, которые я получил от запуска с различными ограничениями на случайно генерируемые значения exponent. Я не включил результаты вплоть до 1 для предела exponent, но общий вид кривой остается тем же самым, с хребтом вокруг отметки 12-17, а долина между 18- 28. Все тесты выполнялись в JUnitBenchmarks с использованием общих контейнеров для случайных значений для обеспечения идентичных входных данных тестирования. Я также запускал тесты как по порядку от самого длинного оператора switch до кратчайшего, так и наоборот, чтобы попытаться устранить возможность проблем, связанных с упорядочением. Я поставил свой тестовый код на репозиторий github, если кто-то захочет воспроизвести эти результаты.
Итак, что здесь происходит? Некоторые капризы моей архитектуры или микро-эталонной конструкции? Или Java switch действительно немного быстрее выполнить в диапазоне от 18 до 28 case, чем от 11 до 17?
github test repo "switch-experiment"
  ОБНОВЛЕНИЕ: Я немного очистил библиотеку бенчмаркинга и добавил текстовый файл в /results с некоторым выходом в более широком диапазоне возможных значений exponent. Я также добавил параметр в тестовом коде, чтобы не вызывать Exception из default, но это не влияет на результаты.
  ОБНОВЛЕНИЕ 2: Нашел довольно неплохое обсуждение этой проблемы еще в 2009 году на форуме xkcd здесь: http://forums.xkcd.com/viewtopic.php?f=11&t=33524. Обсуждение OP с использованием Array.binarySearch() дало мне представление о простой реализации шаблона экспоненциации на основе массива выше. Нет необходимости в бинарном поиске, так как я знаю, что такое записи в array. Кажется, он работает примерно в 3 раза быстрее, чем при использовании switch, очевидно, за счет некоторого потока управления, который дает switch. Этот код был добавлен в репозиторий github.
