JavaScript数组进化与性能分析实例

在使用 javascript 前,我对 c、c++、c# 这些已经颇为熟悉。与许多 c/c++ 开发者一样,javascript 给我的第一印象并不好。本文主要和大家介绍了javascript 数组的进化与性能分析,本文讲得更多的是内存、优化、语法差异、性能、近来的演进。需要的朋友可以参考下,希望能帮助到大家。

Array 是主要原因之一。JavaScript 数组不是连续(contiguous)的,其实现类似哈希映射(hash-maps)或字典(dictionaries)。我觉得这有点像是一门 B 级语言,数组实现根本不恰当。自那以后,JavaScript 和我对它的理解都发生了变化,很多变化。

为什么说 JavaScript 数组不是真正的数组

在聊 JavaScript 之前,先讲讲 Array 是什么。

数组是一串连续的内存位置,用来保存某些值。注意重点,“连续”(continuous,或 contiguous),这很重要。

立即学习“Java免费学习笔记(深入)”;

JavaScript数组进化与性能分析实例

上图展示了数组在内存中存储方式。这个数组保存了 4 个元素,每个元素 4 字节。加起来总共占用了 16 字节的内存区。

假设我们声明了 tinyInt arr[4];,分配到的内存区的地址从 1201 开始。一旦需要读取 arr[2],只需要通过数学计算拿到 arr[2] 的地址即可。计算 1201 + (2 X 4),直接从 1209 开始读取即可。

JavaScript数组进化与性能分析实例

JavaScript 中的数据是哈希映射,可以使用不同的数据结构来实现,如链表。所以,如果在 JavaScript 中声明一个数组 var arr = new Array(4),计算机将生成类似上图的结构。如果程序需要读取 arr[2],则需要从 1201 开始遍历寻址。

以上急速 JavaScript 数组与真实数组的不同之处。显而易见,数学计算比遍历链表快。就长数组而言,情况尤其如此。

JavaScript 数组的进化

不知你是否记得我们对朋友入手的 256MB 内存的电脑羡慕得要死的日子?而今天,8GB 内存遍地都是。

与此类似,JavaScript 这门语言也进化了不少。从 V8、SpiderMonkey 到 TC39 和与日俱增的 Web 用户,巨大的努力已经使 JavaScript 成为世界级必需品。一旦有了庞大的用户基础,性能提升自然是硬需求。

实际上,现代 JavaScript 引擎是会给数组分配连续内存的 —— 如果数组是同质的(所有元素类型相同)。优秀的程序员总会保证数组同质,以便 JIT(即时编译器)能够使用 c 编译器式的计算方法读取元素。

不过,一旦你想要在某个同质数组中插入一个其他类型的元素,JIT 将解构整个数组,并按照旧有的方式重新创建。

因此,如果你的代码写得不太糟,JavaScript Array 对象在幕后依然保持着真正的数组形式,这对现代 JS 开发者来说极为重要。

此外,数组跟随 ES2015/ES6 有了更多的演进。TC39 决定引入类型化数组(Typed Arrays),于是我们就有了 ArrayBuffer。

ArrayBuffer 提供一块连续内存供我们随意操作。然而,直接操作内存还是太复杂、偏底层。于是便有了处理 ArrayBuffer 的视图(View)。目前已有一些可用视图,未来还会有更多加入。

var buffer = new ArrayBuffer(8);var view  = new Int32Array(buffer);view[0] = 100;

登录后复制

高性能、高效率的类型化数组在 WebGL 之后被引入。WebGL 工作者遇到了极大的性能问题,即如何高效处理二进制数据。另外,你也可以使用 SharedArrayBuffer 在多个 Web Worker 进程之间共享数据,以提升性能。

从简单的哈希映射到现在的 SharedArrayBuffer,这相当棒吧?

旧式数组 vs 类型化数组:性能

前面已经讨论了 JavaScript 数组的演进,现在来测试现代数组到底能给我们带来多大收益。下面是我在 Mac 上使用 Node.js 8.4.0 进行的一些微型测试结果。

旧式数组:插入

var LIMIT = 10000000;var arr = new Array(LIMIT);console.time("Array insertion time");for (var i = 0; i < LIMIT; i++) {arr[i] = i;}console.timeEnd("Array insertion time");

登录后复制

用时:55ms

Typed Array:插入var LIMIT = 10000000;var buffer = new ArrayBuffer(LIMIT * 4);var arr = new Int32Array(buffer);console.time("ArrayBuffer insertion time");for (var i = 0; i < LIMIT; i++) {arr[i] = i;}console.timeEnd("ArrayBuffer insertion time");

登录后复制

用时:52ms

擦,我看到了什么?旧式数组和 ArrayBuffer 的性能不相上下?不不不。请记住,前面提到过,现代编译器已经智能化,能够将元素类型相同的传统数组在内部转换成内存连续的数组。第一个例子正是如此。尽管使用了 new Array(LIMIT),数组实际依然以现代数组形式存在。

接着修改第一例子,将数组改成异构型(元素类型不完全一致)的,来看看是否存在性能差异。

旧式数组:插入(异构)var LIMIT = 10000000;var arr = new Array(LIMIT);arr.push({a: 22});console.time("Array insertion time");for (var i = 0; i < LIMIT; i++) {arr[i] = i;}console.timeEnd("Array insertion time");

