背景

前一阵子开发的项目 pptx 导入, 由于自己的代码问题,引起了个性能问题,一个 40p 的 pptx 文件,转换成 json 数据,大概要耗时 60s+ ,虽然后面发现是某个使用频率非常高的函数内部,用了 new Function 构造函数 造成的(所以这里顺便提醒一下,如果你很在乎几毫秒的差距的话,建议谨慎使用哈),但是在优化的过程中,一度怀疑是性能达到了瓶颈,所以尝试了使用 web worker 去优化,由于是文件,一般内容都比较大,发现 web worker 在传值这块占用了大部分的时间,所以想开这篇来详细聊聊.

两种传值方式

关于 web worker 的基本用于以及传值方式,网上以及有一大堆介绍了,这里就不赘述了,这里我们重点来看一下同一个文件用两种方式来传值,会有多大的差别,这边随意从电脑里面找了一个 96MB 的 PSD 文件来测试.

主线程

fetch('./case.psd').then(file => {return file.blob();}).then(blob => {return new Promise(resolve => {let fileReader = new FileReader();fileReader.onload = e => {resolve(e.target.result);}fileReader.readAsArrayBuffer(blob);})}).then(buf => {let worker = new Worker('1.js');console.time('计算时间');worker.postMessage(buf);worker.onmessage = e => {console.timeEnd('计算时间');}})

worker(子)线程, 这里为了避免不必要的因素干扰,worker 线程里面什么也不做,在收到消息后,直接 post 一个消息回去

self.onmessage = e => {postMessage(0);}

这边我直接用 FileReader 的 readAsArrayBuffer,读出来是一个长度为 96,138,230 的字符串,长度大概 0.96 亿, 耗时大概 70ms 左右(同一个台电脑取 10 次平均值,下同)

我们稍微改一下上面主线程的代码,改用 转移数据 的方式


- worker.postMessage(buf);+ worker.postMessage(buf, [buf]);

同样的数据, 耗时大概 17ms 左右,这 17ms 好像是个固定值,我尝试换了个 800MB+ 的文件和一个里面啥都没有的空文本文件,大概都是这个时间.

不同的数据类型,用值传递的耗时也是不一样的

fetch('./case.psd').then(file => {return file.blob();}).then(blob => {return new Promise(resolve => {let fileReader = new FileReader();fileReader.onload = e => {resolve(e.target.result);}fileReader.readAsText(blob);})}).then(str => {console.log(str.length);let worker = new Worker('1.js');console.time('计算时间');worker.postMessage(str);worker.onmessage = e => {console.timeEnd('计算时间');}})

这里我们改用 FileReader 的 readAsText,读出来是一个长度为 95,855,954 的字符串,长度大概 0.95 亿, 耗时大概 118ms 左右,同样我换了上面那个里面啥都没有的空文本文件,耗时也是 17ms 左右.

那我们试试用 readAsDataURL 看看读出来的数据要多久

fetch('./case.psd').then(file => {return file.blob();}).then(blob => {return new Promise(resolve => {let fileReader = new FileReader();fileReader.onload = e => {resolve(e.target.result);}fileReader.readAsDataURL(blob);})}).then(str => {console.log(str.length);let worker = new Worker('1.js');console.time('计算时间');worker.postMessage(str);worker.onmessage = e => {console.timeEnd('计算时间');}})

读出来是一个长度为 128,184,345 的字符串,长度大概 1,28 亿, 耗时大概 85ms 左右(虽然字符串长度更长,但是耗时却更短)

以上耗时,均为主线成向 worker 线程单向传递数据的耗时.

结论

  1. 转移数据几乎是零开销(因为和传递空字符串的耗时是差不多的).
  2. 值传递的话,不同的数据类型,耗时也有差别,ArrayBuffer < base64 < 普通字符串.
  3. postMessage 传递消息,除了发送数据的耗时外,还有其他开销(就是上面的 17ms). 当然每台电脑性能不一样,耗时也是不一样的,不过按比例来看,这个占比还挺大的.

关于转移的缺点, 网上也是有很多的, 这里也就不啰嗦了, 总结一句就是数据无法同时在2个线程上使用.

另外个人觉得如果是普通的数据,为了转移而去转换成 Transferable objects 的话, 大部分情况下是划不来的, 因为你需要在花在编码解码上的时间,会比直接传递花的时间多.

另外, 如果你是要用子线程处理图片的话, ImageBitmap 格式 配合最近新鲜出炉的 OffscreenCanvas 也许是不错的选择.前提是你不需要考虑兼容性问题.

最后是广告时间

我们40人的前端团队常年招兵买马中,在厦门的和想来厦门的童鞋们,不要吝惜你的简历,使劲砸过来 邮箱:nuoya@gaoding.com, 期待你一起来稿事

原文地址 https://github.com/noahlam/ar...

转载于:https://www.cnblogs.com/qixidi/p/10390960.html

