CSS3 中实体元素与透明元素的性能

Performance of solid elements versus transparent elements in CSS3

渲染纯色和透明色时的性能差异是什么。 loadingscrolling 都是网页。假设它们都由 GPU 处理,差异变得很小,但我仍然想知道。采取了哪些额外步骤来生成透明元素,透明元素对 FPS 的影响是否比常规元素更大?

从技术上讲,这不仅限于颜色,还包括 solid elementstransparent elements

JSFiddle Demo 选择的颜色是 SO 绿色 :)

CSS

.example1{
  background-color:#75845c;
  color: #e1e818;
}

.example2{
  background-color:#75845c;
  color: rgba(255, 255, 0, 0.6);
}

HTML

<div class="example1">
  I am a solid color
</div>
<br />
<div class="example2">
  I am a transperant color
</div>

简答:browser-dependent。现在长答案...

[作为背景,我是从一个人的角度来看这个的,这个人一直在混合、渐进和合成像素,这是生活中令人尴尬的一大当务之急,从早期的 DOS 中戳视频内存今天的游戏到 low-level UI 套件和绘图库到光线追踪器和 GPU 着色器。它的核心始终是图像处理。我的工作通常与网络非常分离,而且相当 lower-level,但这似乎是一个更概念化的问题。我从未实现过网络浏览器,但已经实现了 general-purpose 网络浏览器所需的许多相同的光栅化技术,并且针对具有脚本和节点编程的插件架构,面临许多类似的设计和优化挑战和妥协浏览器实现者必须面对所有的可能性。]

Alpha-Blending便宜

在最高的概念级别上,尤其是在这种情况下,alpha 混合像素的成本非常低,您可能永远不必担心这个成本(除非您每帧渲染数百万个粒子或类似的东西).要将像素混合在一起,只需在覆盖内存中的目标像素之前涉及一些基本算法。

即使是基本的 CPU 实现也可以每秒处理数亿像素(其中涉及的每个像素都经过 alpha 混合),而快速 alpha 混合是一个 well-studied 问题在图像处理和光栅化的背景下,从快速 8 位 lerps 和缩放到利用最近的硬件趋势(如 SIMD),非常好的解决方案已经为人所知多年。当 GPU 介入时,算术运算以涡轮速度进行(而且它们已经快得惊人)。

但是Alpha-Blending可能需要一些不便宜的东西

但是,这是一个孤立的案例,仅研究混合透明元素的成本。围绕此有各种复杂因素,可能使渲染透明元素成为热点。

首先,GPU 扫描线光栅化旨在完成比简单地将图像混合在一起更复杂的事情。 per-fragment 基础上涉及顶点变换以及着色和照明。即使你使用 none 这些东西但使用扫描线光栅化将这些图像显示为纹理,hardware/rasterization 管道被设计用来做这些事情,并且无论如何都必须付出很多成本。因此,通过扫描线光栅化进行的 alpha 混合可能开始成为瓶颈,但这并不是因为 alpha 混合算法。这是因为 alpha-blended 片段总是必须支付全部渲染成本,并且不能被涉及 z-buffer.

的深度测试排除在外

这变成了 non-issue,但是,在使用 GPGPU 而不是扫描线光栅化的上下文中(例如:使用 GPU 对最初存储在系统内存中的图像进行一系列算术运算,而不涉及完整的 GPU扫描线流水线)。然而,这正在进入猜想,如果他们选择使用 GPU,许多浏览器可能更喜欢普通的 GPU 路线而不是 GPGPU,因为它是更 widely-supported,成熟的路线。

另一个突然出现的问题,但在 3D 上下文中更多,是 alpha-blending 的许多形式就它们提供的结果而言是 order-specific。片段呈现的顺序很重要。在 3D 上下文中,如果我们要渲染一百万个半透明多边形,现在我们必须以 depth-sorted 顺序渲染它们的片段,以确保一致、正确的结果。这种排序开销非常昂贵,即使使用非常优化的近似方法,如 Dual-Depth 剥离。

这个 depth-sorting 问题通常在 2D 上下文中变得没有实际意义。 2D 上下文通常可以通过开发人员请求绘制事物的顺序简单地产生所需的结果。 2D 元素通常也具有恒定深度(其深度不会变化 per-fragment),因此它不会 intersect/overlap 与其他元素的深度在 per-pixel/fragment 基础上呈现。

不尽如人意的世界

可能与这个一般性问题最相关的是,即使接近理想的概念水平,事情也很少得到优化。

alpha 混合的需要可能会在 less-than-ideal 实现中引起辅助需求。例如,您 alpha-blending 的内容可能会在某些实施中变得非常重要。

例如,如果您在渲染的透明前景元素后面有一个静态背景,则此 less-than-ideal 实现可能必须更频繁地处理背景(以及很多比理想情况下更多)。浏览器必须处理涉及 client-side 脚本和小程序的动态世界,其中图形可能会根据无限可能的条件发生变化。

可能会毁了破坏他们关于引入透明元素的静态与动态的假设,并且可能需要对昂贵的背景元素进行额外的再处理(例如:每次滚动时)。至少我在这里看到了一些 performance-related 问题,这些问题似乎表明可能是这种情况,其中引入一个非常简单的透明元素(绘制起来应该很便宜)会对性能产生巨大的负面影响,而且大多数可能是由于对静态元素的重复、冗余处理,浏览器不再能够对其做出坚定的假设。当然,这都是推测。

在更简单的层面上,alpha 混合多层确实需要检查每一层的内存。如果你,比如说,alpha 混合了一个巨大的图像上的一个小透明元素,即使 alpha 混合过程只需要合成少量像素,它仍然必须移动这个巨大图像的部分内存(它没有在这个上下文中跨扫描线的非常好的参考位置)从慢得多的内存区域一直向上缓存层次结构并进入寄存器*。根据此合成过程必须发生的频率以及浏览器为降低此频率而缓冲的程度,它可能会成为一个很大的瓶颈。

* 为简单起见,我将避免在没有缓存的情况下进入流式处理 loads/stores——无论如何,同样的内存趋势经常存在。

如果您曾经遇到过这种情况,解决此类问题的一种非常通用的方法是使复合材料中涉及的层更便宜。例如,可以将史诗背景图像分解为拼接在一起的较小图像,只有特定的较小图像需要合成。这改善了缓存局部性,即使通常会在 pixel-by-pixel 基础上应用相同数量的工作来将这两个元素组合在一起*。

* 在计算中,一个常见的误解是做相同数量的工作,甚至执行相同的指令,将具有相同的成本。有动态的硬件和操作系统因素使许多指令具有可变成本,其中大多数 note-worthy 是硬件将内存从较大但较慢类型的内存移动到更快、较小类型的内存并落后的性质软件开发人员的支持。

滚动和加载

What is the performance difference when rendering a solid color and a transparent color. Both when loading and scrolling a web page.

同样,alpha 混合非常便宜。但是,透明元素可能会破坏 less-than-ideally-implemented 浏览器可以对不透明元素进行的一些潜在优化。这比加载更可能出现在滚动中(因为加载只需要发生一次)。

结论

简而言之,在这个问题的上下文中,alpha 混合过程本身非常便宜。甚至要让它成为一个问题,通常需要混合数百万像素,甚至开始显示为可能需要担心的事情。

但是,为了将像素混合在一起所涉及的辅助过程,尤其是在那些现实的 less-than-ideal 实现中,可能会开始变得昂贵。不幸的是,如果不了解特定浏览器的实现,就不可能对这些进行精确细分,但上面的这些要点应该涵盖了很多广泛的可能性。