前言

之所以会研究这个东西,是我在网上找了一下各个语言的执行效率比较。好吧,我承认这是个无聊的东西,不过看看总是无妨,然而我惊讶的发现,有些测试声称Java,C,Nodejs是处在同一个效率级别参见链接。这个让我很是惊讶,因为在我的理解中,像nodejs这种解释语言,每一个对象应该都是一个key-value字典结构,那么每一个属性查找的速度就会被C这种编译语言甩开一条街。

那么,nodejs的属性查找是怎么实现的?

我有很多定义说的不太准确的,大家理解意思就行。。别揪着一两个名词不放,求高抬贵手。

property lookup

property lookup,就是指找到程序中某一个对象的属性的具体内存位置以完成读写,根据我的理解,根据是否支持动态属性,编程语言的property lookup一般会有两个方案。

  • 静态属性语言

    这种语言基本都是编译语言,比如C,C++,Java。编译语言其实是不存在property lookup这个事的,或者说,他的property lookup已经在编译阶段完成了,例如下面的code:

    a.b = 24

    在编译后会直接变成对内存位置的写入操作,根本不需要lookup

    set pos[offset] 24
    // 原谅我汇编稀烂,明白意思就行
  • 动态属性语言

    动态属性语言指的是对象的属性是可以随时动态存取的,动态属性带来了极大的灵活性,但同时也对效率带来了较大影响。

    通常动态类型语言的对象模型就是一个字典,每一次property lookup,都需要一个字典的查询过程,那么就包含了hash值的计算,然后key的字符串比较,成功后才能返回属性对应值,比如同样的一个命令:

    a['b'] = 24       //支持以字符串来动态更新属性

    往往会变成以下过程:

    hash_code = hash('b')
    if(a.dict[hash_code] == null) return null
    if(a.dict[hash_code].key == 'b') return a.dict[hash_code].value
    hash_code = rehash(hash_code)...

    不用想也知道,每一次property lookup都这么麻烦,执行效率必然会比第一种语言低很多了。

    那么nodejs的对象模型有什么不同之处,可以弥补这条鸿沟?

V8所做的优化

这里我们拎出nodejs的执行引擎中效率最好的佼佼者--- V8引擎,看看它的特别之处。在V8的官方文档中给出了说明。V8采取了一种类似编译语言的机制:hidden class.

V8会给每一个创建的对象都创建一个hidden class,比如下面这段代码:

    funciton Person(x, y){
this.x = x;
this.y = y;
}

V8会创建出三个hidden_class分别对应于 Person{}, Person {x: }, Person {x: y:},具体过程可以参见官方说明。

那么这三个hidden_class有啥作用?这个必须跟V8的Inline Cache结合起来才行。

inline cache

V8解释完js脚本后生成的不是中间语言,而是直接的机器语言。而且v8使用了inline cache技术。

inline cache具体是什么?简单的说,就是试图通过观察程序执行过程,动态的去调整代码以提高效率。

一个简单的例子

	x.a = 25

在通常的动态类型语言中会翻译成一个字典查找,不过在V8的第一次执行中,它会找到x对应的hidden_class,然后找到a在x实例中的偏移。而在以后的执行中,它会将这段代码优化成以下形式:

if(x.hidden_class == "supposed hidden class"){
x[offset_a_in_hidden_class] = 25
}else{
//dictionary lookup "a"
...
}

与其每次都去做一个基于属性的字典查询,不如试着根据上次执行的结果,猜测下,如果还是相同的class,那就可以复用执行时已经得到的offset结果。虽然JavaScript是一个动态类型语言,但是大部分时候我们的代码并没有用到这么多动态特性,因此本来一个字典操作变成了一个直接的地址比较。从而达到了静态类型语言的执行速度。

正因为这个特点,写nodejs程序时有一些可以遵循的规则,用以加快执行效率,参见链接

