这是一个简单的代码,仅将窗口着色4次。
也许有些明显的东西我看不到。
我的目标是从头学习计算机图形,我想逐个像素绘制以完全控制。我正在寻找一种快速的方法。
Here是完整代码。
相关Clojure部分:
(defmacro for-loop [[sym init check change :as params] & steps]
`(loop [~sym ~init value# nil]
(if ~check
(let [new-value# (do ~@steps)]
(recur ~change new-value#))
value#)))
(time
(for-loop
[k 0 (< k 2) (inc k)]
(for-loop
[c 0 (< c 2) (inc c)]
(for-loop
[i 0 (< i width) (inc i)]
(for-loop
[j 0 (< j height) (inc j)]
(aset ^ints @pixels (+ i (* j width)) (get cs c))))
(.repaint canvas))))
Java中的相同代码:
long t = System.currentTimeMillis();
for (int k = 0 ; k < 2; k++) {
for (int c = 0; c < 2; c++) {
for (int i = 0 ; i < width; i++) {
for (int j = 0; j < height; j++) {
pixels[i + j * width] = cs[c];
}
}
repaint();
}
}
System.out.println(System.currentTimeMillis() - t);
最佳答案
有几个问题:
lein check
,则会看到反射警告。您将在运行时强制进行反射,这会减慢速度。我将canvas
的创建更改为:(defonce canvas (doto (proxy [Frame] []
(update [g] (.paint this g))
(paint [^Graphics2D g]
(.drawImage g, ^BufferedImage image, 0, 0 nil)))
(.setSize width height)
(.setBackground Color/black)
(.setFocusableWindowState false)
(.setVisible true)))
注意我正在使用的类型提示。它不知道要使用哪种
drawImage
重载,并且根本找不到paint
方法。 aset
的使用。从aset
的文档中:强调我的。
问题在于
aset
不适用于原语。它将每个数字强制包装为Integer
,然后在图像中使用该数字时再次将其解包。当乘以图像的每个像素时,这是非常昂贵的。将
aset
更改为aset-int
,以改为使用int
基元。这将使执行时间从大约20秒减少到半秒。 老实说,我不能再降低了。它比以前快很多,但仍然比Java版本慢20倍。我已经为此工作了将近2个小时,而且碰壁了。希望其他人可以减少最后的超时时间。
关于performance - 寻找一种逐像素绘制的快速方法,为什么此代码比Java慢1000倍?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49956224/