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

Max*_*axB 6 lua luajit

在64位平台上,LuaJIT仅允许最多1-2GB的数据(不包括分配的对象malloc).这种限制来自何处,为什么这比32位平台还要少?

Ada*_*dam 11

LuaJIT旨在使用32位指针.在x64平台上,限制来自使用mmapMAP_32BIT标志.

MAP_32BIT(自Linux 2.4.20,2.6):

将映射放入进程地址空间的前2 GB.对于64位程序,仅在x86-64上支持此标志.添加它是为了允许在前2GB内存中的某处分配线程堆栈,以便改善某些早期64位处理器的上下文切换性能.

基本上使用此标志限制为前31位,而不是名称建议的前32位.看看这里有一个很好的概述MAP_32BITLinux内核中使用的1GB限制.

即使你的内容超过1GB,LuaJIT作者也解释了为什么这对性能有害:

  • 完整的GC比分配本身多花费50%的时间.
  • 如果GC已启用,则会使分配时间加倍.
  • 为了模拟真实的应用程序,对象之间的链接在第三次运行中随机化.这使GC时间加倍!

这只是1GB!现在想象一下使用8GB - 一个完整的GC循环会让CPU忙碌24秒!好的,所以正常模式是使用增量GC.但这只意味着开销高出约30%,它在分配之间混合,每次都会驱逐CPU缓存.基本上你的应用程序将由GC开销占主导地位,你会开始怀疑为什么它很慢....

tl;博士版:不要在家里试试.GC需要重写(推迟到LuaJIT 2.1).

总而言之,1GB限制是Linux内核和LuaJIT垃圾收集器的限制.这仅适用于LuaJIT状态内的对象,可以通过使用来解决malloc,它将在较低的32位地址空间之外进行分配.此外,它可以在32位模式下使用x86构建,x64并可以访问完整的4GB.

查看这些链接以获取更多信息:


Ale*_*lex 6

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

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

msvcbuild.bat gc64
Run Code Online (Sandbox Code Playgroud)

XCFLAGS+= -DLUAJIT_ENABLE_GC64Makefile

我使用此代码来测试内存分配:

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("Test complete")
local pause = io.read(1)
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明