最近在项目中使用v8来进行扩展,下面简单说一下使用v8过程中遇到的一些问题。
 
v8的多线程调用
最初调研v8的测试代码是单线程的,后来一个项目在多线程中使用,出现了一些问题,后来看到参考3中的才恍然大悟,又翻了v8.h中关于Isolate的注释。
  1. /**
  2. * Isolate represents an isolated instance of the V8 engine. V8
  3. * isolates have completely separate states. Objects from one isolate
  4. * must not be used in other isolates. When V8 is initialized a
  5. * default isolate is implicitly created and entered. The embedder
  6. * can create additional isolates and use them in parallel in multiple
  7. * threads. An isolate can be entered by at most one thread at any
  8. * given time. The Locker/Unlocker API can be used to synchronize.
  9. */
 
多线程调用的时候,如果需要每个线程运行一个单独的v8 vm的话,就需要在线程初始化的时候运行Isolate::New(),线程结束前调用Isolate::Dispose()。
 
v8如果不显示创建Isolate,会自动创建一个默认的Isolate。
 
关于Locker
因为每个v8 vm就会有自己的heap,如果每个线程都运行一个v8 vm的话,内存占用就很恐怖,可以多个线程使用同一个Isolate,多个线程在使用v8的时候就需要使用Locker进行同步。
Locker(Isolate *)在某个Isolate中进行加锁;默认Locker不加参数进行构造就会锁住默认的Isolate,实现全局的互斥。
Locker保证一个Isolate同时只能够被一个线程使用。具体可以参考test/cctest/test-locker.cc中的代码。
 
Locker的位置
Isolate的一些方法需要进行加锁:
void Enter();
void Exit();
void Dispose();
void SetData(void* data);
void* GetData();
 
尤其是与Enter()相关的位置Isolate::Scope()内会自行调用Isolate::Enter(),所以Isolate::Scope在和Locker一起使用的时候,要注意Locker要在Isolate::Scope前否则运行会出错。
 
 
 
v8的GC管理
v8的gc对用户是透明的,在其认为需要进行的时候才会进行gc,一般是其托管的内存满足一定阈值的时候才会触发gc。但有时候这些是不够的,例如一些嵌入到v8中的Object,本身需要很多的外部资源,这个时候v8并不知道这些外部资源的消耗,长久运行下去就会导致内存紧张,这个典型的例子就是网页中图片的处理和buffer对象的处理。因此需要暗示v8进行主动的GC【GC耗时可能会比较长,内存资源充裕情况下不建议频繁GC】。
 
1. 外部分配资源管理
v8会有一个整体内存占用的上限阈值,通过AdjustAmountOfExternalAllocatedMemory()调整注册的外部内存数量,反映当前引擎的内存分配情况,当达到阈值的时候,v8引擎会强制调用GC进行资源清理。【可以伪造一个较大的数值来迫使v8进行GC】
  1. /**
  2. * Adjusts the amount of registered external memory. Used to give
  3. * V8 an indication of the amount of externally allocated memory
  4. * that is kept alive by JavaScript objects. V8 uses this to decide
  5. * when to perform global garbage collections. Registering
  6. * externally allocated memory will trigger global garbage
  7. * collections more often than otherwise in an attempt to garbage
  8. * collect the JavaScript objects keeping the externally allocated
  9. * memory alive.
  10. *
  11. * \param change_in_bytes the change in externally allocated memory
  12. * that is kept alive by JavaScript objects.
  13. * \returns the adjusted value.
  14. */
  15. static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
 
2. 暗示v8调用GC
IdleNotification()当嵌入器空闲的时候进行资源清理;LowMemoryNotification()当内存过低时进行资源清理。
  1. /**
  2. * Optional notification that the embedder is idle.
  3. * V8 uses the notification to reduce memory footprint.
  4. * This call can be used repeatedly if the embedder remains idle.
  5. * Returns true if the embedder should stop calling IdleNotification
  6. * until real work has been done. This indicates that V8 has done
  7. * as much cleanup as it will be able to do.
  8. */
  9. static bool IdleNotification();
  10. /**
  11. * Optional notification that the system is running low on memory.
  12. * V8 uses these notifications to attempt to free memory.
  13. */
  14. static void LowMemoryNotification();
 
3. 启动时设置内存相关参数
SetFlagsFromCommandLine()和SetFlagsFromString(),这两个函数设置v8的几个flag:
    FLAG_max_new_space_size
    FLAG_max_old_space_size
    FLAG_max_executable_size
这几个FLAG影响v8的Heap::Setup。
 
SetFlagsFromCommandLine()/SetFlagsFromString()应该在任何v8的API调用前调用。
 
4. SetResourceConstraints设置参数
SetResourceContraints()可以在v8 vm初始化前调用设置Isolate相关Heap的大小,一旦vm初始化后,就无法再进行调整了。
  1. {
  2. ResourceConstraints rc;
  3. rc.set_max_young_space_size(2048); //KB
  4. rc.set_max_old_space_size(10); //MB
  5. rc.set_max_executable_size(10); //MB
  6. rc.set_stack_limit(reinterpret_cast<uint32_t*>((char*)&rc- 1024 * 400));
  7. SetResourceConstraints(&rc);
  8. }
 
 
