Search code examples
performancecsscolorstransparencyhardware-acceleration

Performance of solid elements versus transparent elements in CSS3


What is the performance difference when rendering a solid color and a transparent color. Both when loading and scrolling a web page. Assuming they are both processed by the GPU, the difference becomes tiny however I'd still like to know. What extra steps are taken to generate the transparent elements, and do transparent elements weigh more heavily on FPS than regular elements?

Technically this is not limited to colors but solid elements versus transparent elements.

JSFiddle Demo colors selected were the SO greens :)

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>

Solution

  • Short answer: browser-dependent. Now for the long answer...

    [As a background, I'm coming at this from the angle of one who has been blending and lerping and compositing pixels as an embarrassingly large preoccupation in life, from poking video memory in early DOS games to low-level UI kits and drawing libraries to raytracers and GPU shaders today. At the heart of it was always image processing. My work is often very detached from the web and considerably lower-level, but this seems to be a more conceptual question. I've never implemented a web browser, but have implemented many of the same rasterization techniques required of a general-purpose web browser, and against plugin architectures with scripting and nodal programming, facing many of the similar design and optimization challenges and compromises that a browser implementor would have to tackle in the face of all the possibilities.]

    Alpha-Blending is Cheap

    At a peak conceptual kind of level, and especially in this kind of context, alpha blending pixels costs so little that you should probably never worry about this cost (unless you are rendering millions of particles per frame or something like that). To alpha blend pixels together simply involves some basic arithmetic prior to overwriting the target pixel in memory.

    Even a basic CPU implementation can blaze through hundreds of millions of pixels a second doing this (where every single pixel involved is being alpha blended), and fast alpha blending is a well-studied problem in the context of image processing and rasterization where very optimal solutions have been known for many years from fast 8-bit lerps and scales to utilizing recent hardware trends like SIMD. When the GPU becomes involved, arithmetical operations go at turbo speed (and they were already blazingly fast).

    But Alpha-Blending May Require Things That Aren't Cheap

    BUT, that's for an isolated case studying just the cost of blending transparent elements. There are all kinds of complicating factors around this that could make rendering transparent elements a hotspot.

    For a start, GPU scanline rasterization is designed to do far more complex things than simply blend images together. There are vertex transformations involved along with shading and lighting on a per-fragment basis. Even if you use none of this stuff but use scanline rasterization to display these images as textures, the hardware/rasterization pipeline is designed to do these kinds of things, and has to pay much of the cost regardless. As a result, alpha blending through scanline rasterization can start to become a bottleneck but not because of the alpha blending arithmetic. It's because an alpha-blended fragment always has to pay this full rendering cost, and cannot be excluded by a depth test involving the z-buffer.

    This becomes a non-issue, however, in a context using GPGPU instead of scanline rasterization (ex: using the GPU to do a bunch of arithmetic over an image stored originally in system memory without involving the full GPU scanline pipeline). However, and this is getting into conjecture, a lot of browsers may favor the ordinary GPU route anyway instead of GPGPU if they choose to utilize the GPU, as it's the more widely-supported, mature path.

    Another issue that crops up, but more in 3D contexts, is that many forms of alpha-blending are order-specific with respect to the results they provide. The order in which the fragments are rendered matters. In a 3D context, if we have a million translucent polygons to render, now we have to render their fragments in a depth-sorted order to ensure consistent, proper results. That sorting overhead is extremely expensive, even with very optimal approximated methods like Dual-Depth Peeling.

    This depth-sorting issue often becomes moot, however, in 2D contexts. 2D contexts can often produce the desired result simply by the order in which the developer requests to draw things. A 2D element also generally has constant depth (its depth doesn't vary per-fragment), so it doesn't intersect/overlap with the depth of other elements being rendered on a per-pixel/fragment basis.

    A Less Than Ideal World

    Probably most relevant to this general question is that things are rarely optimized even close to an ideal conceptual level.

    The need for alpha blending may give rise to auxiliary needs in less-than-ideal implementations. For example, what you're alpha-blending over may start to become very relevant in some implementations.

    It's possible, for example, that if you have a static background behind the transparent foreground element you're rendering, this less-than-ideal implementation may have to process the background a lot more often (as well a lot more of it) than it ideally should. Browsers have to deal with dynamic worlds involving client-side scripting and applets where the graphics could potentially change based on an infinite possibility of conditions.

    It may wreck havoc on their assumptions about what is static vs. dynamic to introduce transparent elements, and may require additional reprocessing of expensive background elements (ex: every time when scrolling). At least I have seen some performance-related questions here which seem to suggest that could be the case, where the introduction of a very simple transparent element (which should be dirt cheap to draw) made a huge negative performance impact, and most likely due to repeated, redundant processing of static elements which the browser was no longer able to make firm assumptions about. This is all conjecture, of course.

    At a simpler level, alpha blending multiple layers does require examining the memory of each layer. If you, say, alpha blend even a teeny transparent element over a massive image, even though the alpha blending process only requires compositing a small number of pixels, it must still move portions of the memory of this massive image (which doesn't have very good locality of reference in this context across scanlines) from much slower regions of memory all the way up the cache hierarchy and into a register*. Depending on how frequently this compositing process has to occur and how much the browser is buffering to reduce this frequency, it may become a substantial bottleneck.

    * For simplicity I'll avoid going into streaming loads/stores without caching -- the same kind of memory trends often exist regardless.

    If you ever encounter such a scenario, a very general approach to tackle such a problem is to make the layers involved in the composite cheaper. For example, an epic background image can be decomposed into smaller images stitched together, with only specific smaller images requiring compositing. That improves cache locality even though the same amount of work will typically be applied on a pixel-by-pixel basis to composite these two elements together*.

    * It is a common misconception in computing that doing the same amount of work, or even executing identical instructions, will have identical cost. There are dynamic hardware and operating system factors which make many instructions have variable costs, most note-worthy of which is the nature in which the hardware moves memory from bigger, but slower types of memory to faster, smaller types of memory and behind the software developer's back.

    Scrolling and Loading

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

    Again, alpha blending is dirt cheap. However, transparent elements may wreck some potential optimizations that less-than-ideally-implemented browsers can make for opaque elements. This is far more likely to show up in scrolling than loading (since loading only has to occur once).

    Conclusion

    In a nutshell, the alpha blending process itself is very cheap in the context of this question. To even make it a concern would often requires millions and millions of pixels to be blended to even start showing up as a possible thing to worry about.

    However, the auxiliary processes involved in order to blend pixels together, and especially in those realistic less-than-ideal implementations, may start to become expensive. Unfortunately it's impossible to give a precise breakdown of these short of knowing a specific browser's implementation, but these points above should cover a lot of the broad possibilities.