2010-06-14 3 views
40

Я знаю, что могу получить время, чтобы оценить функцию, которую можно распечатать на экране/stdout, используя функцию времени/макрос.Как измерить функции в Clojure?

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

Есть функция, которая возвращает прошедшее время в какой-либо библиотеке, чтобы помочь с этим бенчмаркингом?

+0

Возможный дубликат [Профилирующий инструмент для Clojure?] (Http://stackoverflow.com/questions/2974916/profiling-tool-for-clojure) –

+0

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

ответ

27

Возможно, вы захотите изучить библиотеку бенчмаркинга Hugo Duncan для Clojure - Criterium.

Из README:

критериум измеряет время вычисления выражения. Он предназначен для решения некоторых проблем, связанных с бенчмаркингом и бенчмаркингом на JVM в частности.

Это включает в себя:

  • статистическая обработка множественных оценок
  • включение периода прогрева, разработанный, чтобы позволить JIT компилятор оптимизировать свой код
  • продувку дс перед тестированием, чтобы изолировать таймингов из состояния ГК до тестирования
  • окончательный принудительный GC после испытаний для оценки воздействия очистки на результаты синхронизации
30

Если это всего лишь вопрос о том, чтобы запрограммировать строку программно, вы можете привязать * out * к чему-то еще, прежде чем использовать время.

user=> (def x (with-out-str (time (+ 2 2)))) 
#'user/x 
user=> x 
"\"Elapsed time: 0.119 msecs\"\n" 

Если вы хотите получить больше контроля над форматом, то вы можете создать свою собственную версию времени используя методы времени системы в Java, которая является то, что времени макроса использует под капотом в любом случае:

user => (macroexpand '(time (+ 2 2))) 
(let* [start__4197__auto__ (. java.lang.System (clojure.core/nanoTime)) 
     ret__4198__auto__ (+ 2 2)] 
    (clojure.core/prn (clojure.core/str "Elapsed time: " (clojure.core//  
      (clojure.core/double 
       (clojure.core/- (. java.lang.System (clojure.core/nanoTime)) 
           start__4197__auto__)) 1000000.0) " msecs")) 
ret__4198__auto__) 

Возьмите эту базовую структуру и замените вызов на prn с любым механизмом отчетности, который вы бы предпочли.

+4

+1 для использования macroexpand, чтобы копать под капотом! – mikera

+1

Спасибо, я смотрел на это, чтобы начать тоже. Библиотека критерия полностью соответствует законопроекту. Но если вы не знаете библиотеку Haskell, вы не будете спотыкаться о ней случайно с помощью Google. –

+1

@PeterTillemans Ну, теперь мы знаем, что это упоминается в StackOverflow. :-) –

0

Если вы создаете привязку Java для своих функций (и с некоторой конфигурацией плагинов Clojure Maven), вы даже можете использовать JMH (http://openjdk.java.net/projects/code-tools/jmh/), который, вероятно, является лучшим жгутом для микрообъектива JVM. Посмотрите на https://github.com/circlespainter/pulsar-auto-instrument-bench

Смежные вопросы