具体Heap设置的这些参数如何影响Heap以及GC,暂时没有细细研究,后面有时间再分析。Heap初始化调用关系图:
  1. Context::New
  2. Bootstrapper::CreateEnvironment
  3. Genesis::Genesis
  4. V8::Initialize
  5. V8::Initialize
  6. V8::InitializeHelper
  7. V8::Initialize(Deserializer *des)
  8. Isolate::Init
  9. Heap::Setup
  10. Heap::ConfigureHeapDefault
  11. Heap::ConfigureHeap
  12. FLAG_max_new_space_size
  13. FLAG_max_old_space_size
  14. FLAG_max_executable_size
 
google v8的示例很少,可以不急于从网上找答案,先看一下v8.h以及test/cctest下面的代码,学习一下开发者是如何使用v8的,就可以解决大部分v8的使用问题。
常见的v8使用,可以直接参考v8cgi和nodejs,相比之下v8cgi的代码要更清晰些;-)
 

参考

google v8引擎常见问题的更多相关文章

  1. Google V8 引擎 原理详解

    V8 引擎概览 V8 引擎简介 Google V8 引擎使用 C++ 代码编写,实现了 ECMAScript 规范的第五版,可以运行在所有的主流 操作系统中,甚至可以运行在移动终端 ( 基于 ARM ...

  2. 用NAN简化Google V8 JS引擎的扩展

    通过C++扩展Google V8 JS引擎的文章很多,Google V8 JS带的例子也容易明白.但是大部分文章都是Hello World型的,真正使用时发现处处是坑.扩展V8最经典的例子就是node ...

  3. 在Android上使用Google V8 JS 引擎

    在cantk-runtime中直接使用的webview,通过JAVA扩展接口把Canvas的2d Context的API定向到JNI,通过OpenGL来图形加速,渲染速度大大提高.后来测试发现在大部分 ...

  4. Chrome V8引擎系列随笔 (1):Math.Random()函数概览

    先让大家来看一幅图,这幅图是V8引擎4.7版本和4.9版本Math.Random()函数的值的分布图,我可以这么理解 .从下图中,也许你会认为这是个二维码?其实这幅图告诉我们一个道理,第二张图的点的分 ...

  5. Google V8编程详解(序)Cloud App

    此系列文章转载于此http://blog.csdn.net/feiyinzilgd/article/details/8247723          应用程序发展到今天,应用程序的概念也在不断地发生着 ...

  6. V8引擎嵌入指南

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

  7. Javascript的V8引擎研究

    1.针对上下文的Snapshot技术 什么是上下文(Contexts)?实际是JS应用程序的运行环境,避免应用程序的修改相互影响,例如一个页面js修改内置对象方法toString,不应该影响到另外页面 ...

  8. JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍

    概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...

  9. V8引擎——详解

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

随机推荐

  1. 全新升级的WiFi无线上网短信认证系统,适用于咖啡厅、足浴等公共场所,提高门门店营业收入

    WiFi无线上网短信认证系统经历从1.0到1.88的升级,都是用户在使用过程中,提出宝贵的意见,一直修复至今,有着非常稳定的版本. 这个软件有什么作用?WiFi为什么要认证呢? 其实这个只是获取用户联 ...

  2. Ubuntu14.04下安装Libsvm,并使用Libsvm

    (1)Ubuntu14.04下安装Libsvm 转载:https://blog.csdn.net/katrinawj/article/details/78915874 一.下载: 网址:http:// ...

  3. Junit结合Spring对Dao层进行单元测试

    关于单元测试,上一次就简单的概念和Mock基础做了,参考:http://60.174.249.204:8888/in/modules/article/view.article.php/74 实际开发过 ...

  4. 【WP8】LoopingSelector

    WP8的WindowsPhoneToolkit工具包中有一个 LoopingSelector 可以想选择日期或时间一样进行选择 1.首先当然是引用WindowsPhoneToolkit 在Nuget控 ...

  5. VCL 中的 Windows API 函数(1): AbortDoc

    AbortDoc: 该函数终止当前打印作业并删除最好一次调用 StartDoc 函数写入的所有信息. 该函数在 Printers 单元的应用:AbortDoc(Canvas.Handle);

  6. .Net执行cmd命令

    using System;using System.Collections;using System.Configuration;using System.Data;using System.Linq ...

  7. Python中使用MongoEngine

    pymongo来操作MongoDB数据库,但是直接把对于数据库的操作代码都写在脚本中,这会让应用的代码耦合性太强,而且不利于代码的优化管理 一般应用都是使用MVC框架来设计的,为了更好地维持MVC结构 ...

  8. Thinkphp 模板中使用自定义函数的方法

    1.number_format {$number|number_format=2}   千分位,保留两位小数 2.round {$number|round=2}   四舍五入保留两位小数

  9. [原]反编译unity3d发布apk

    郑重声明:本教程仅用于学习使用,从事任何商业用途非法行为与作者无关,请知晓! 本文目的:通过教会大家如何破解别人游戏的同时,也希望各位开发者能加强自身游戏的防破解能力! 1:到gitHub下载DisU ...

  10. RHEL5 yum更新源

    1.检查yum是否安装 rpm -qa |grep yum 2.利用CentOS的yum更新源来实现RHEL5的YUM功能 vi /etc/yum.repos.d/CentOS-Base.repo [ ...