师夷长技以制夷:跟着PS学前端技术(二)

简介: 师夷长技以制夷:跟着PS学前端技术(二)

3.2 发挥WebAssembly的威力

WebAssembly对于在JavaScript中重新创建Photoshop的计算密集型图形处理是一个不可或缺的要素。Adobe使用Emscripten编译器将他们现有的C/C++代码库移植到WebAssembly模块中。

兼容性

还是熟悉的配方,我们通过caniuse来查看,桌面浏览器对WebAssembly的支持程度。哇塞,形势一片大好。各大厂商都意识到这个神兽能给我们带来更多意想不到的可能性。

其实,暂且不看市面上公司如何使用,从各个厂商的积极程度也侧面反应了,我们的预期。

image.png

几个WebAssembly的功能至关重要:

  • 线程 - Photoshop使用工作线程以并行方式执行任务,比如处理图像块
  • SIMD - SIMD矢量指令加速像素操作和过滤。
  • 异常处理 - C++异常广泛用于整个Photoshop的代码库。
  • 流式实例化 - Photoshop的80MB+ WASM模块需要流式编译。
  • 调试 - Chrome的WebAssembly在DevTools中的调试支持是非常有价值的。

如果大家对WebAssembly还不是很了解的话,可以翻阅我们之前写的浏览器第四种语言-WebAssembly。针对wasm的概念性东西这里就不在过多介绍了。在里面我们还介绍了利用Emscripten实现了 将C/C++代码编译为WebAssembly

并且,在我们之前还介绍过,CJS代码之间的互操作。感兴趣的可以参看WebAssembly-C与JS互相操作

而我们来讲讲SIMD的东西。


SIMD

SIMD代表单指令,多数据。是Single Instruction, Multiple Data的缩写。

SIMD操作这个术语指的是一种计算方法,它能够通过单个指令来处理多个数据。相比之下,传统的顺序方法使用一条指令来处理每个单独的数据,这被称为标量操作

以简单的加法为例,下面说明了标量操作SIMD操作之间的差异。

image.png

使用传统的标量操作,必须依次执行四个加法指令才能获得如图(a)所示的总和。与此同时,SIMD只使用一条加法指令就能获得相同的结果,如图(b)所示。由于处理相同数量的数据所需的指令更少,SIMD操作比标量操作具有更高的效率

这里简单的说一句题外话:标量这个词是不是感觉似曾相识。其实,我们在介绍Rust数据结构的时候就有过接触呢。

image.png

这下估计就知道标量操作就是单一操作了。

SIMD指令是一类特殊指令,通过同时对多个数据元素执行相同的操作,来充分利用应用程序中的数据并行性。计算密集型应用程序,如音频/视频编解码器、图像处理器,都是利用SIMD指令来加速性能的示例。

SIMD的限制

尽管SIMD操作具有能够在一条指令中处理多个数据的优势,但它们只能应用于特定预定义的处理模式。下图展示了一个这样的模式,在该模式中,所有数据都执行相同的加法操作

image.png

SIMD操作不能用于以不同方式处理多个数据。下图中提供了一个典型的示例,其中一些数据需要相加,而其他数据需要相减、相乘或相除。

image.png

SIMD操作就是需要所有数据都是执行相同的操作)

想了解更多关于SIMD概念性的东西,可以参看SIMD基础介绍 (需要🪜)

由于SIMDwasm的特性,而我们的关注点又是浏览器环境,我们就挑一个我们熟悉的浏览器chrome来描述一下,所以我们看看V8是如何支持这个特性的。(V8chrome/chromium的关系我们之前聊过)

由于可编译为wasm的语言过于多,例如C/C++/Rust甚至TypeScript。所以,我们就挑一个我们比较感兴趣的语言来说明。

将Rust代码编译为WebAssembly SIMD

当将Rust代码编译为WebAssembly SIMD目标时,我们需要启用与Emscripten中的simd128 LLVM特性相同的特性。

当启用msimd128特性时,默认情况下启用LLVM的自动矢量化器,即在优化级别-O2-O3时启用。

