内置大量CALayer的层托管NSView(WindowServer - CPU 100%)

UJe*_*Jey 5 performance cocoa cpu-usage calayer nsview

我有一个有趣的案例给你.并需要帮助.

我的Mac应用程序有一个层托管的NSView,里面有很多层,子层和子子层.想象一个带有项目(图标,文本标签)的Finder窗口......就像那样.每个项目都有一个按钮,选择背景图层.

一切都很好,直到你有1000个这样的项目.

现在有很多这些项目,当我尝试与此视图交互时,我的应用程序变得没有响应.而棘手的部分是它不是我的应用程序消耗CPU,而是WindowServer.它达到100%并且系统冻结一段时间.

重要的提示:

我的观点是app界面的一部分.有一个主窗口,其他视图.它们也有自己的结构.

而且我注意到,如果我把这个图层托管的视图放到一个单独的窗口中,它可以正常工作,没有冻结具有相同的1000个项目.但是如果我把它放回主窗口就开始停止系统.

问题

  1. 我的应用程序(视图/图层)是什么让WindowServer发疯?
  2. 为什么将此视图放在单独的窗口有帮助?

我已经进行了一些测试并删除了每个项目的所有子图层,每个项目只留下一两个.它减轻了系统的负担,但仍然很糟糕.我已经禁用了所有图纸 - 只是图标的小图像.没有帮助.

bri*_*ple 3

WindowServer主要工作是为 macOS 绘制图形相关的东西,这意味着你从整个屏幕上看到的所有东西,你都必须经过WindowServer并让它为你绘制。

WindowServer 使用高 CPU 的原因有很多。

  1. 您的应用程序中有复杂的绘图方法。——尝试简化你的绘画方法。
  2. 您的桌面上有很多图形,因此 WindowServer 不仅可以绘制您的应用程序,还可以绘制桌面图形。-- 尝试清理桌面。
  3. 您是否打开了一些需要复杂图形绘制的应用程序?-- 尝试关闭该应用程序。

在看到您的确切代码之前,我无法告诉您为什么将元素放入单独的窗口中会有帮助。也许窗口本身隐藏了一些东西以便更容易绘制?

我的一款软件有很多图形元素和动画。但我从来没有遇到过你的问题。创建一个测试项目并尝试类似的事情怎么样?有时,它可以帮助在更清晰的项目结构上看到问题。

我创建了一个简单的演示,窗口中有 100*100 的子层。看起来完全没有问题。

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

@IBOutlet weak var window: NSWindow!

func applicationDidFinishLaunching(_ aNotification: Notification) {
    // Insert code here to initialize your application
    self.window.contentView?.wantsLayer = true

    let size = 10
    for i in 0..<10000 {
        let x = i%100
        let y = i/100

        let layer = CALayer()
        layer.frame = NSRect(x: x*size, y: y*size, width: size, height: size)
        layer.backgroundColor = .random()
        self.window.contentView?.layer?.addSublayer(layer)
    }

}



   func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
}

extension CGFloat {
    static func random() -> CGFloat {
        return CGFloat(arc4random()) / CGFloat(UInt32.max)
    }
}

extension CGColor {
    static func random() -> CGColor {
        return CGColor(red:   .random(),
                       green: .random(),
                       blue:  .random(),
                       alpha: 1.0)
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述