Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5689496
  • 博文数量: 675
  • 博客积分: 20301
  • 博客等级: 上将
  • 技术积分: 7671
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-31 16:15
文章分类

全部博文(675)

文章存档

2012年(1)

2011年(20)

2010年(14)

2009年(63)

2008年(118)

2007年(141)

2006年(318)

分类: C/C++

2011-09-05 11:28:40

最近在项目中使用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的代码要更清晰些;-)

参考
1. 
阅读(17548) | 评论(0) | 转发(0) |
0

上一篇:linux xbind后门库

下一篇:google v8使用示例

给主人留下些什么吧!~~