Nodejs V8引擎 fast property lookup的更多相关文章

  1. nodejs v8引擎

    Node.js 线程你理解的可能是错的 本文代码运行环境 系统:MacOS High Sierra Node.js:10.3.0 复制代码 Node.js是单线程的,那么Node.js启动后线程数是1 ...

  2. nodejs v8引擎c++编译版本号升级教程

    原GCC版本号:4.4.7. 目标:升级GCC到4.8.2.以支持C++11. yum install gcc-c++ 获取GCC 4.8.2包:wget http://gcc.skazkaforyo ...

  3. 深入出不来nodejs源码-V8引擎初探

    原本打算是把node源码看得差不多了再去深入V8的,但是这两者基本上没办法分开讲. 与express是基于node的封装不同,node是基于V8的一个应用,源码内容已经渗透到V8层面,因此这章简述一下 ...

  4. V8引擎嵌入指南

    如果已读过V8编程入门那你已经熟悉了如句柄(handle).作用域(scope)和上下文(context)之类的关键概念,以及如何将V8引擎作为一个独立的虚拟机来使用.本文将进一步讨论这些概念,并介绍 ...

  5. 浅谈V8引擎中的垃圾回收机制

    最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...

  6. google v8引擎常见问题

    最近在项目中使用v8来进行扩展,下面简单说一下使用v8过程中遇到的一些问题.   v8的多线程调用 最初调研v8的测试代码是单线程的,后来一个项目在多线程中使用,出现了一些问题,后来看到参考3中的才恍 ...

  7. V8引擎——详解

    前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...

  8. Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略

    V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 一.前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存.垃圾 ...

  9. v8引擎详解

    引用网址: https://blog.csdn.net/swimming_in_it_/article/details/78869549 前言 JavaScript绝对是最火的编程语言之一,一直具有很 ...

随机推荐

  1. flask建立数据模型数据类型

    https://blog.csdn.net/happyanger6/article/details/53947162 https://blog.csdn.net/happyanger6/article ...

  2. linux下非root用户的sudo问题

    linux下的root用户是个超级管理员,一般是不用这个用户登录进行操作的,但有时候需要root权限,又不想切换用户的话可以使用sudo命令.但是不是所有的用户都可以使用sudo命令的. 首先可能会遇 ...

  3. Azkaban简介及使用

    一.Azkaban概述 Azkaban是一个分布式工作流管理器,在LinkedIn上实现,以解决Hadoop作业依赖性问题. 我们有需要按顺序运行的工作,从ETL工作到数据分析产品. 特点: 1)给用 ...

  4. add() 方法用于向 <select> 添加一个 <option> 元素。

    //add() 方法用于向 <select> 添加一个 <option> 元素. //new Option() 创建一个option标签 school.add(new Opti ...

  5. windows中根据进程PID查找进程对象过程深入分析

    这里windows和Linxu系列的PID 管理方式有所不同,windows中进程的PID和句柄没有本质区别,根据句柄索引对象和根据PID或者TID查找进程或者线程的步骤也是一样的.   句柄是针对进 ...

  6. 感知器python

    感知器学习的目标是求得一个能够将训练集正实例点和负实例点·完全正确分开的分离超平面.即找到这超平面的参数w,b. 超平面定义 w*x+b=0 其中w是参数,x是数据.公式很好理解以二维平面为例,w有两 ...

  7. dos常用命令【总结】

    win7下有很多有用的dos命令,现在总结如下: 延伸:Linux常用命令[总结] 命令 作用 其他 ping 检查和另一台主机的连通性  ping  127.0.0.1   telnet 检查连通性 ...

  8. Elasticsearch.js 发布 —— 在Node.js和浏览器中调用Elasticsearch

    继PHP.Ruby.Python和Perl之后,Elasticsearch最近发布了Elasticsearch.js,Elasticsearch的JavaScript客户端库.可以在Node.js和浏 ...

  9. 对BeforeSuite和BeforeTest的理解

    在BeforeSuite.BeforeTest.BeforeClass.BeforeMethod及BeforeGroups中,后面三个注解都比较好理解,其实BeforeSuite.BeforeTest ...

  10. Mysql binlog 安全删除(转载)

    简介: 如果你的 Mysql 搭建了主从同步 , 或者数据库开启了 log-bin 日志 , 那么随着时间的推移 , 你的数据库 data 目录下会产生大量的日志文件 shell > ll /u ...