首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >有人能解释一下这种出乎意料的V8 JavaScript性能行为吗?

有人能解释一下这种出乎意料的V8 JavaScript性能行为吗?
EN

Stack Overflow用户
提问于 2020-01-06 09:19:21
回答 1查看 198关注 0票数 8

更新(2020年3月2日)

事实证明,在我的示例中,编码是以正确的方式构造的,可以在V8 JavaScript引擎中从已知的性能悬崖上掉下来……

有关详细信息,请参阅关于bugs.chromium.org的讨论。这个错误现在正在研究中,应该在不久的将来修复。

更新(2020年1月9日)

我试图将以下面描述的方式运行的编码隔离到一个页面Web应用程序中,但是这样做,这种行为就消失了(??)。然而,下文所述的行为在全面适用的情况下仍然存在。

尽管如此,我已经优化了分形计算编码,这个问题在实时版本中不再是一个问题。如果有人感兴趣,那么显示此问题的JavaScript模块仍然可用这里

概述

我刚刚完成了一个基于网络的小应用程序,比较了基于浏览器的JavaScript和Web的性能。此应用程序计算Mandelbrot集图像,然后当鼠标指针移动到该图像上时,动态计算相应的Julia集,并显示计算时间。

您可以在使用JavaScript (按'j')或WebAssembly (按'w')来执行计算和比较运行时之间切换。

单击这里查看工作应用程序

然而,在编写这段代码时,我发现了一些出乎意料的奇怪的JavaScript性能行为。

问题摘要

  1. 这个问题似乎是针对用于Chrome和Brave的V8 JavaScript引擎的。在使用SpiderMonkey (火狐)或JavaScriptCore (Safari)的浏览器中没有出现此问题。我无法使用脉轮引擎在浏览器中测试这一点。
  2. 这个网络应用程序的所有JavaScript代码都写成了ES6模
  3. 我尝试使用传统的function语法而不是新的ES6箭头语法重写所有函数。不幸的是,这并没有造成任何明显的差别。

性能问题似乎与创建JavaScript函数的范围有关。在这个应用程序中,我调用了两个部分函数,每个函数都给出了另一个函数。然后,我将这些生成的函数作为参数传递给嵌套for循环中调用的另一个函数。

相对于它执行的函数,for循环似乎创建了类似于它自己的作用域的东西(但不确定它是一个完整的作用域)。然后,将生成的函数传递到这个作用域(?)边界太贵了。

基本编码结构

每个部分函数接收鼠标指针在Mandelbrot集图像上的位置的X或Y值,并返回在计算相应的Julia集时要迭代的函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const makeJuliaXStepFn = mandelXCoord => (x, y) => mandelXCoord + diffOfSquares(x, y)
const makeJuliaYStepFn = mandelYCoord => (x, y) => mandelYCoord + (2 * x * y)