登录后复制

用时:1207ms

改变发生在第 3 行,添加一条语句,将数组变为异构类型。其余代码保持不变。性能差异表现出来了,慢了 22 倍。

旧式数组:读取

var LIMIT = 10000000;var arr = new Array(LIMIT);arr.push({a: 22});for (var i = 0; i < LIMIT; i++) {arr[i] = i;}var p;console.time("Array read time");for (var i = 0; i < LIMIT; i++) {//arr[i] = i;p = arr[i];}console.timeEnd("Array read time");

登录后复制

用时:196ms

Typed Array:读取var LIMIT = 10000000;var buffer = new ArrayBuffer(LIMIT * 4);var arr = new Int32Array(buffer);console.time("ArrayBuffer insertion time");for (var i = 0; i < LIMIT; i++) {arr[i] = i;}console.time("ArrayBuffer read time");for (var i = 0; i < LIMIT; i++) {var p = arr[i];}console.timeEnd("ArrayBuffer read time");

登录后复制

用时:27ms

结论

类型化数组的引入是 JavaScript 发展历程中的一大步。Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,这些是类型化数组视图,使用原生字节序(与本机相同)。我们还可以使用 DataView 创建自定义视图窗口。希望未来会有更多帮助我们轻松操作 ArrayBuffer 的 DataView 库。

JavaScript 数组的演进非常 nice。现在它们速度快、效率高、健壮,在内存分配时也足够智能。

以上就是JavaScript数组进化与性能分析实例的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2786473.html

(0)
上一篇 2025年3月8日 17:45:38
下一篇 2025年3月8日 17:45:44

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • js高效率服务器时间同步实例

    本文主要和大家分享一个js倒计时的功能代码,首先说一下,为什么要服务器时间同步, 因为服务器时间和本地电脑时间存在一定的时间差。有些对时效性要求非常高的应用,例如时时彩开奖,是不能容忍这种时间差存在的。 方案1:每次倒计时去服务端请求时间 …

    编程技术 2025年3月8日
    200
  • js中Date()日期函数浏览器兼容问题如何解决

    一般直接new date() 是不会出现兼容性问题的,而 new date(datetimeformatstring) 常常会出现浏览器兼容性问题,为什么,datetimeformatstring中的某些格式浏览器不兼容。本文主要和大家介绍…

    编程技术 2025年3月8日
    200
  • JS鼠标3次点击事件的实现代码

    这几天看了一下javascript高级程序设计中的dom事件相关内容,同时看到网上有关鼠标多次点击事件,鼠标事件是简单、常用的事件之一,于是便针对点击事件进行一些小的扩展和实现,增强对dom事件的进一步理解。其中的实现和思路是自己总结的,有…

    编程技术 2025年3月8日
    200
  • js实现1,2,3,5数字按照概率生成代码分享

    本文主要和大家介绍了js实现1,2,3,5数字按照概率生成,需要的朋友可以参考下,希望能帮助到大家。 js按照配置的概率生成,概率规则如下:1————50% 2——&#…

    编程技术 2025年3月8日
    200
  • JavaScript面向对象实例详解

    构造函数和原型对象 构造函数也是函数,用new创建对象时调用的函数,与普通函数的一个区别是,其首字母应该大写。但如果将构造函数当作普通函数调用(缺少new关键字),则应该注意this指向的问题。本文主要和大家介绍了JavaScript面向对…

    2025年3月8日
    200
  • JS数据类型转换总结

    在js中数据类型转换有两种强制类型转换和隐式类型转换。本文主要和大家分享js数据类型转换总结,希望能帮助到大家。 隐式类型转换原则 都是数字,直接运算 都是字符串,使用字符对应的ASCII值运算 有一个是boolean值,将boolean值…

    2025年3月8日
    200
  • JavaScript面试基础知识题分享

    根据StackOverflow调查, 自2014年一来,JavaScript是最流行的编程语言。当然,这也在情理之中,毕竟1/3的开发工作都需要一些JavaScript知识。因此,如果你希望在成为一个开发者,你应该学会这门语言。 这篇博客的…

    2025年3月8日
    200
  • JavaScript相等性判断分享

    JavaScript提供三种不同的值比较操作 严格相等 “===” 宽松相等 “==” Object,is(es6d的新特性) 本文主要和大家分享JavaScript相等性判断,希望能帮助到大…

    2025年3月8日
    200
  • js实现省市区三级联动插件分享

    本文主要和大家分享js实现省市区三级联动插件,希望本文能帮助大家更好的掌握省市区三级联动插件的实现方法。 // 页面上先引入css与js文件 登录后复制 页面中的容器标签不限制,只需给个id就行 var address = new Addr…

    2025年3月8日
    200
  • 几个JavaScript异步加载相关问题

    默认的js是同步加载的,这里的“加载”可以理解成是解析、执行,而不是“下载”,在最新版本的浏览器中,浏览器对于代码请求的资源都是瀑布式的加载,而不是阻塞式的,但是js的执行总是阻塞的。这会引起什么问题呢?如果我的index页面要加载一些js…

    编程技术 2025年3月8日
    200

发表回复

登录后才能评论