2016-12-02 3 views
4

Я пытался использовать this challenge, для чего требуется написать программу, которая постоянно потребляет память.Программа отказывается постоянно потреблять память

Я полагал, что это будет легко, так что я написал:

(reduce conj [] (range)) 

Который в основном добавляет число из бесконечного диапазона в вектор; теоретически навсегда.

Проблема в том, что это скачок до 3/4 ГБ памяти, а затем просто останавливается. Процессор все еще работает, но он отказывается расти больше.

я решил украсть идею из ответа Java и переопределить finalize для создания нескольких объектов каждый раз, когда один будет перераспределена:

(defrecord A [] 
    Object 
    (finalize [this] (mapv (fn [_] (A.)) (range 5)))) ; Create 5 more 

(mapv (fn [_] (A.)) (range)) 

Но это перестает расти вокруг той же точки, а также.

Как это не взрывается? Тем более, что я использую строгий map, он должен хранить все в памяти, не так ли? Насколько он «знает», я хочу, чтобы он в какой-то момент распечатал весь список, поэтому ему нужно удержать все. Плюс, если в какой-то момент это было освобождение, не следует ли преодолеть этот переопределенный метод finalize?

Может ли кто-нибудь объяснить, что здесь происходит? Я написал это на своем перерыве, поэтому я, возможно, что-то пропустил, но не понимаю, что. Он был протестирован в REPL Intellij/Cursive.

ответ

2

Ваша JVM базово проводит все время сбора мусора. В моей системе предел размера кучи по умолчанию ~ 8.7GB поэтому в зависимости от того, что это дает вам, ваш GC будет пытаться остаться ниже этого еще раньше:

java -XX:+PrintFlagsFinal -version | grep HeapSize 

Вы можете увеличить это с -Xmx вариант виртуальной машины Java.

Ваша программа на самом деле продолжит работу и продолжит добавлять вещи к вашему вектору. Я рекомендую запустить JVM с опцией :XX:+PrintGCDetails, чтобы узнать, что происходит. После того, как вы приблизитесь к своему пределу кучи, JVM будет делать полные GC в течение нескольких секунд. Обратите внимание, что if the JVM spends too much time for the GC then it will throw and OOM error.

Чтобы увидеть, что вы по-прежнему выделять, просто бросить в (when (zero? (rem x 1e5)) (println x)):

java -server -Xmx2g -XX:+PrintGCDetails -cp clojure-1.8.0.jar clojure.main -e '(mapv #(cond-> % (zero? (rem % 1e4)) println) (range))'  
+0

О, спасибо. Интересно, как тогда работал Java-ответ (если бы это было так). Я предполагаю, что они столкнутся с одной и той же проблемой. Они не упомянули об изменении размера кучи. Интересно, стоит ли говорить в гольф. О, хорошо, спасибо за объяснение. – Carcigenicate

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