自发布以来,
WebAssembly技术立即引起了前端开发人员的注意。 Web社区热烈接受在以JavaScript以外的语言编写的浏览器中运行代码的想法。 最主要的是,WebAssembly保证的速度远远高于JavaScript。
我们的工程师密切关注标准的制定。 在所有主要的浏览器中都实现了WebAssembly 1.0支持后,开发人员立即想尝试一下。
但是有一个问题。 尽管
许多应用程序都受益于WebAssembly,但是电子商务中的技术范围仍然很原始。 我们无法立即找到其使用的正确版本。 有一些建议,但是JavaScript在所有版本中都更好。 当我们在eBay上评估新技术时,第一个问题是:“对我们的客户有哪些潜在好处?” 如果此处不清楚,我们将不进行下一步。 即使对客户无关紧要,只会使现有的工作流程复杂化,但很容易被新的流行技术所吞噬。 用户体验始终比开发人员体验更重要。 但是与WebAssembly不同。 这项技术具有巨大的潜力,我们只是找不到合适的用例。 但是,最终他们仍然找到了它。
条码扫描器
在iOS和Android上的本机eBay应用程序中,具有
UPC条码扫描功能可自动输入表单。 它仅在应用程序中有效,并且需要对设备上的图像进行密集处理,以便识别来自相机的图像流中的条形码数字。 然后将生成的代码发送到服务器服务,该服务器服务依次填写表格。 这意味着设备上的图像处理逻辑必须非常有效。 对于本机应用程序,我们将自己的C ++库编译为iOS和Android的本机代码。 它对条形码的识别非常好。 我们正在逐步转向iOS和Android中的本机API,但是我们的C ++库仍然可靠。
条形码扫描仪对卖家来说是一种直观的功能,它大大简化了表格的填写。 不幸的是,该功能在网站的移动版本上不起作用,卖家不得不手动输入UPC,这很不方便。
网络条码扫描器
我们曾经寻找一种在网络上扫描条形码的选项。 两年前,他们甚至发布了基于
BarcodeReader开源JavaScript库的原型。 问题在于它仅在20%的情况下有效。 其余80%的时间,扫描仪工作极慢或完全不工作。 在大多数情况下,这是超时。 可以预料到:只有在“热路径”上,JavaScript才能与本机代码进行速度比较,也就是说,它已由
JIT编译器进行了高度优化。 诀窍在于,JavaScript引擎会使用多种启发式方法来确定路径是否“热”而不保证结果。 这种差异显然导致用户沮丧,因此我们必须禁用此功能。 但是现在一切都不同了。 随着网络平台的快速发展,出现了一个问题:“是否有可能在网络上实现可靠的条形码扫描仪?”
一种选择是等待
Shape Detection API及其内置的图像检测功能(包括
条形码)退出。 但是这些接口仍处于开发的早期阶段,与跨浏览器的兼容性还相去甚远。 即使在这种情况下,也
不能保证在所有平台上都能正常工作。 因此,您必须考虑其他选择。
这就是WebAssembly发挥作用的地方。 如果在WebAssembly上实现了条形码扫描仪,则可以保证它可以工作。 WebAssembly的强类型和字节码结构使您可以始终保持执行的“热路径”。 另外,我们已经有一个本机应用程序的C ++库。 C ++库是在WebAssembly中进行编译的理想选择。 我们认为问题已解决。 事实并非如此。
建筑学
WebAssembly上条形码扫描仪的有效原型架构非常简单。
- 用Emscripten编译C ++库。 它将产生中间件和.wasm文件。
- 从主线程中选择一个工作线程。 用于工作程序的JavaScript代码将导入生成的JavaScript链接代码,该代码随后将创建.wasm文件。
- 主流将快照从摄像机的流发送到工作人员的流,它将通过连接代码调用相应的WASM API。 API响应传递到主线程。 响应可以是UPC字符串(传递到后端),如果未检测到条形码,则为空字符串。
- 对于空白答案,重复上述步骤,直到检测到条形码为止。 此周期运行指定的时间间隔(以秒为单位)。 达到阈值后,我们将显示警告消息“无效的产品代码。 尝试使用其他条形码或文本搜索 。 ” 用户没有将相机聚焦在真实的条形码上,或者扫描仪的效率不足。 我们跟踪超时统计信息,以此作为扫描仪质量的指标。
WebAssembly工作流程合编
任何WebAssembly项目的第一步都是定义一个清晰的编译管道。 Emscripten已经成为编译WebAssembly的事实上的标准,但是具有一致的环境以产生确定性的结果很重要。 我们的前端基于Node.js,因此我们需要找到与npm工作流程兼容的解决方案。 幸运的是,在那个时候,
Surma Das发表了一篇
名为“ Emscripten and npm”的文章。 基于
Docker的WebAssembly编译方法很有意义,因为它消除了大量的开销。 根据文章的建议,我们从
trzeci 拍摄了Emscripten的码头工人
形象 。 为了在WebAssembly中启用编译,必须对本地C ++库进行一些调整。 基本上,我们的行为是随机,反复试验的。 最后,我设法对其进行了编译,并在现有的装配流水线中建立了一个简洁的WebAssembly工作流。
它工作很快,但是...
扫描仪性能通过每秒Wasm API处理的帧数来衡量。 Wasm API从摄像机的视频流中获取一帧,进行计算并返回响应。 持续进行直到检测到条形码。 性能以FPS衡量。
我们的WebAssembly测试实现显示了惊人的50 FPS速度。 但是,它仅在60%的情况下有效,在其余情况下,由于超时而崩溃。 即使具有如此高的FPS,他们也无法快速检测出剩余40%扫描的条形码,并在最后发出警告消息。 相比之下,以前的JavaScript实现通常以1 FPS运行。 是的,WebAssembly快得多(50倍),但是由于某种原因,它在几乎一半的情况下不起作用。 还应注意,在某些情况下,JavaScript可以很好地工作并立即找到条形码。 一种明显的选择是增加超时时间,但这只会增加用户的沮丧感,因此我们无法解决真正的问题。 因此,我们放弃了这个想法。
最初,我们无法理解为什么在本机应用程序中运行良好的本机C ++库无法在Web上显示相同的结果。 经过长时间的测试和调试,我们发现识别速度取决于对象的聚焦角度和背景阴影。 但是,然后一切如何在本机应用程序中工作呢? 事实是,在本机应用程序中,我们使用内置的API进行自动聚焦,并通过将手指指向条形码为用户提供了手动聚焦的机会。 因此,本机应用程序始终为库提供高质量的清晰图像。
意识到正在发生的事情的实质,我们决定尝试另一个本地库:一个相当流行且稳定的开源
ZBar条码扫描器。 更重要的是,它适用于模糊和颗粒状图像。 为什么不尝试一下呢? 由于我们已经有了WebAssembly工作流,因此在WebAssembly中ZBar的编译和部署可以顺利进行。 表现出不错的表现,大约15 FPS,尽管不如我们自己的C ++库好。 但是在相同的超时时间内成功率接近80%。 与我们的C ++库相比有明显的改进,但仍不是100%。
结果尚未使我们满意,但我们注意到了一些意外情况。 Zbar崩溃的地方,我们自己的C ++库很快完成了这项工作。 这真是令人惊喜。 图书馆似乎以不同的方式处理了不同质量的图像。 这使我们想到了这个主意。
多线程和速度赛车
您可能已经了解了。 为什么不创建两个工作线程:一个用于Zbar,一个用于我们的C ++库,而不是并行运行它们。 谁赢了(谁首先发送了有效的条形码),就将结果发送到了主流,并且两个工作人员都停了下来。 我们实施了这样的方案并开始进行自我测试,尝试模拟尽可能多的方案。 此设置显示成功扫描的95%。 比以前的结果好得多,但仍不是100%。
奇怪的建议之一是将原始JavaScipt库添加到竞赛中。 这将是三个流。 老实说,我们认为这不会改变任何事情。 但是这样的测试不需要任何努力,因为我们对工作界面进行了标准化。 令我们惊讶的是,通过三个流,成功率确实接近100%。 这再次完全出乎意料。 如前所述,JavaScript在某些情况下效果很好。 显然,他缩小了差距。 因此,该法律的普遍智慧是
“ JavaScript永远赢 。
” 如果没有笑话,下图将概述我们已实现的最终体系结构。
网络架构条码扫描器下图显示了高级功能图:
条形码扫描仪的功能图资源加载说明
呈现主页后,将预加载扫描仪工作所需的资源。 这样,目标网页可以快速加载并准备进行交互。 加载主页后,将使用
XMLHttpRequest预先加载和缓存WebAssembly资源(wasm文件和中间件脚本)和JavaScript扫描程序库。 在此很重要,不要立即执行它们,以使主线程可以自由供用户与页面交互。 仅当用户单击条形码图标时才会执行。 如果用户在加载资源之前单击该图标,则将按需加载并立即执行。 该页面已装入条形码扫描器事件处理程序和辅助控制器,但它们很小。
结果
经过员工的严格测试和内部使用,我们对用户进行了A / B测试。 扫描仪图标(下面的截图)显示给测试组,但不显示给对照组。
最终产品为了衡量成功,我们引入了“完成率草案”指标。 这是开始编辑草稿和提交表单之间的时间。 该指标应显示条形码扫描仪如何帮助人们填写表格。 测试持续了几个星期,结果非常令人满意。 它们与我们最初的假设完全一致。
使用条形码扫描仪的流的草稿完成时间减少了30%。A / B测试结果我们还添加了配置文件,以评估所有类型的扫描仪的有效性。 不出所料,Zbar贡献最大(成功扫描的53%),然后是我们的C ++库(34%),最后是JavaScript库的13%。
结论
实施WebAssembly的经验对我们来说非常有用。 工程师对新技术的出现感到非常高兴,并立即想尝试一下。 如果该技术对客户也有用,那么这就是双重喜悦。 让我们重复本文开头表达的想法。 技术发展非常迅速。 每天都有新事物出现。 但是只有少数技术对客户很重要,WebAssembly就是其中之一。 我们从此练习中得出的最大结论是,在99种情况下表示“否”,只有在对客户真正重要的情况下,才表示“是”。
将来,我们计划扩大条形码扫描仪的使用范围,并将其介绍给买方,以便他们可以离线扫描产品代码以在eBay上搜索和购买。 我们还将考虑使用Shape Detection API和浏览器中的其他功能来扩展该功能。 但是我们很高兴在eBay上找到WebAssembly的正确用例,并成功地将该技术应用于电子商务。
特别感谢Surma Das和
Lin Clark在WebAssembly上发表的许多文章。 他们确实帮助我们几次打破了僵局。