web worker 的传值方式以及耗时对比相关推荐

  1. 【有趣的实验】JAVA 遍历数组的几种方式的耗时对比

    一.前言 出于对遍历方式的耗时想法,是普通for循环.fori.foreach.迭代器 iterator.还是steam流的形式哪种耗时更少呢? 首先添加一个List 集合,这边采用ArraryLis ...

  2. web worker原理 SSE原理

    第一部分 什么是 web worker? 我们一直强调JavaScript是单线程的,但是web worker的出现使得JavaScript可以在多线程上跑,只是web worker本身适合用于一些复 ...

  3. Service Worker,Web Worker,WebSocket的对比

    Service Worker 处理网络请求的后台服务.适用于离线和后台同步数据或推送信息.不能直接和dom交互.通过postMessage方法交互. Web Worker 模拟多线程,允许复杂计算功能 ...

  4. 一文搞懂 Web Worker(原理到实践)

    作者:poetry 原文地址:https://mp.weixin.qq.com/s/XF7qOhbBtYlwADCiyxbT-w Web Worker 作为浏览器多线程技术,在页面内容不断丰富,功能日 ...

  5. Web Worker 初探

    (给前端大全加星标,提升前端技能) 作者:SHERlocked93 juejin.im/post/5b4af72ae51d45198d4b1388 以前我们总说,JS是单线程没有多线程,当JS在页面中 ...

  6. JavaScript多线程之HTML5 Web Worker

    在博主的前些文章Promise的前世今生和妙用技巧和JavaScript单线程和浏览器事件循环简述中都曾提到了HTML5 Web Worker这一个概念.在JavaScript单线程和浏览器事件循环简 ...

  7. PWA(Progressive Web App)入门系列:(五)Web Worker

    前言 在说Service Worker前有必要说一下Web Worker,因为Service Worker本身就属于Web Worker的延伸,大部分功能也是基于Web Worker进行的扩展. 背景 ...

  8. 一文了解Web Worker

    一.概述 众所周知,JavaScript最初设计是运行在浏览器中的,为了防止多个线程同时操作DOM带来的渲染冲突问题,所以JavaScript执行器被设计成单线程.但是随着前端技术的发展,JavaSc ...

  9. HTML加js实现计算文件哈希值,HTML5 File API 配合 Web Worker 计算大文件 SHA3 Hash 值

    这学期的安全学课程有个作业,内容是写一个软件实现 SHA3 Hash 值的快速计算.想一想老师这么安排,大致上也有一种推广新的密码学算法的意图.既然希望应用起来,天然跨平台的 Web 显然是一项非常具 ...

  10. Web Worker,Service Worker,Web Worker

    Web Worker.Worker Service和Service Worker Web Worker.Worker Service和Service Worker Service Worker.Wor ...

最新文章

  1. 类执行方法的过程与运行时
  2. 利用sendmail搭建邮件服务器
  3. python语言做法_python学习笔记(十六)
  4. Jquery 日历控件
  5. 触发器如何通知websocket_「Web应用架构」如何扩展WebSockets
  6. 三维点云学习(5)1-introduction on to Deep learning
  7. antd的select的滚动条怎么才会出现_纵向滚动条对横向滚动条的影响
  8. 16QAM的理论误码率仿真
  9. 电商管理后台 API 接口文档
  10. 当马队遭遇狼群,阿里华为长篇竞合剧基情开幕
  11. 为出海掘金创造更多可能 助力开发者触达全球用户
  12. win7怎么查看计算机用户名,Win7怎么查看自己电脑ip地址?
  13. pytorch之torch.zeros_like
  14. 计算机环境安全容器服务未启动怎么解决,音频服务未运行|音频服务未启动 - 音频服务未运行的解决办法 - 安全专题...
  15. jQuery中所用到的第三方插件
  16. ASUS华硕/RT-AC1200GU vs TP-LINK双千兆WDR6500
  17. 第十七章 使用系统监视器 - 使用 ^%SYSMONMGR 实用程序
  18. xml建模包括以下_()是专业建模语言。A.XMLB.UMLC.VC++D.JAVA - 信管网
  19. 桂电信科17级c语言期末试卷,桂电期末考试Linux习题总结
  20. 超越股神的贝佐斯:“我可是在做一件大事”

热门文章

  1. PollingBlockTracker - encountered an error while attempting to update latest block:
  2. 区块链 自私挖矿(selfish mining)是什么
  3. -1交替c语言代码,排序(1)---------选择排序(C语言实现)(示例代码)
  4. mysql 导入 druid,Druid数据库连接池的使用(非常实用!!!)
  5. A non well formed numeric value encountered
  6. 十四、Oracle学习笔记:集合操作
  7. Logstash 日志搜集处理框架 安装配置
  8. 阶段3 3.SpringMVC·_04.SpringMVC返回值类型及响应数据类型_2 响应之返回值是String类型...
  9. 阶段2 JavaWeb+黑马旅游网_15-Maven基础_第5节 使用骨架创建maven的java工程_11使用骨架创建maven的java工程...
  10. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_5_函数式接口作为方法的参数案例...