puerts icon indicating copy to clipboard operation
puerts copied to clipboard

[UE] V8_ENABLE_SANDBOX开启沙盒的兼容

Open yellow7ming opened this issue 5 months ago • 18 comments

打算开指针压缩,然后v8官方建议是指针压缩配合沙盒模式一起使用,因为单独打开指针压缩,10.x版本可能有oom的内存问题。所以重新编译了v8版本,build也加入两个宏

V8_COMPRESS_POINTERS V8_ENABLE_SANDBOX

但真机会崩溃 2025-07-11 16:38:17.529 6246-6356 vulkan com.sy.S3 D searching for layers in '/data/app/~~eFmiIKh8TnM5mHG5Dszm0A==/com.sy.S3-IUdh6d8zUhzeXokWGFAXVw==/base.apk!/lib/arm64-v8a' 2025-07-11 16:38:18.673 6246-6356 UE com.sy.S3 D [2025.07.11-16.38.18:673][ 0]LogTemp: JSEnv::Javascript() V8::Initialize() PointerCompression: 1, Sandbox: 1 2025-07-11 16:38:22.166 6246-6356 UE com.sy.S3 D [2025.07.11-16.38.22:166][ 85]LogTemp: JSEnv::Javascript() V8 flags: 2025-07-11 16:38:22.263 6246-6356 v8 com.sy.S3 E # # Fatal error in v8_ArrayBuffer_NewBackingStore # When the V8 Sandbox is enabled, ArrayBuffer backing stores must be allocated inside the sandbox address space. Please use an appropriate ArrayBuffer::Allocator to allocate these buffers, or disable the sandbox. # 2025-07-11 16:38:23.456 6561-6561 DEBUG crash_dump64 A #03 pc 00000000124f9124 /data/app/~~eFmiIKh8TnM5mHG5Dszm0A==/com.sy.S3-IUdh6d8zUhzeXokWGFAXVw==/lib/arm64/libUnreal.so (puerts::FJsEnvImpl::BindStruct(puerts::FScriptStructWrapper*, void*, v8::Localv8::Object, bool)+872) (BuildId: 274f1cd5eafc264a57ac5b7c5f8a2f27bd25b3a9) 2025-07-11 16:38:23.456 6561-6561 DEBUG crash_dump64 A #04 pc 000000001251ad48 /data/app/~~eFmiIKh8TnM5mHG5Dszm0A==/com.sy.S3-IUdh6d8zUhzeXokWGFAXVw==/lib/arm64/libUnreal.so (puerts::FScriptStructWrapper::New(v8::Isolate*, v8::Localv8::Context&, v8::FunctionCallbackInfov8::Value const&)+536) (BuildId: 274f1cd5eafc264a57ac5b7c5f8a2f27bd25b3a9) 2025-07-11 16:38:23.456 6561-6561 DEBUG crash_dump64 A #05 pc 00000000124fab00 /data/app/~~eFmiIKh8TnM5mHG5Dszm0A==/com.sy.S3-IUdh6d8zUhzeXokWGFAXVw==/lib/arm64/libUnreal.so (puerts::FScriptStructWrapper::New(v8::FunctionCallbackInfov8::Value const&)+108) (BuildId: 274f1cd5eafc264a57ac5b7c5f8a2f27bd25b3a9)

尝试改 FJsEnvImpl::BindStruct 中传递外部指针的处理,想改为Memcpy的方式。但影响颇大,原始指针还要考虑数据同步和释放,请问怎么改比较好呢?还是说因为虚幻对象的强引用绑定机制还有反射调用等,也不考虑开沙盒

yellow7ming avatar Jul 16 '25 03:07 yellow7ming

ps一下,10.6.194和ue的内存分配有些冲突,在mac editor会崩溃,在unity下ios也会崩溃。最新版本已经移除了10.6.194的支持。 建议用9.4或者11.8

chexiongsheng avatar Jul 16 '25 04:07 chexiongsheng

至少我知道两个项目在用11.8的V8_COMPRESS_POINTERS,没问题

chexiongsheng avatar Jul 16 '25 04:07 chexiongsheng

至少我知道两个项目在用11.8的V8_COMPRESS_POINTERS,没问题

感谢大佬回复。我说漏了一些,我们也是拿11.8重新编译的。主要是沙盒 V8_ENABLE_SANDBOX 带来的问题。报这个: Fatal error in v8_ArrayBuffer_NewBackingStore When the V8 Sandbox is enabled, ArrayBuffer backing stores must be allocated inside the sandbox address space. Please use an appropriate ArrayBuffer::Allocator to allocate these buffers, or disable the sandbox.

那两个用11.8的,是只开了指针压缩,并没有开沙盒模式是吗?

yellow7ming avatar Jul 16 '25 05:07 yellow7ming

至少我知道两个项目在用11.8的V8_COMPRESS_POINTERS,没问题