这些函数在以下逻辑中调用:

  • 用户将鼠标指针移动到Mandelbrot集的图像上,触发mousemove事件。
  • 将鼠标指针的当前位置转换为Mandelbrot集的坐标空间,将(X,Y)坐标传递给函数juliaCalcJS,计算相应的朱莉娅集。
  • 在创建任何特定的Julia集时,调用上述两个部分函数来生成在创建Julia集时要迭代的函数。
  • 然后,一个嵌套的for循环调用函数juliaIter来计算朱莉娅集中每个像素的颜色。完整的编码可以看到这里,但基本逻辑如下: const juliaCalcJS = (cvs,juliaSpace) => { // Set初始化画布,并为画布中的每个像素创建一个新的图像数组//生成函数来计算当前的朱莉娅集let juliaXStepFn = makeJuliaXStepFn(juliaSpace.mandelXCoord) let juliaYStepFn = makeJuliaYStepFn(juliaSpace.mandelYCoord) /.for (设iy = 0;iy < cvs.height;++iy) { for (设ix = 0;ix < cvs.width;++ix) { //将像素值转换为x_coord = juliaSpace.xMin + (juliaSpace.xMax - juliaSpace.xMin) * ix / (cvs.width - 1)让y_coord = juliaSpace.yMin + (juliaSpace.yMax - juliaSpace.yMin) * iy / (cvs.height - 1) /计算当前像素的颜色让thisColour = juliaIter(x_coord,y_coord,juliaXStepFn,x_coord,y_coord,juliaXStepFn,( juliaYStepFn) // Snip -将像素值写入图像数组}} // Snip -将图像数组写入画布}
  • 如您所见,调用makeJuliaXStepFnmakeJuliaYStepFnfor循环外返回的函数将传递给juliaIter,后者将完成计算当前像素颜色的所有艰苦工作。

当我看这个代码的结构时,我一开始想:“这很好,一切都很好,所以这里没什么问题。”

只是有。表演比预期要慢得多.

意外解决方案

很多人抓着头到处乱动.

过了一会儿,我发现如果将函数juliaXStepFnjuliaYStepFn的创建移到外部或内部的for循环中,那么性能就会提高2到3倍.

天啊!?

所以,代码现在看起来如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const juliaCalcJS =
  (cvs, juliaSpace) => {
    // Snip - initialise canvas and create a new image array

    // For each pixel in the canvas...
    for (let iy = 0; iy < cvs.height; ++iy) {
      // Generate functions for calculating the current Julia Set
      let juliaXStepFn = makeJuliaXStepFn(juliaSpace.mandelXCoord)
      let juliaYStepFn = makeJuliaYStepFn(juliaSpace.mandelYCoord)

      for (let ix = 0; ix < cvs.width; ++ix) {
        // Translate pixel values to coordinate space of Julia Set
        let x_coord = juliaSpace.xMin + (juliaSpace.xMax - juliaSpace.xMin) * ix / (cvs.width - 1)
        let y_coord = juliaSpace.yMin + (juliaSpace.yMax - juliaSpace.yMin) * iy / (cvs.height - 1)

        // Calculate colour of the current pixel
        let thisColour = juliaIter(x_coord, y_coord, juliaXStepFn, juliaYStepFn)

        // Snip - Write pixel value to image array
      }
    }

    // Snip - write image array to canvas
  }

我本以为这个看似微不足道的更改会降低效率,因为每次迭代for循环时,都会重新创建一对不需要更改的函数。然而,通过在for循环中移动函数声明,这段代码的执行速度要快2到3倍!

有人能解释一下这种行为吗?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-02 07:06:11

我的代码在V8 JavaScript引擎中掉下了一个已知的性能悬崖.

问题和修复的细节在bugs.chromium.org上进行了描述。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59616335

复制
相关文章
从嵌套结构中取值时如何编写兜底逻辑
对a解构时赋予的默认值(空数组),仅当b.a的值为undefined时才会生效,如果b.a的值为null,默认值就无法生效,使得第二行调用map方法的代码直接报错,所以第一行代码兜底并没有做好。
大史不说话
2020/11/03
2.9K0
Java从Object取值
在我们进行springboot的model、view、controller方式进行的时候,常常会遇到需要从请求的参数中去除具体值的业务,下面我们就提供了一种Java从Object对象中解析出对象属性和对象值之后并转换为实体的过程,示例代码如下:
问问计算机
2021/05/08
3.2K0
tensorflow中取值
本文主要介绍了在 TensorFlow 中如何取出张量(Tensor)的返回值。首先介绍了两种方法:使用 tf.cast() 和 tf.to_int32(),但它们都返回了 Tensor 对象。然后,文章介绍了如何将 Tensor 对象转换为变量类型,通过使用 tf.Variable 和 tf.Session()。最后,文章通过示例代码展示了如何将变量类型转换为 Tensor 对象。
用户1148830
2018/01/04
2.1K0
loadrunner动态从mysql取值
loadrunner动态从mysql取值 [需要下载跟数据库服务器一致的dll,32位或64位]
流柯
2018/08/31
9610
如何优雅地链式取值
但是对于这种操作报出类似于Uncaught TypeError: Cannot read property 'goods' of undefined 这种错误也是再正常不过了,如果说是res数据是自己定义,那么可控性会大一些,但是如果这些数据来自于不同端(如前后端),那么这种数据对于我们来说我们都是不可控的,因此为了保证程序能够正常运行下去,我们需要对此校验:
用户1515472
2019/07/24
1.1K0
【编程基础】C语言指针、引用和取值
什么是指针?什么是内存地址?什么叫做指针的取值?指针是一个存储计算机内存地址的变量。“引用”表示计算机内存地址。从指针指向的内存读取数据称作指针的取值。指针可以指向某些具体类型的变量地址,例如int、long和double。指针也可以是void类型、NULL指针和未初始化指针。本文会对上述所有指针类型进行探讨。 根据出现的位置不同,操作符 * 既可以用来声明一个指针变量,也可以用作指针的取值。当用在声明一个变量时,*表示这里声明了一个指针。其它情况用到*表示指针的取值。 &是地址操作符,用来引用一个内存地址
程序员互动联盟
2018/03/12
2.6K0
【编程基础】C语言指针、引用和取值
VBA实战技巧16:从用户窗体的文本框中复制数据
有时候,我们需要从用户窗体的文本框中复制数据,然后将其粘贴到其他地方。下面举例说明具体的操作方法。
fanjy
2021/01/20
4K0
VBA实战技巧16:从用户窗体的文本框中复制数据
Python 面向对象编程(OOP) ——取值,赋值方法and逻辑
如果类能够在为属性赋值之前对值进行检查,就会更实用, 这样,类就可以确保它发送的都是有效数据,这就可使类及实例 更加准确, 可靠。
Gorit
2021/12/09
1.1K0
Python 面向对象编程(OOP) ——取值,赋值方法and逻辑
Excel中如何对多张图片或者文本框元素进行快速排版?
在Excel中对多张图片或者文本框元素进行快速排版非常简单,并不需要一个一个地拖,而且拖动的时候还老是对不齐。以一个简单的例子说明如下:
大海Power
2021/08/30
2.2K0
从N个数组分别取值,穷尽全部情况
有N个数组,每个数组元素不定,从每个数组都中取出一个,组成长度为N的序列,求穷尽序列的所有情况。
ZONGLYN
2019/08/08
8450
【说站】python字符串如何取值
字符串都有序列存储。第一个字节的索引是0,第二个索引是1,第三个是2,一次排序。在字符串中空格也占字节。
很酷的站长
2022/11/23
8260
【说站】python字符串如何取值
如何提高编程能力?(中)
函数方程: y - f2 = (f2 - f1) / (x2 - x1)(x - x2) 化简得: x=(f2x1-f1x2)/(f2-f1)
公众号guangcity
2019/09/20
8240
layui弹出层中添加文本框
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/132366.html原文链接:https://javaforall.cn
全栈程序员站长
2022/06/29
1.8K0
layui弹出层中添加文本框
python中int的取值范围_int32的取值范围是多少?
int32的数值取值范围为“-2147483648”到“2147483647”;而int64的数值取值范围为“-9223372036854775808”到“9223372036854775808”。
全栈程序员站长
2022/09/29
3.1K0
python中int的取值范围_int32的取值范围是多少?
用户窗体编程:实现组合框与文本框联动
在VBE中,插入一个类模块,将其重命名为“CComboboxes”。在该类模块中,输入代码:
fanjy
2023/09/27
6100
用户窗体编程:实现组合框与文本框联动
JS中的JSON对象 定义和取值[通俗易懂]
1.JSON(JavaScript Object Notation)一种简单的数据格式,比xml更轻巧。JSON是JavaScript原生格式,这意味着在JavaScript中处理JSON数据不需要任何特殊的API或工具包。
全栈程序员站长
2022/08/03
8.7K0
浅谈RPA软件如何填写富文本框
什么是富文本框?富文本框就是在网页上可以输入带格式的文本输入框。在富文本框中,可以设置使用不同的字体、颜色,可以控制段落、边距,还可以插入图片、表情等。是实现在线编辑不可或缺的工具。在html表单控件里,并没有标准的富文本框控件,一般使用特定元素和css,js配合实现。
木头软件
2023/07/01
4180
从机器学习学python(三) ——数组冒号取值与extend
从机器学习学python(三)——数组冒号取值与extend (原创内容,转载请注明来源,谢谢) 一、数组冒号取值 1、 小白级别 python的特有取值方式,假设数组a = [0,1,2,3,4],则: b=a[:3]表示b取数组a第四个元素之前的元素,即b=[0,1,2] c=a[:-1]则表示取a最后一个元素前面的所有元素,即c=[0,1,2,3] 原理是因为冒号前面带0的可以省略掉。 2、困难级别 b=array( [ [ [ 0, 1, 2, 3]
用户1327360
2018/03/07
1.6K0
点击加载更多

相似问题

如何从文本框中自动取值

116

从文本框中获取值

46

jquery -如何从文本框中获取值?

40

从文本框中获取值

22

从文本框中读取值

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文