Что происходит с getVarRoot?
Я действительно удивлен, что любая программа тратит много времени в getRawRoot ().Все, что делает этот метод, это возвращает одно поле из Var, согласно источнику в clojure.lang.Var :
final public Object getRawRoot(){
return root;
}
Кроме того, это небольшой финальный метод, поэтому он должен бытьвстроенный любым современным JIT-компилятором ..... в основном любые вызовы getRawRoot должны быть безумно быстрыми.
Я подозреваю, что с вашим профилировщиком происходит что-то странное: возможно, это добавляет отладочный код в getRawRoot (), которыйзанимает много времени.Поэтому я бы посоветовал сравнить ваш код без профилировщика и с помощью java -server
, чтобы увидеть, как на самом деле работает эта функция.
Другие советы по производительности
Убедитесь, что вы используете Clojure 1.3 + , поскольку есть некоторые оптимизации для доступа к var, которые вы почти наверняка захотитевоспользуйтесь этим видом низкоуровневого кода.
Если бы я предположил, что на самом деле является самым большим узким местом в этом коде, то я думаю, что это будет тот факт, что функция сетки #(blocked? maze [%1 %2])
создает новый вектор каждый раз, когда он вызывается для проверки квадрата сетки.Было бы намного лучше, если бы вы могли реорганизовать это так, чтобы он не нуждался в векторе, и тогда вы могли бы просто использовать #(blocked? maze %1 %2)
напрямую.Создание новых коллекций обходится дороже по сравнению с простыми математическими операциями, поэтому вы хотите делать это экономно во внутренних циклах.
Вы также хотите убедиться, что вы используете примитивные операции везде, где это возможно, и с(set! *unchecked-math* true)
.Убедитесь, что вы объявили свои локальные объекты как примитивы, поэтому вам понадобится, например, (let [u0 (int (if x-long x0 y0)) .....] .....)
и т. Д. Основная причина сделать это - избежать накладных расходов примитивов в штучной упаковке, что опять-таки подразумевает распределение памяти, которое вы хотите избежать во внутренних циклах.