2013-10-09 38 views
6

我們正面臨着連接到鼠標移動jQuery的事件傳播的性能問題:jQuery mousemove性能 - 油門事件?

我們有一個屏幕填充畫布和需要,如果用戶拖動它的鼠標追蹤,所以我們增加了鼠標移動偵聽器對象像這樣:

ourCanvas.on('mousemove', 
    function(event) { 
     event.preventDefault(); 
     //our drag code here 
    } 
}); 

此代碼工作正常,但我們一個測試系統上已經在當前的Firefox(24)嚴重的性能問題。 Profiler告訴我們,大部分時間都花在jQuery.event.dispatch()(我們嘗試了當前最新的jQuery 1.8,1.9,1.10和2.0)。

我們通過在此處使用「jQuery.event.fix()」性能優化,成功地減少了dispatch()函數花費的時間:http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html但該測試系統的性能仍低於我們的預期。

經過進一步的測試,我設法讓這個向下鼠標在系統上使用的:它使用1000Hz的。 我們將使用過的鼠標切換到125Hz,瞧,表現非常好。

我們的假設是,該鼠標上的高赫茲率引起了很多鼠標移動事件,所以我們改變了上面的代碼,以將事件油門,只能調用事件處理每隔X毫秒:

var lastMove = 0; 
var eventThrottle = 1; 
ourCanvas.on('mousemove', 
    function(event) { 
     event.preventDefault(); 
     var now = Date.now(); 
     if (now > lastMove + eventThrottle) { 
      lastMove = now; 
      //our drag code here 
     } 
    } 
}); 

它像一個迷人的工作,表現很棒。即使我們只跳過兩毫秒的事件。

現在我有兩個問題:

  1. 我們有我們重視鼠標移動聽衆不同的HTML元素和我想這個手工製作油門添加到所有這些mousemove處理的其他位置不要再次遇到問題。這在某種程度上可以在jQuery(2.0.3)中以一種很好的方式做到嗎?我已經在jQuery javascript中看到了preDispatch鉤子,但是它們已經在調用fix()之後調用,這也使用了一些時間,我也想保存該調用。

  2. 我對2ms的eventThrottle已經足以獲得非常好的性能感到困惑,所以我添加了一個計數器來查看有多少事件被跳過。令人驚訝的結果是:它只跳過0-1個事件...在100ms的節流時,跳過的事件大約爲60-70,所以如果每毫秒少於1個mousemove事件,則爲,爲什麼此代碼有畢竟這種積極的影響?

感謝您的任何意見, 克里斯托弗

回答

2

1 - 有一個油門jQuery插件:https://github.com/cowboy/jquery-throttle-debounce

正如你可以閱讀in the examples,可以更換:

// Bind the not-at-all throttled handler to the resize event. 
$(window).resize(handler); 

// Bind the throttled handler to the resize event. 
$(window).resize($.throttle(250, handler)); // This is the line you want! 

2 - 你想發佈你的處理程序的代碼?

一個盲目的建議:螢火蟲有性能問題與FF 24.你有沒有試着用啓用/禁用螢火蟲比較的表演?

+0

謝謝:@ 1:使用'setTimeout()'和'clearTimeout()'的有趣插件,但它並不限制實際的事件處理。兩個副作用:1:我仍然需要調用'$ .throttle()'而不是'$ .on()'(很難用多個開發人員實現)。 2:CPU繁重的jQuery處理開銷仍然存在(調用'fix()',...)。也許最簡潔的解決方案是將自己的jQuery事件處理函數改寫爲「插件」。@ 2我們的處理程序更改了從'requestAnimationFrame'上運行的循環訪問的一些變量。 @Firebug:你說的對FF24來說,只是用停用的Firebug進行測量。 –

+0

如果你想得到什麼吃你的CPU的幫助,你將不得不張貼一些代碼... – LeGEC

3

2015年年底,我遇到了我最終發現的這個問題。

在我的瀏覽應用程序我畫的各種尺寸在特定位置的多個圓圈,然後我拖累了整個屏幕的可見部分,只露出從全面的背景是在當前縮放級別中可見的圓圈。拖動鼠標會生成一個mousemove事件,這會觸發對我的渲染例程的調用,從而導致對每個可見圓圈重新繪製。

在IE 11測試這個,我發現,一旦我在可視區域有大約100多個圈,渲染,同時拖動鼠標變得非常不穩定。分析器指出這幾乎完全是由於paint()例程。

我的代碼已經在使用庫中的requestAnimationFrame()。有趣的是,在拖動屏幕時,我看到了放緩;但如果我只拖動屏幕並將其釋放,讓庫代碼繼續以減速動畫動畫,重新繪製就像黃油一樣平滑。拖動鼠標時發生放緩。這個問題絕對似乎與鼠標移動。 (回到這片刻)

我相比下來的油漆()例程只是一個簡單的填充弧 - 同樣的問題。當我改變縮放級別,然後使用drawImage()將離屏畫布複製到我的主屏幕時,我嘗試將實心圓圈繪製到屏幕外的畫布上 - 這種性能得到了改善,但在IE中它仍然不可用。然後我嘗試使用這種技術將所有圓圈繪製到與我的主要可見窗口大小相同的離屏畫布,然後更改paint()以使其不做任何操作,但將屏幕外畫布複製到我的可見畫布上 - 這又改進了一點,但還不夠。

然後我試圖運行我的應用程序在不同的瀏覽器:

IE 11:非常波濤洶涌 火狐42:非常波濤洶涌 鉻47:在所有縮放級別 完美流暢:在所有縮放級別 歌劇院34完美流暢桌面的Safari 5.1.7(對PC):在所有縮放級別

到鼠標移動的問題肯定是相關的,它是如何通過不同瀏覽器處理的輕微波動。

最後,我發現在計算器上和這個問題的建議,鼠標本身正在發送,它的沼澤化瀏覽器的重繪速度不夠快的能力,這麼多的鼠標移動事件。而且我的確有一個具有高事件發生率的現代鼠標。

我嘗試添加eventThrottle檢查到我的mousemove事件處理程序,瞧!成功。我的代碼現在可以在所有瀏覽器上平滑呈現。 (Upvoted with pleasure :) :)

我想爲任何可能在使用高頻鼠標拖動時遇到IE和Firefox性能較差的問題的人添加此附加信息。提議的解決方案,以節制鼠標移動事件爲我工作。