2016-01-01 2 views
1

У меня есть следующие функции:памяти в бесконечном цикле в Clojure

(defn- clock-process [every f] 
    (while true 
    (f) 
    (Thread/sleep every))) 

И я закручивая его в его собственном потоке, чтобы избежать блокировки основного потока:

(future 
    (clock-process 3600000 ;; fire every hour 
    #(intensive-fn ...))) 

на дино Heroku, общее использование памяти существенно растет на каждом часовом интервале:

enter image description here

В случае падения памяти происходит перезапуск приложения.

Может ли кто-нибудь помочь мне понять, что происходит?

+0

Спасибо, что ответили. Это действительно необычно для любого приложения, которое я развернул в Heroku. То, что использование памяти постоянно увеличивается с каждым часовым интервалом (каждый раз, когда анонимная функция запускается), мне кажется, что я делаю _something_ wrong ... Annnnd [ошибки R14] (https://devcenter.heroku.com/articles/error-codes # r14-memory-quota-above) ... – KendallB

+1

Многое могло зависеть от функции, которую вы вызываете. Очень распространенной проблемой, которая может показаться утечкой памяти, является наличие функции, которая использует ленивую последовательность, но где-то у вас есть что-то, что зависает на голове этой последовательности. Это предотвратит значения, которые реализуются, когда последовательность обрабатывается от освобождения и приведет к увеличению использования памяти, поскольку все больше и больше значений последовательности реализованы. Возможно, опубликуйте свою «интенсивную функцию» или попробуйте использовать другую функцию. –

+0

Я согласен с Тимом - утечка, вероятно, связана с некоторой деталью реализации вызываемой функции, а не с самим циклом. Еще одним распространенным виновником утечек памяти в давно работающих приложениях является memoization. – Alex

ответ

1

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

tl; dr: Уменьшение размера кучи - это, вероятно, лучшее, что нужно сделать.

Во-первых, настройте Memory logging agent. Это будет периодически некоторые сообщения в журналах, как:

source=web.1 measure.mem.jvm.heap.used=33M measure.mem.jvm.heap.committed=376M measure.mem.jvm.heap.max=376M 
source=web.1 measure.mem.jvm.nonheap.used=19M measure.mem.jvm.nonheap.committed=23M measure.mem.jvm.nonheap.max=219M 
source=web.1 measure.threads.jvm.total=21 measure.threads.jvm.daemon=11 measure.threads.jvm.nondaemon=1 measure.threads.jvm.internal=9 

Из этого, вы будете в состоянии определить, где происходит рост (т.е. кучу или недостижение кучу).

Если вы обнаружили, что рост - это все куча, попробуйте установить максимальный размер кучи (т. Е. -Xmx). ниже значений по умолчанию. Кое-что вроде -Xmx300m должно быть достаточно, но вы, вероятно, можете пойти ниже. Вы также можете создать несколько кучи кучи и проанализировать их с помощью инструмента, например Eclipse MAT, если вы хотите точно определить источник.

Если вы обнаружили, что рост находится в не-куче, то используйте некоторые из других шагов, описанных в troubleshooting guide, чтобы определить, является ли это Metaspace или чем-то еще. Если это не в Metaspace, тогда у вас может быть утечка памяти, которая может возникнуть из-за того, что вы не открываете файлы или буферы.

Вы пытались воспроизвести проблему локально? Если вы это сделаете, если будет легче копать немного глубже, используя инструменты, такие как VisualVM и jmap.

Наконец, вы можете открыть support ticket with Heroku. Они могут смотреть на такие вещи, как smaps, чтобы справиться с утечками не-кучи/нативной памяти.

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