GPU负载下CGEventPost性能不佳

Dae*_*Dae 52 macos core-graphics mouseevent quartz-graphics

我们偶然发现了Quartz Events的性能问题,更具体地说是CGEventPost:在繁重的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
Run Code Online (Sandbox Code Playgroud)

在这里,我们可以看到发布事件平均需要大约0.03毫秒.线程似乎也在0.5ms左右被唤醒了.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
Run Code Online (Sandbox Code Playgroud)

当系统负载较重时,发布事件可能需要(峰值)毫秒而不是微秒.在极端GPU压力(<1 FPS)下,此值可能需要几秒钟.CGEventPost 有时 似乎在等待GPU返回之前完成一些工作.我们的线程仍然正常安排,没有明显的延迟/尖峰(外部).

任何想法都表示赞赏.

nie*_*bot 5

我猜你正在填补队列(底层马赫端口)......

您可以使用仪器中的"调度"或"系统调用"仪器进行确认.(创建一个新的空白文档,添加仪器,然后File > Record Options...确保选中"延迟模式".)这将显示应用程序中的所有线程活动(线程阻塞,睡眠时,激活时以及原因).

我首先尝试提高man 3 PTHREAD_SCHEDPARAM线程调用的线程优先级(cf. )CGEventPost.如果您的线程在较低优先级的线程上被阻塞,则内核应暂时提升阻塞线程的优先级以避免优先级倒置并帮助您的任务更早完成.

总的来说,我认为你必须实现一个双线程解决方案,如下所示:

为要发布的事件创建队列.从主线程(或事件发布线程)将事件发布到此队列,然后发出第二个线程(您创建的事件使用者线程)的信号,以便遍历队列并发布任何未完成的事件CGEventPost.

CGEventPost阻塞时,你的第二个事件发布线程将阻塞,但这不会阻止任何其他线程.当CGEventPost最终解除阻塞时,它将消耗您的事件使用者线程发布的任何未完成事件,并且事件使用者线程可以恢复发布事件.

另一种可能性:你能举办活动吗?某些类型的事件(鼠标移动?)可以用来减少事件.您可能仍会遇到CGEventPost有时的队列限制,我认为2线程方法可能是您最好的选择.