感谢大佬回复。我说漏了一些,我们也是拿11.8重新编译的。主要是沙盒 V8_ENABLE_SANDBOX 带来的问题。报这个: Fatal error in v8_ArrayBuffer_NewBackingStore When the V8 Sandbox is enabled, ArrayBuffer backing stores must be allocated inside the sandbox address space. Please use an appropriate ArrayBuffer::Allocator to allocate these buffers, or disable the sandbox.

那两个用11.8的,是只开了指针压缩,并没有开沙盒模式是吗?

应该没开。

chexiongsheng avatar Jul 16 '25 05:07 chexiongsheng

好的。我们发现指针压缩要用到外部实体表,如果不开沙盒,这个实体表就不会回收。如果js对象比较多且频繁创建,随着时间推移越来越大(比如挂机10小时),V8会自己判定自己OOM。所以才开沙盒配套解决这个问题

如果必须得开,FJsEnvImpl::BindStruct 中直接传递裸指针的处理有比较好的建议吗?

yellow7ming avatar Jul 16 '25 06:07 yellow7ming

BindStruct用ArrayBuffer只是个优化,那一段可以去掉。 不过还有FArrayBuffer,这个你也可以去掉,只用值拷贝版本FArrayBufferValue

chexiongsheng avatar Jul 17 '25 01:07 chexiongsheng

感谢大佬,我们试试~

yellow7ming avatar Jul 21 '25 06:07 yellow7ming

好的。我们发现指针压缩要用到外部实体表,如果不开沙盒,这个实体表就不会回收。如果js对象比较多且频繁创建,随着时间推移越来越大(比如挂机10小时),V8会自己判定自己OOM。所以才开沙盒配套解决这个问题

如果必须得开,FJsEnvImpl::BindStruct 中直接传递裸指针的处理有比较好的建议吗?

我们项目是用的11.8,没有开沙盒模式。即 v8_enable_pointer_compression=true v8_enable_sandbox=false

"指针压缩要用到外部实体表,如果不开沙盒,这个实体表就不会回收",请问这里的实体表,指的是什么呢,具体代码在哪里?

zhaojunmeng avatar Aug 06 '25 08:08 zhaojunmeng

我们11.8版本也遇到v8_enable_pointer_compression=true v8_enable_sandbox=false下,挂机指针压缩表的内存会泄露,10小时1个GB的水平(iOS 6GB)。查了代码就是 ExternalPointerTable里的SweepAndCompact调用必现打开 V8_ENABLE_SANDBOX宏。 关闭 v8_enable_pointer_compression V8内存泄露问题解决,但基础内存增加不少。 我们尝试打开这两个宏,构建的版本会到了登录页面自动Crash(4/4),没有Crash堆栈上报,日志也没有体现,内存才600MB占用,看Perfdog像是 上下文切换过多导致。

BillZhang2023 avatar Aug 14 '25 06:08 BillZhang2023

好的。我们发现指针压缩要用到外部实体表,如果不开沙盒,这个实体表就不会回收。如果js对象比较多且频繁创建,随着时间推移越来越大(比如挂机10小时),V8会自己判定自己OOM。所以才开沙盒配套解决这个问题 如果必须得开,FJsEnvImpl::BindStruct 中直接传递裸指针的处理有比较好的建议吗?

我们项目是用的11.8,没有开沙盒模式。即 v8_enable_pointer_compression=true v8_enable_sandbox=false

"指针压缩要用到外部实体表,如果不开沙盒,这个实体表就不会回收",请问这里的实体表,指的是什么呢,具体代码在哪里?

是ExternalPointerTable超出最大限制了,v8自己抛OOM错误,用logcat才能看到。具体代码就是你楼下说的那部分SweepAndCompact。

yellow7ming avatar Aug 14 '25 10:08 yellow7ming

我们11.8版本也遇到v8_enable_pointer_compression=true v8_enable_sandbox=false下,挂机指针压缩表的内存会泄露,10小时1个GB的水平(iOS 6GB)。查了代码就是 ExternalPointerTable里的SweepAndCompact调用必现打开 V8_ENABLE_SANDBOX宏。 关闭 v8_enable_pointer_compression V8内存泄露问题解决,但基础内存增加不少。 我们尝试打开这两个宏,构建的版本会到了登录页面自动Crash(4/4),没有Crash堆栈上报,日志也没有体现,内存才600MB占用,看Perfdog像是 上下文切换过多导致。

两个都打开的时候我们也崩溃,你用logcat看就能看到有报错堆栈,就是我帖子里贴出来那些。开沙盒后,内存分配相关代码需要调整

yellow7ming avatar Aug 14 '25 10:08 yellow7ming

你那里的提示,说明打开沙盒宏的时候,需要在v8构建参数里指定 array_buffer_allocator 为ArrayBuffer::Allocator v8::Isolate::CreateParams CreateParams; static v8::ArrayBuffer::Allocator* DefaultAllocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); CreateParams.array_buffer_allocator = DefaultAllocator;

