2014-01-15 40 views
2

爲了好玩,我正在做一個簡單的各種語言的OpenGL基準測試,並且我剛剛完成了一個Clojure實現。然而,它的運行速度很慢,所以我決定用VisualVM進行分析,結果我得到了一些相當奇怪的結果。從各自的Java和Clojure的版本配置文件以下是快照(兩者具有相同的渲染邏輯)爲什麼OpenGL在Clojure中的表現與在Java中表現如此不同?

Java profiling screencap

Clojure profiling screencap

注意glPopMatrix是佔用了大部分的時間在Clojure的執行功能,但是在Java實現中,glDrawArrays需要更多的時間。用於Clojure version的代碼是:

(defn render-pt [apt] 
    (GL11/glPopMatrix) 
    (GL11/glPushMatrix) 
    (GL11/glTranslatef (:x apt) (:y apt) (- 0 (:z apt))) 
    (GL11/glScalef (* (:R apt) 2) (* (:R apt) 2) (* (:R apt) 2)) 
    (GL11/glDrawArrays GL11/GL_QUADS 0 24) 
    apt) 

函數渲染-PT被映射到PT的陣列。

Java version的代碼是:

for (int i = minPt; i < numPts; i++) { 
    Pt pt = Pts[i]; 
    GL11.glPopMatrix(); 
    GL11.glPushMatrix(); 
    GL11.glTranslatef(pt.X, pt.Y, -pt.Z); 
    GL11.glScalef(pt.R * 2, pt.R * 2, pt.R * 2); 
    GL11.glDrawArrays(GL11.GL_QUADS, 0, 24); 
} 

兩個功能似乎同樣給​​我;我正在犯一些錯誤嗎?還是我讀的配置文件錯了?

+0

編輯:我想也許,因爲你的個人資料顯示'LazySeq'的證據,你沒有迭代所有的點;但你(用'dorun')。順便說一句,你不應該使用def來聲明局部變量,而是使用'let'。 – omiel

+0

@omiel對於代碼的抱歉;它是Scheme實現的直接端口,它重用全局變量以避免分配。我打算在清理完性能問題後進行清理。 – LogicChains

回答

2

這些功能之間的一些差異:

(:x apt)總是返回一個盒裝數值,因爲它不是類型暗示。 pt.X可能會返回取消裝箱的數字原語,具體取決於Pt的定義。

(:x apt)將執行哈希查找,而不是pt.X所做的更快速的槽查找(除非apt是Clojure記錄,您沒有顯示足夠的代碼讓我知道這是什麼,所以我認爲它是哈希映射)。

默認情況下,Clojure中的數字文字爲Long,默認情況下爲Java中的Integer

+2

是的,但據我所知,所有這些應該增加更多的「自我時間」,或者在拳擊/拆箱方法中增加一些時間,同時在drawArrays和popMatrix中花費的時間平衡基本上與Java中相同。我對這個很困惑。 – amalloy

+0

drawArrays/popMatrix的行爲可能與Long與整數/雙精度對浮點輸入有所不同?只是猜測,並假設也有浮點文字(在Clojure代碼中是雙字)。 – noisesmith

+1

魅力:當我改變下面的行,在程序中調用一次: '(GL11/glFrustum -1 1 -1 1 1 1000)' 爲以下: '(GL11/glFrustum(INT - 1)(int 1)(int -1)(int 1)(int 1)(int 1000))' 然後幀率增加15%!我沒有意識到OpenGL對這樣的事情非常敏感。順便說一下,我在我的問題中鏈接了整個代碼。 – LogicChains

相關問題