如果可以直接控制rustc标志或通过环境变量RUSTFLAGS,可以传递-C target-feature=+simd128

RUSTFLAGS="-C target-feature=+simd128" cargo build

或者

RUSTFLAGS="-C target-feature=+simd128" cargo build

例如,考虑以下函数,该函数将两个输入数组的元素相乘并将结果存储在输出数组中。

pub fn multiply_arrays(out: &mut [i32], in_a: &[i32], in_b: &[i32]) {
  in_a.iter()
    .zip(in_b)
    .zip(out)
    .for_each(|((a, b), dst)| {
        *dst = a * b;
    });
}

如果没有传递msimd128特性,编译器会生成以下WebAssembly循环:

(loop
  (i32.store
    … 获取`out`中的地址 …
    (i32.mul
      (i32.load … 获取`in_a`中的地址 …)
      (i32.load … 获取`in_b`中的地址 …)
)

但是,当使用msimd128特性时,自动矢量化器会将其转换为包含以下循环的代码:

(loop
  (v128.store align=4
    … 获取`out`中的地址 …
    (i32x4.mul
       (v128.load align=4 … 获取`in_a`中的地址 …)
       (v128.load align=4 … 获取`in_b`中的地址 …)
  )
)

循环体的结构相同,但在循环体内部使用SIMD指令加载、相乘和存储四个元素


启发&应用场景

与其说是启发,倒不如说是,WebAssembly能够给我们带来多大的惊喜。在之前的文章中,我们聊过WebAssembly在哪些场景下能够大放异彩。 而今天既然聊到了WebAssembly -SIMD,那我们到底看看它是否还有绝活


WebAssembly SIMD提案旨在加速高计算应用程序,如音频/视频编解码器、图像处理应用程序、加密应用程序等。

MediaPipe是一个用于构建多模式(例如视频、音频、任何时间序列数据)应用机器学习管道的框架。

其中一个视觉效果最吸引人的演示,可以很容易地观察到SIMD带来的性能差异,是一个仅使用CPU构建的手部跟踪系统。没有启用SIMD时,在现代笔记本电脑上只能获得大约14-15帧每秒(FPS),而在Chrome Canary中启用SIMD后,您可以获得更平滑的体验,帧率可达38-40帧每秒。

image.png

OpenCV,这是一个流行的计算机视觉库,也可以编译成WebAssembly。

OpenCVIntel开源计算机视觉库。它由一系列C 函数和少量C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。

其中它有一个WebCamera的项目,如下图。做了一下用于图像和视觉处理的工具。

image.png

此图,就是用于用摄像头识别银行卡中的帐号数据,并对齐提取。

image.png

那是不是,在我们遇到类似的功能点时,我们在已经引入到对应的视觉处理工具后,效果还没达到我们的心里预期,那WebAssembly SIMD不就有了用武之地了吗。

不仅,视觉处理,还有音频处理也是相同的道理。这里就不展开说明了。


3.3 将sRGB替换为P3

还有老样子,让我们can一下。

image.png

DCI-P3,有时也称为P3Display P3DCIDigital Cinema Initiatives的缩写,是数字电影领域的一个标准。

sRGB代表标准红绿蓝,是一种颜色空间,也是一组特定的颜色,由惠普和微软于1996年创建,旨在标准化电子设备中显示的颜色。sRGB是目前最流行的颜色空间,用于Windows、大多数网络浏览器以及大多数控制台和个人电脑游戏,除非它们支持高动态(HDR)。

显示器或其他设备的色域告诉我们设备可以重现哪个颜色空间,以及它可以在0-100%甚至更高的范围内呈现多少颜色。除了sRGB,其他常见的颜色空间还包括Adobe RGBP3,它们都比sRGB更大,即包含更多颜色

下面是XY色度图,代表了人眼可以看到的所有颜色范围。在那个颜色范围内,有一个白色的三角形,它勾勒出sRGB标准所包括的颜色。例如,如果我们试图在sRGB显示器上查看超出该三角形范围的颜色的图像,那些额外的颜色会显得不准确和饱和不足

image.png

sRGB vs P3

虽然sRGB是标准,但其他颜色空间也可能更具吸引力。P3表现色域比sRGB更大(覆盖更多颜色)。

P3显示的色域比sRGB显示器宽50%

image.png

白线显示了sRGB的边缘。它上面右边的部分是Display-P3颜色,而这些颜色在sRGB中是不可用的。请注意,绿色扩展得很大,而蓝色扩展则远远不及。

sRGBP3之间的另一个区别是P3可以处理10位颜色

Photoshop使用新的color()函数和Canvas API来释放P3的全部光彩,实现更准确的颜色呈现。

color: color(display-p3 1 0.5 0)

上面的语法等同于旧有的css表示颜色的语法。

  • hsl(42, 70%, 50%)
  • rgb(3, 5, 11)
  • #abc

如果我们想使用p3可以使用@supports功能查询。

/* sRGB颜色。 */
:root {
    --bright-green: rgb(0, 255, 0);
}
/* Display-P3颜色,如果支持的话。 */
@supports (color: color(display-p3 1 1 1)) {
    :root {
        --bright-green: color(display-p3 0 1 0);
    }
}
header {
    color: var(--bright-green);
}

启发

如果我们在项目中,想要实现一下对色彩饱和度有强烈要求的功能,那么我们就可以使用color(display-p3)来增强我们的项目。虽然,写不出五彩斑斓的黑,红的发紫的白。但是这也算是我们扩展应用功能的一把利器。

好钢要用在刀刃上


3.4 利用Web组件提升UI的灵活性

Photoshop利用基于Lit构建的标准化Web组件策略,可以实现应用程序之间的UI一致性。

image.png

Photoshop的用户界面元素来自AdobeSpectrum Web Components库,该库实现了Adobe的设计系统。

Spectrum Web Components具备以下特点:

  • 默认支持辅助功能 — 开发时考虑了现有和新兴的浏览器规范,以支持辅助技术。
  • 轻量级 — 使用LitElement实现,减小了额外开销。
  • 基于标准 — 基于Web Componment标准,如自定义元素和Shadow DOM 构建。
  • 框架无关 — 由于浏览器级别的支持,可以与任何框架一起使用。

此外,整个Photoshop应用程序都是使用基于LitWeb组件构建的。Lit的模板和虚拟DOM diff使得UI更新更加高效。Web组件的封装性也使得在需要时可以轻松集成来自其他团队的React代码。

我们在之前的文章中也有对Lit有过涉猎,本人也在项目中也有对应的简单应用。咋说呢,感觉Lit的封装还是很nice的。但是,如果硬要刨根问底的话,其实还是要从Web Componment来讲。

如果想了解Lit可以通过Lit 官网去学习和查阅。这里就不在多讲。

虽然,现在Vue/React等,框架大行其道,但是Web Componment中的一些理念和使用方式是最贴合浏览器渲染机制的。然后,由于篇幅有限,我们打算,针对Web Componment会做一次深度的解析和教学。

启发

虽然,不知道PS团队,不知出于何种目的,选用了Lit作为了构建前端页面的UI库。但是,想象一下,如果现在我们有一个大前端团队,由于历史包袱原因,即有React,又有Vue团队。现在有一个庞大的功能需求需要全团队配合去做。那是不是利用Lit或者Web Componment可以解决这个痛点。

但是呢,使用Lit只是一个跨语言合作的一个可行方案,我相信市面上肯定有很多解决方案,例如:Veaury

image.png

还有很多巨石应用的解决方案。这里也不过多展开了。


4. 优化Photoshop在浏览器中的性能

尽管新的Web功能提供了基础,但像Photoshop这样的高强度桌面应用程序仍然需要进行大量的跟踪和性能优化工作,以提供一流的在线体验。

4.1 使用Service Workers缓存资源和代码

Service Workers允许Web应用将其资源、代码和其他资源本地缓存,以在初始访问后加载速度更快。虽然它还不是一个完全离线可用的应用程序,但Photoshop已经利用Service Workers来缓存其WebAssembly模块、脚本和其他资源。

image.png

Adobe使用Workbox库更轻松地将Service Worker缓存集成到他们的构建过程中。

针对Worker呢,我们之前的文章就有过介绍。

image.png

分别对Web WorkerService Worker做了一次比较透彻的分析。

然后呢,其实在Service Worker始终有一种欲罢不能的感觉。就像上面说的,Photoshop是借助了Workbox实现了资源的本地缓存。同时,我也是第一次听说这个技术(Workbox),然后就这两天开始着手找资料学习和研究。发现,其中的很多点都很喜欢,然后也是有很多的点可讲。但是呢,由于现在有些东西还未亲身实践,所以有些想着,等我实践完然后准备写一篇或者多篇的文章,深度解析一下这个东西。

在这里,我就偷个懒了哈,不过更文列表中已经有计划了。优先级还很高呢。



4.2 V8对已缓存资源的优化

当资源从Service Worker缓存中返回时,V8会进行一些优化:

  • 在安装期间缓存的资源会被急切地编译,并立即进行代码缓存,以保持一致、快速的性能。
  • 通过Cache API缓存的资源在第二次加载时进行了优化缓存,比通常的缓存速度更快。
  • V8会检测已缓存资源的重要性,并更积极地进行编译。

这些优化允许对Photoshop庞大的缓存Wasm模块进行优化。

image.png


4.3 流式传输和缓存大型WebAssembly模块

Photoshop的代码库需要多个大型WebAssembly模块,其中一些超过80MBV8Chrome中的流式编译支持使这些大型模块可以在性能方面进行有效处理。

image.png

也就是说,V8不用讲wasm模块全盘接收,再开启编译模式。这样在很大程度上节省了时间,尤其在遇到大文件的时候。

此外,第一次从Service Worker请求WebAssembly模块时,V8会生成并存储一个优化版本以进行缓存,这对于Photoshop庞大的代码尺寸至关重要。

4.4 用于并行图形操作的多线程

Photoshop中的许多核心图像处理操作,如像素变换,可以通过跨线程并行执行来大幅加速。WebAssembly的线程支持可以利用多核设备进行计算密集型图形任务

这允许Photoshop在转移到WebAssembly后,使用与桌面相同的多线程方法来处理性能关键的图像处理函数。

4.5 用于优化的WebAssembly调试

在开发过程中,强大的WebAssembly调试支持对于诊断和解决性能瓶颈至关重要。

Chrome DevTool的能力可以对WASM代码进行性能分析、设置断点,并检查丰富的变量,这与JavaScript的调试性质相似。

image.png


5. 使用TensorFlow.js集成本地设备上的机器学习

最近版本的Web上的Photoshop包括使用TensorFlow.js的AI功能。在设备上运行模型而不是在云端改善了隐私、延迟和成本。

image.png

TensorFlow.jsGoogle推出的针对JavaScript开发者的开源机器学习库,能够在浏览器中客户端运行。它是用于Web机器学习的最成熟选择,具有全面的WebGLWebAssembly后端操作支持,未来还将提供WebGPU后端选项,以在浏览器中获得更快的性能,以适应新的Web标准的发展。"

"选择主题"功能利用机器学习自动提取图像中的主要前景对象,大大加速了复杂的选择操作。


image.pngimage.png

image.png

为了实现本地执行,该模型从TensorFlow转换为TensorFlow.js

// 加载“选择主题”模型
const model = await tf.loadGraphModel('select_subject.json');
// 在图像张量上运行推理
const {mask, background} = model.execute(imgTensor);

Adobe和Google合作开发了一个用于Emscripten的代理API,以解决Photoshop的WebAssembly代码和TensorFlow.js之间的同步问题,从而实现了这两个框架的无缝集成。

“由于Google团队通过其各种支持的后端(WebGL、WASM、Web GPU)提高了TensorFlow.js的硬件执行性能,这导致模型的性能改进在30%到200%之间(尤其是对于倾向于获得最大性能提升的较大模型而言),在浏览器中几乎实时性能。”


启发

这个点,算是继wasm在浏览器中实现,又一个让我眼前一亮的特性。现在大家都在卷各种大模型,国内国外都是如此,我们公司也有自己的AI团队。而大部分的开发模式,基本上都是将AI模型配置到后端,然后前端页面都是通过异步接口进行传值处理。其实这和旧有的前端开发模式没有任何的改变。

但是,在PS团队实现了基于TensorFlow.js的前端AI模型,那是不是变现的说,万物即可AI,并且在前端也会有一席之地。

等着,给我一段时间,到时候给大家出一篇在前端界面中使用TensorFlow.js的教程。(这个是真心喜欢研究的东西)


后记

写到这里,其实里面的内容过于多,本来不想再继续聒噪了,但是还是有感而发。

人人都说前端已死,但是你如果看到上面的一些技术和特性,你还会有这种感觉吗。

不要学着别人去,自怨自艾,只有自己内心渴望一个东西,你才会有勇气和动力去面对和征服它。

分享是一种态度

全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。

相关文章
|
1月前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
24天前
|
前端开发 JavaScript 搜索推荐
HTML与CSS在Web组件化中的核心作用及前端技术趋势
本文探讨了HTML与CSS在Web组件化中的核心作用及前端技术趋势。从结构定义、语义化到样式封装与布局控制,两者不仅提升了代码复用率和可维护性,还通过响应式设计、动态样式等技术增强了用户体验。面对兼容性、代码复杂度等挑战,文章提出了相应的解决策略,强调了持续创新的重要性,旨在构建高效、灵活的Web应用。
32 6
|
29天前
|
前端开发 JavaScript 搜索推荐
前端懒加载:提升页面性能的关键技术
前端懒加载是一种优化网页加载速度的技术,通过延迟加载非首屏内容,减少初始加载时间,提高用户访问体验和页面性能。
|
29天前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
41 5
|
1月前
|
移动开发 前端开发 JavaScript
惊!这些前端技术竟然能让你的网站在移动端大放异彩!
随着互联网技术的发展,移动设备成为主要的上网工具。本文介绍了几种关键的前端技术,包括响应式设计、图片优化、字体选择、HTML5和CSS3的应用、性能优化及手势操作设计,帮助开发者提升网站在移动端的显示效果和用户体验。示例代码展示了如何实现简单的双向绑定功能。
31 3
|
1月前
|
数据采集 前端开发 安全
前端测试技术
前端测试是确保前端应用程序质量和性能的重要环节,涵盖了多种技术和方法
|
1月前
|
编解码 前端开发 JavaScript
前端界的黑科技:掌握这些技术,让你的网站秒变未来感十足!
【10月更文挑战第31天】前端技术日新月异,黑科技层出不穷,让网页更加美观、交互更加丰富。本文通过响应式布局与媒体查询、前端框架与组件化开发等案例,展示这些技术如何让网站充满未来感。响应式布局使网站适应不同设备,前端框架如React、Vue则提高开发效率和代码质量。
42 3
|
1月前
|
前端开发 JavaScript 数据处理
前端界的宝藏技术:掌握这些,让你的网页秒变交互神器!
【10月更文挑战第31天】前端开发藏有众多宝藏技术,如JavaScript异步编程和Web Components。异步编程通过Promise、async/await实现复杂的网络请求,提高代码可读性;Web Components则允许创建可重用、封装良好的自定义组件,提升代码复用性和独立性。此外,CSS动画、SVG绘图等技术也极大丰富了网页的视觉和交互体验。不断学习和实践,让网页秒变交互神器。
30 2
|
1月前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
41 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
1月前
|
前端开发 JavaScript 开发者
惊!这些前端技术竟然能让你的网站在社交媒体上疯传!
【10月更文挑战第30天】在这个信息爆炸的时代,社交媒体成为内容传播的重要渠道。本文介绍了前端开发者如何利用技术让网站内容在社交媒体上疯传,包括优化分享链接、创建引人注目的标题和描述、利用Open Graph和Twitter Cards、实现一键分享功能以及创造交互式内容。通过这些方法,提升用户分享意愿,使网站成为社交媒体上的热门话题。
41 2
下一篇
DataWorks