跳过导航
Main illustrated image for Speeding up Symbols blog post
Sketch 内部

加速符号:我们如何在 Sketch 67 中提升性能

幕后了解我们如何在 Sketch 中构建符号——以及我们如何使使用它们更快

当我们宣布 Mac 应用程序的 67 版本时,我们将重点放在它带来的性能改进上。我们的团队在幕后努力工作,以简化事情并使整个应用程序感觉更流畅、响应更快。看看 我们的公告帖子 了解更多信息。

现在,我们想让您了解我们加速符号的方法。这是新系列文章中的第一篇,我们将在其中更深入地探讨该应用程序的技术方面。请继续关注未来更多内容。


我们花了很多时间来改进 Sketch 67 的性能,以使 Mac 应用程序更快。我们改进了很多方面,从我们如何渲染具有饱和度的背景模糊,到我们如何调整显示更新的时间以使其更接近屏幕的刷新率。

我们还试图让使用符号在总体上感觉更流畅,并且有些人询问我们是如何做到的。虽然答案不是一些涉及高级计算机科学或数学的疯狂故事,但也没有一件事能产生所有影响。但我们确实认为有一些有趣的事情可以分享,这些事情也可能对其他开发人员适用。

是什么构成一个符号?

当我们引入符号时,我们从一个基本的基础开始。符号由两部分组成:符号母版(就像一个画板),包含多个图层(例如文本图层、组和形状),以及符号实例(这是一个常规图层,仅包含对母版的引用)。每当我们需要在画布上绘制一个实例时,我们都会找到符号母版并在其位置绘制它。

符号实例还可以包含覆盖,这是一组来自母版值的派生。文本覆盖是最常见的。在 Sketch 67 之前,如果一个实例有覆盖,我们会制作一个母版的完整副本,使用覆盖值更新文本图层,然后绘制该副本。

寻找焦点

当我们首次发布符号时,它们仅支持文本覆盖。从那时起,我们添加了更多类型的覆盖 — 嵌套符号覆盖、样式覆盖、调整大小规则、智能布局等等。拥有一个不断壮大的团队来处理这些问题带来了挑战,虽然我们总是尝试记录我们的代码并分享知识,但我们并不是一个蜂巢思维。我们有一种挥之不去的感觉,我们本可以做得更好。

随着功能的发展,构建它们的基本假设可能不再成立,而且您在第一天设置的架构可能不再足够。但是,与其在出现问题的第一时间就重写它,通常更有意义的是稍微扩展一下系统。毕竟,我们不能每次创建新功能时都重写每一行代码。

但是,最终,您会达到一个临界点,我们在开发智能布局时达到了一个临界点。我们过去将符号实例渲染为符号母版的副本,但这必须改变,以便我们可以处理影响嵌套符号的布局调整。现在我们将符号渲染为分离的组 — 符号实例被转换为一个组,该组包含所有这些图层的副本,递归地向下进入所有嵌套符号。

在我们发布智能布局后,我们觉得我们需要退后一步并评估我们的整个方法。毫不奇怪,我们发现不再成立的假设 — 而且不可避免地,当多个开发人员在不同的假设下工作时,现在存在冲突。例如,我们发现我们有两个用于存储计算符号的缓存,并且我们花费大量时间提前填充其中一个缓存 — 但实际上从未在最重要的位置使用它们。

将符号拉成形

我们还决定好好看看我们是如何计算最终符号实例的,这些实例是在应用覆盖、缩放、智能布局等之后渲染的。正如我所提到的,这些使用了分离的组,并且我们发现我们创建了太多(深层)对象树的中间副本。我们设法大幅削减了这一点。

我之前描述了我们如何制作母版的副本来应用覆盖。虽然这对大多数符号来说都可以,但对于更复杂和深度嵌套的符号来说,情况会呈指数级恶化。更糟糕的是我们在模型中使用的双树结构 — 一个可变树,让 UI 层可以轻松进行更改,并由一个无锁不可变模型支持,我们可以安全地在线程之间传递该模型以进行诸如跨多个线程渲染画布之类的操作。

简而言之,我们创建了许多中间副本,然后又将它们丢弃。对此没有神奇的答案 — 这只是找到我们从一棵树模型过渡到另一棵树模型的方法并尝试消除它们的情况。在任何大小合适的符号上,我们都设法使用此方法消除了至少六个中间副本。

这也产生了各种其他的连锁反应。例如,这意味着我们可以更好地利用基于身份的缓存。制作中间副本会导致缓存未命中,这可能会导致相对昂贵的事情(如阴影)被重新计算。

更少的工作,更快的速度

另一个很大的收获是发现当符号母版更改时我们绘制了太多内容。在典型的 macOS 应用程序中,快速绘制是通过尽可能少地绘制来实现的。这有两个好处

  1. 通过告诉系统屏幕上已更改的最小区域,我们可以将更少的像素推回屏幕
  2. 我们不需要重绘未更改的像素,因此您可以跳过遍历图层、绘制路径、阴影等的逻辑。

我们发现编辑符号母版实际上会导致整个画布重绘,这与我们如何跟踪文档中的更改有关 — 通过计算一系列不可变树上的差异。我们将在未来的文章中讨论这带来的更大的好处,但可以肯定地说,这是一个值得修复的错误。

未来的蓝图

如果说有什么教训可以从中吸取的话,那就是偶尔停下来调查一下你已经拥有的东西非常重要。很容易就会潜入一些小效率低下的问题,而且由于它们发生在代码库的其他持续变化之间,因此很容易被忽略。使 Sketch 尽可能响应迅速和可靠是我们优先考虑的事项,我们将继续为此做出努力。

不过,现在如果您还没试用过 Sketch 67,并且您的文档中有很多符号,我希望您能试用一下,看看它带来的改变。

您可能也喜欢

Sketch 内部

Sketch 和 AI

一段时间以来,我们一直在思考 AI 对 Sketch 的意义。以下是我们可能使用它、永远不会使用它以及指导我们思考的方式。

免费试用 Sketch

无论您是 Sketch 的新手,还是回来看看有什么新功能,我们都会让您在几分钟内完成设置并准备好完成您的最佳作品。

免费开始
免费开始
1280x720