为什么LuaJIT在64位平台上的内存被限制在1-2 GB?

在 64 位平台上,LuaJIT 只允许最多 1-2GB 的数据(不包括使用 malloc 分配的对象)。这个限制是从哪里来的,为什么甚至比 32 位平台还要少?

点赞
用户415823
用户415823

LuaJIT被设计为使用32位指针。在x64平台上,限制来自于使用mmapMAP_32BIT标志。

MAP_32BIT(自Linux 2.4.20、2.6以来):

将映射放置在进程地址空间的前2GB。该标志仅支持64位程序的x86-64,在某些早期的64位处理器上它被添加以允许在内存的前2GB中分配线程栈,从而提高上下文切换性能。

实际上,使用此标志限制为前31位,而不是名称所示的前32位。在这里查看使用Linux内核中的MAP_32BIT的1GB限制的概述。

即使你可以拥有超过1GB,LuaJIT的作者也解释了为什么这对性能不利:

  • 一个完整的GC需要比分配本身多50%的时间。
  • 如果启用GC,它会将分配时间加倍。
  • 为了模拟真实应用程序,第三次运行中对象之间的链接被随机化。这会将GC时间加倍!

这仅仅是针对1GB的情况!现在想象使用8GB——一个完整的GC周期将使CPU忙碌了长达24秒! 好吧,正常模式是使用增量GC。但这只意味着开销要高出约30%,它混杂在分配之间,并且每次都会使CPU缓存被清空。基本上,您的应用程序将被GC开销所支配,并且您将开始想知道它为什么慢......

要点:不要在家中尝试这个。GC需要一次重写(推迟到LuaJIT 2.1)。

总之,1GB限制是Linux内核和LuaJIT垃圾回收的限制。这仅适用于LuaJIT状态内的对象,可以通过使用malloc来克服,该函数将在低32位地址空间之外分配内存。此外,可以在32位模式下使用x86构建在x64上,并且可以访问完整的4GB。

点击以下链接获取更多信息:

2016-02-02 15:42:47
用户70405
用户70405

由于最近的补丁,luajit的2GB内存限制可以得到解决。

要测试,请克隆this repo,并使用LUAJIT_ENABLE_GC64符号定义进行构建:

msvcbuild.bat gc64

或者在Makefile中使用XCFLAGS+=-DLUAJIT_ENABLE_GC64

我使用了这段代码来测试内存分配:

local ffi = require("ffi")

local CHUNK_SIZE     = 1 * 1024 * 1024 * 1024
local fraction_of_gb = CHUNK_SIZE / (1024*1024*1024)
local allocations    = {}

for index=1, 64 do
    local huge_memory_chunk = ffi.new("char[?]", CHUNK_SIZE)
    table.insert(allocations, huge_memory_chunk)
    print( string.format("allocated %q GB", index*fraction_of_gb) )
    local pause = io.read(1)
end

print("测试完成")
local pause = io.read(1)

在我的机器上,在出现not enough memory错误之前已分配了48GB。

进入图像描述这里

2019-05-23 22:48:16