在上一篇文章中,老司机带你了解了像 JavaScript 这样的语言是如何自动管理内存的。还解释了如何在 C 语言中手动管理内存。
我们为什么要在介绍 ArrayBuffers 和 SharedArrayBuffers 之前,先解释内存管理的知识呢?
这是因为,在 JavaScript 中,正是 ArrayBuffers 给你提供了手动管理内存的途径。
为什么要去手动管理内存呢?
正如我们在上一篇文章中谈到的关于自动内存管理的利弊:自动内存管理对开发人员来说比较友好。但它增加了一些额外的开销,在某些情况下,这些开销可能导致性能问题。
例如,当你在 JS 中创建变量时,引擎必须猜测它的数据类型,以及如何保存在内存中。因此,JS 引擎通常预留的空间比这个变量真正需要的空间大很多。根据变量的不同,内存分配可能会比实际需要的大2-8倍,这会导致大量的内存浪费。
此外, 某些创建和使用 JS 对象的模式会使收集垃圾变得更加困难。如果你手动管理内存的话, 可以根据实际使用需求来决定分配和释放内存的策略。
大多数时候, 这没什么大不了的。因为,大多数场景对性能要求并不苛刻,你无需手动管理内存。对于常见场景,手动内存管理甚至可能会更慢。
但是对于那些在底层需要极致优化的场景,ArrayBuffers 和 SharedArrayBuffers 就派上用场了。

那么 ArrayBuffer 怎么工作?

它基本上就像其它 JavaScript 数组一样。但是,ArrayBuffer 的元素必须是字节(可以用数字表示),对象或字符串这类的 JavaScript 类型的数据是不行的。
有一点我应该在这里明确指出,你并没有将这个字节直接添加到 ArrayBuffer 中。ArrayBuffer 本身并不知道字节应该有多大,也不知道不同的数字应该如何转换成字节。
ArrayBuffer 只是一串 0 和 1。它是不知道怎么拆分这个数组中各个元素的。
为了提供上下文信息,把 ArrayBuffer 拆分开,我们需要将它放在视图中。这些数据的视图可以添加类型化数组,并且有很多不同的类型数组可以使用。
例如,你可以使用 Int8 类型的数组,将 ArrayBuffer 分解为8位字节。
或者你可以用一个无符号的 Int16 类型数组,它可以将 ArrayBuffer 分解成16位不带符号整数。
同一 buffer 上可以有多个视图,不同的视图会为相同的操作提供不同的结果。
例如,我们从这个 ArrayBuffer 的 Int8 视图获取的元素,和从它的 Uint16 视图获取的元素就是不同的值,即使它们包含完全相同的 bits。
通过这种方式,ArrayBuffer 基本上就像原始内存,让你可以像使用 C 语言那样直接操作内存。
你可能会想知道为什么我们不让程序员直接访问内存,而是添加这一层抽象。这是因为直接访问内存将会打开一些安全漏洞。以后我会写一篇文章对此进行详细的解释。

那么 SharedArrayBuffer 是什么?

要解释 SharedArrayBuffers,我需要先解释一下并行运行代码和 JavaScript。
并行运行代码会使你的代码运行更快,也可以更快的响应用户的事件。要做到这一点,你需要先拆分工作。
在一个典型的应用中,所有工作全部单独由主线程来处理。主线程就像一个全栈开发者,它负责处理 JavaScript,Dom,和布局。
任何减少主线程工作负载的事对代码运行效率都是有帮助的。在某些情况下,ArrayBuffer 可以减少主线程的工作。
但有时仅仅减少主线程工作是不够的,你还需要一个增援来分担一部分工作。
大多数语言里,这种分割工作的方法可以使用多线程实现。这就像多人在一个项目上工作。如果有些任务是相互独立的且没有依赖,那么就可以把它们分配到不同线程上。然后,这些线程可以同时处理单独的任务。
在 JavaScript 中,可以通过 web worker 来实现这些,但跟其他语言中的线程处理方式有些不同。默认情况下,它们不共享内存。
这意味着,如果想处理一些其他线程上的数据,你不得不通过 postMessage 方法将数据完整的复制一份过来。
postMessage 会将你传进去的东西序列化,然后发送给另一个 web worker,那边会反序列化并放入内存中。
这是一个相当缓慢的过程。
对于某些数据,比如 ArrayBuffer,你还可以使用“转移内存”。这种方式会把指定区域的内存移动到另一个 web worker 那里。
但是之前的 web worker 将不再能访问这些被转移走的内存。
转移内存这种方式适用于某些场景,但是对于更多的高性能并行的场景,共享内存才是你真正想要的。
这就是 SharedArrayBuffers 能给你的。
有了 SharedArrayBuffers,多个 web workers,多个线程都可以在同一块内存上读写数据。
这意味着他们不会再有使用 postMessage 时的通讯开销和延迟。所有 web workers 都可以即时访问数据。
当然,多个线程同时访问内存是有风险的,这会引起条件竞争(race conditions)问题。
我会在下一篇中详细说明。
SharedArrayBuffers 的支持情况
SharedArrayBuffers 即将在所有主流浏览器中支持。
Safari 10.1 已经支持了,Firefox 和 Chrome 的版本 将在7月或8月发布。而 Edge 计划在秋季 Windows 的更新中得到支持。
即使所有主流浏览器都支持了,我们也不指望应用开发者们直接使用它们。事实上,我们也不推荐直接使用。你应该使用的是最顶部的抽象层。
我们希望 JavaScript 库的开发者们开发出更简单安全的使用 SharedArrayBuffers 的库。
此外,一旦 SharedArrayBuffers 内置到平台中,WebAssembly 可以利用它实现多线程。到那时,你就可以使用像 Rust 这种以处理并发性为目标的语言一样轻松的处理多线程。
下一章,我们将介绍那些库开发者们构建抽象同时又避免条件竞争(race conditions)所使用的工具 Atomics
 

