2013-01-15 38 views
52

我們偶然發現了Quartz Events的性能問題,更具體地說是CGEventPost:在GPU負載過重時CGEventPost可能會阻塞。我們創建了a small benchmark application to demonstrate the issue。這個應用程序只是一個創建,發佈和發佈事件的循環。在GPU負載下CGEventPost的性能弱

您可以在下面看到運行應用程序的結果。第一次運行在空閒系統上。第二輪是FurMark(GPU壓力測試),儘量使用轉盤。

  • 內部是內部循環需要多長時間,基本上只是用Quartz Events創建,發佈和發佈一個事件。
  • 外部是我們的程序等待被喚醒多久(睡眠)。應該接近我們的睡眠時間,但如果系統處於壓力之下,可能會延遲。
  • 帖子是事件發佈需要多長時間。

 

18:58:01.683 EventPerformance[4946:707] Measurements: (outer should be close to 10) 
18:58:01.684 EventPerformance[4946:707] inner (ms): 0.04, outer (ms): 11.02, CGEventPost (ms): 0.03 
18:58:01.684 EventPerformance[4946:707] inner (ms): 0.04, outer (ms): 11.02, CGEventPost (ms): 0.03 
18:58:01.685 EventPerformance[4946:707] inner (ms): 0.07, outer (ms): 10.26, CGEventPost (ms): 0.03 
18:58:01.685 EventPerformance[4946:707] inner (ms): 0.06, outer (ms): 10.85, CGEventPost (ms): 0.05 
18:58:01.686 EventPerformance[4946:707] inner (ms): 0.07, outer (ms): 10.41, CGEventPost (ms): 0.04 
18:58:01.686 EventPerformance[4946:707] inner (ms): 0.04, outer (ms): 10.39, CGEventPost (ms): 0.03 
18:58:01.686 EventPerformance[4946:707] inner (ms): 0.05, outer (ms): 11.02, CGEventPost (ms): 0.03 
18:58:01.687 EventPerformance[4946:707] inner (ms): 0.03, outer (ms): 10.67, CGEventPost (ms): 0.03 
18:58:01.687 EventPerformance[4946:707] inner (ms): 0.08, outer (ms): 10.09, CGEventPost (ms): 0.05 
18:58:01.688 EventPerformance[4946:707] Averages: (outer should be close to 10) 
18:58:01.688 EventPerformance[4946:707] avg inner (ms): 0.05, avg outer (ms): 10.64, avg post (ms): 0.03 

在這裏我們可以看到,張貼的事件平均需要約0.03毫秒。而且這個線程似乎太遲了0.5毫秒左右就被喚醒了。 CGEventPost沒有尖峯。

19:02:02.150 EventPerformance[5241:707] Measurements: (outer should be close to 10) 
19:02:02.151 EventPerformance[5241:707] inner (ms): 0.03, outer (ms): 10.23, CGEventPost (ms): 0.02 
19:02:02.151 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 10.54, CGEventPost (ms): 0.02 
19:02:02.151 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 11.01, CGEventPost (ms): 0.01 
19:02:02.152 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 10.74, CGEventPost (ms): 0.01 
19:02:02.152 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 10.20, CGEventPost (ms): 0.01 
19:02:02.152 EventPerformance[5241:707] inner (ms): 10.35, outer (ms): 11.01, CGEventPost (ms): 10.35 
19:02:02.152 EventPerformance[5241:707] inner (ms): 0.03, outer (ms): 10.02, CGEventPost (ms): 0.02 
19:02:02.153 EventPerformance[5241:707] inner (ms): 58.90, outer (ms): 10.11, CGEventPost (ms): 58.90 
19:02:02.153 EventPerformance[5241:707] inner (ms): 0.03, outer (ms): 10.12, CGEventPost (ms): 0.02 
19:02:02.153 EventPerformance[5241:707] Averages: (outer should be close to 10) 
19:02:02.371 EventPerformance[5241:707] avg inner (ms): 7.71, avg outer (ms): 10.44, avg post (ms): 7.71 

當系統處於沉重的GPU負載下時,發佈事件可能需要(尖峯)毫秒而不是微秒。在極端的GPU壓力下(< 1 FPS),此值可能需要幾秒鐘。 CGEventPost 有時似乎在等待GPU返回前完成一些工作。我們的線程仍然正常計劃,沒有明顯的延遲/尖峯(外部)。

任何想法表示讚賞。

+2

在提交大量OpenCL工作時,我發現窗口中的效果甚至更糟(我知道你在osx上):所有GPU繪圖都變得越來越慢。就好像GPU沒有優先的概念或者波陣面的年代。 – doug65536

+2

嘗試使用工具進行分析以查看發生減速的位置。 – monoxygen

+1

你在電腦上運行過哪種類型的圖形卡?集成的,集成的+離散的或離散的?看看在具有不同顯卡配置的系統上是否運行不同的行爲會很有趣。 – monoxygen

回答

5

我想你是填補了隊列(Mach端口底層)...

爲此,可以使用在儀器的「調度」或「系統調用」儀器確認。 (創建一個新的空白文檔,添加工具,然後在File > Record Options...下確保選中「延遲模式」。)這將顯示應用程序中的所有線程活動(線程阻塞,睡眠時,激活時間和原因) 。

我會先嚐試提高調用CGEventPost的線程的線程優先級(參見man 3 PTHREAD_SCHEDPARAM)。如果您的線程在較低優先級的線程上被阻塞,那麼內核應暫時提升阻塞線程的優先級以避免優先級反轉並幫助您的任務提前完成。

總的來說,我認爲你將不得不實施2線程解決方案,如下:

創建要張貼事件隊列。將事件從主線程(或事件發佈線程)發佈到此隊列中,然後發出第二個線程(您創建的事件使用者線程)的指示以走過隊列並使用CGEventPost發佈任何未完成的事件。

CGEventPost塊,您的第二個事件發佈線程將阻塞,但這不會阻止任何其他線程。當CGEventPost最終取消阻止時,它將消耗由事件使用者線程發佈的任何未完成事件,並且事件使用者線程可以恢復發佈事件。

另一種可能性:你可以煤炭事件嗎?有某些類型的事件(鼠標移動?),您可以將事件集中到更少的事件中。有時您可能仍會遇到CGEventPost的隊列限制,我認爲2線程方法可能是您最好的選擇。

+0

由於我問了我們從CGEventPost切換到IOHIDPostEvent的問題,該問題在GPU負載下執行得更好,但在其他情況下仍然阻塞。 – Dae

+0

使用儀器,我們發現對於IOHID和Quartz,我們在mach_msg_trap中阻塞,可能等待收到消息。我們還沒有設法獲得更多細節(即誰在另一端,爲什麼他阻止)。 – Dae

+0

至於實時優先級,它被意外從測試應用程序中刪除,但我們確實在我們的實際項目中有。 (但沒有區別)。我們實施了合併和線程化 - 感謝您的建議! – Dae