By implementing a Swing UI of my Mars Rover project (source code is here) I recently faced the problem that if I run hundreds of rovers, then refreshing the panel after every rover position change is impossible. Each position change puts an event - containing the positions for all rovers - on the channel the displayer logic listens to, and the messages just kept piling up. It's a typical IO bottleneck. So I decided it's enough to display every 100th or 1000th of them. They would change faster than my eyes can process them anyway. So I took the original function performing the display - repaint! - and wrapped it in a sampler. Here is the code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn repaint! | |
"Refreshes the Swing JPanel" | |
[positions-msg] | |
...) | |
(defn sampler-filter | |
"Wraps around a function returning a new function with the same signature, which delegates to the original function, but only | |
with the given frequency | |
f - the original function | |
freq - frequency | |
E.g. 'f' is 'println' and 'freq' is 3, then calling the result function only will print at every 3rd time" | |
[f freq] | |
(let [counter (atom 0)] | |
(fn [& args] | |
(swap! counter inc) | |
(when (= freq @counter) | |
(reset! counter 0) | |
(apply f args))))) | |
;; this function will only perform repaint at avery 1000th invocation | |
(def sampling-repaint! (sampler-filter repaint! 1000)) |
No comments :
Post a Comment