看图学习 ArrayBuffers 和 SharedArrayBuffers的更多相关文章

  1. VS2017 community版使用码云(gitee)的一些过程,看图学习,傻瓜式教程

    首先你得有一个gitee账号,VS2017IDE开发工具 第一步,打开VS2017,点击菜单栏上->工具->扩展与更新,如图 然后点击 联机 然后输入 gitee 回车搜索 一定要选择我圈 ...

  2. (CV学习笔记)看图说话(Image Captioning)-1

    Background 分别使用CNN和LSTM对图像和文字进行处理: 将两个神经网络结合: 应用领域 图像搜索 安全 鉴黄 涉猎知识 数字图像处理 图像读取 图像缩放 图像数据纬度变换 自然语言处理 ...

  3. 学习笔记TF060:图像语音结合,看图说话

    斯坦福大学人工智能实验室李飞飞教授,实现人工智能3要素:语法(syntax).语义(semantics).推理(inference).语言.视觉.通过语法(语言语法解析.视觉三维结构解析)和语义(语言 ...

  4. 【转载】跟着9张思维导图学习JavaScript

    原文:跟着9张思维导图学习JavaScript 学习的道路就是要不断的总结归纳,好记性不如烂笔头,so,下面将 po 出我收集的 9 张 JavaScript相关的思维导图(非原创). 思维导图小ti ...

  5. Multimodal —— 看图说话(Image Caption)任务的论文笔记(一)评价指标和NIC模型

    看图说话(Image Caption)任务是结合CV和NLP两个领域的一种比较综合的任务,Image Caption模型的输入是一幅图像,输出是对该幅图像进行描述的一段文字.这项任务要求模型可以识别图 ...

  6. [看图说话]在VMware Workstation 9中安装Mac OS X 10.8 Mountain Lion

    本文环境: CPU:Intel Core i7 920: OS:Windows 7: 内存:8G: 玩Hackintosh各有各的理由,不管什么理由,利用虚拟机安装Mac OS X都是一个可行的办法. ...

  7. 跟着9张思维导图学习Javascript js 关键字和保留字 css3中的BFC,IFC,GFC和FFC

    跟着9张思维导图学习Javascript   学习的道路就是要不断的总结归纳,好记性不如烂笔头,so,下面将 po 出我收集的 9 张 javascript 相关的思维导图(非原创). 思维导图小ti ...

  8. 关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL))

    关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL)) 欢迎fork本项目原始链接:关于图计算&图学习的基础知识概览:前置知识点学习 ...

  9. 图学习【参考资料2】-知识补充与node2vec代码注解

    本项目参考: https://aistudio.baidu.com/aistudio/projectdetail/5012408?contributionType=1 *一.正题篇:DeepWalk. ...

随机推荐

  1. C#LeetCode刷题之#9-回文数(Palindrome Number)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3840 访问. 判断一个整数是否是回文数.回文数是指正序(从左向右 ...

  2. 初识ABP vNext(2):ABP启动模板

    目录 前言 开始 AbpHelper 模块安装 最后 前言 上一篇介绍了ABP的一些基础知识,本篇继续介绍ABP的启动模板.使用ABP CLI命令就可以得到这个启动模板,其中包含了一些基础功能模块,你 ...

  3. Typora markdown代码块显示序号

    打开偏好设置,找到代码块 打开显示行号 然后关闭Typora重新打开 此时代码块就有行号了

  4. 双系统Linux和win10系统时间不一样。

    https://jingyan.baidu.com/article/456c463b4e6a5a0a5831443a.html

  5. Vue.js中传值给子部件及触发动作的问题

    最近研究一个用vue.js做的程序并修改增加功能.其中用到传值给子部件等问题. template中有个子部件: <template> ...... <child-form  v-if ...

  6. EXCEL 中数据 批量 填充进 word 中

    工具:Python3.7 需求描述:将EXCEL中 第二行 数据 填在 word 对应位置上,然后保存为 "姓名+任务.docx"文件. 再将EXCEL中 第三行 数据 填在 wo ...

  7. 手把手教你写VueRouter

    Vue-Router提供了俩个组件 `router-link` `router-view`, 提供了俩个原型上的属性`$route` `$router` ,我现在跟着源码来把它实现一下 开始 先看平时 ...

  8. 小程序 RecorderManager计时不准确问题

    官方文档:RecorderManager 录音管理器,内部实现计时不准确.有以下俩个问题: 点击暂停继续,当录音结束时,stop返回的时间包含了暂停的那一段时间. 正常录音,录音文件的时长有概率少个1 ...

  9. cmd 和powershell 用git 显示乱码

    错误: 解决: 只需在环境变量中加入 LESSCHARSET=utf-8

  10. py_选择排序

    # 选择排序 # 一趟排序记录最小值,放到第一个位置 #再一趟排序记录记录列表无序区最小的数,放到第二个位置 #.... # 关键点:有序区.无序区.无序区最小值 #方法一 def select_So ...