再看了一下V8的源码,发现不打开沙盒宏的时候,ArrayBuffer::Allocator::NewDefaultAllocator的分配是系统分配,所以打开指针压缩宏(不打开沙盒宏),这个指定分配器代码也没有效果

BillZhang2023 avatar Aug 15 '25 03:08 BillZhang2023

你那里的提示,说明打开沙盒宏的时候,需要在v8构建参数里指定 array_buffer_allocator 为ArrayBuffer::Allocator v8::Isolate::CreateParams CreateParams; static v8::ArrayBuffer::Allocator* DefaultAllocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); CreateParams.array_buffer_allocator = DefaultAllocator;

再看了一下V8的源码,发现不打开沙盒宏的时候,ArrayBuffer::Allocator::NewDefaultAllocator的分配是系统分配,所以打开指针压缩宏(不打开沙盒宏),这个指定分配器代码也没有效果

是的,按源码来看,指针压缩还是得配套沙盒宏一起开。后续你们方案是如何

yellow7ming avatar Aug 15 '25 11:08 yellow7ming

你那里的提示,说明打开沙盒宏的时候,需要在v8构建参数里指定 array_buffer_allocator 为ArrayBuffer::Allocator v8::Isolate::CreateParams CreateParams; static v8::ArrayBuffer::Allocator* DefaultAllocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); CreateParams.array_buffer_allocator = DefaultAllocator; 再看了一下V8的源码,发现不打开沙盒宏的时候,ArrayBuffer::Allocator::NewDefaultAllocator的分配是系统分配,所以打开指针压缩宏(不打开沙盒宏),这个指定分配器代码也没有效果

是的,按源码来看,指针压缩还是得配套沙盒宏一起开。后续你们方案是如何

打开沙盒就必须不能使用外部分配的指针,我们项目里有部分外部指针,现在是去除了BindStruct里的ArrayBuffer优化,目的是尽量减少外部指针的量,保留打开指针压缩宏,关闭沙盒宏的配置,如果后续测试验证泄露速率足够低的话,就这样,如果不行就放弃指针压缩。

在指针压缩宏打开情况下,TS代码里创建ArrayBuffer,同样会导致上述的外部指针表泄露。 结论就是想完全不泄露,这两个宏要同时打开/关闭。 只打开指针压缩宏,就必须控制每帧ArrayBuffer New的数量足够低

BillZhang2023 avatar Aug 18 '25 02:08 BillZhang2023

我们测试了一下 开启指针压缩后,如果不打开sandbox,对于全部的ArrayBuffer都会泄露,不仅仅是cpp里面的bindstruct,还包括脚本的pb里面创建的arraybuffer之类的。泄露堆栈是ExternalPointerTable里面的entry,因为该table相关的gc调用,被sandbox相关的宏所包含了。 打开sandbox后,泄露解除,但是需要额外的50-100M的空间进行gc,所以指针压缩的内存优势几乎被抹平了。同时sandbox对性能影响其实蛮大的,我们观测到了显著的性能降低

Tangxinwei avatar Sep 02 '25 02:09 Tangxinwei

楼内的各位大佬,请问一下11.8 vs 9.4的实际性能收益大概是多少, Jit / Jitless的情况。 我这边跑了些benchmark 评测下来Jitless感觉有一定收益(10%左右),Jit下并不明显。本来想尝试下maglev 发现这个问题,https://github.com/puerts/backend-v8/issues/17 , maglev也被禁用了。

BlurryLight avatar Sep 16 '25 10:09 BlurryLight

楼内的各位大佬,请问一下11.8 vs 9.4的实际性能收益大概是多少, Jit / Jitless的情况。 我这边跑了些benchmark 评测下来Jitless感觉有一定收益(10%左右),Jit下并不明显。本来想尝试下maglev 发现这个问题,puerts/backend-v8#17 , maglev也被禁用了。

要不你探索下更新版本的使用?据google的人反馈,本楼反馈的内存泄露问题在12.6+换了方案,应该没所描述的问题了。

chexiongsheng avatar Sep 18 '25 12:09 chexiongsheng

楼内的各位大佬,请问一下11.8 vs 9.4的实际性能收益大概是多少, Jit / Jitless的情况。 我这边跑了些benchmark 评测下来Jitless感觉有一定收益(10%左右),Jit下并不明显。本来想尝试下maglev 发现这个问题,puerts/backend-v8#17 , maglev也被禁用了。

要不你探索下更新版本的使用?据google的人反馈,本楼反馈的内存泄露问题在12.6+换了方案,应该没所描述的问题了。

大佬,关于开指针关sandbox会泄露这个问题,有没有相关链接可以参考的

haroel avatar Oct 24 '25 07:10 haroel