在64位平台上,LuaJIT只允许最多1-2GB的数据(不包括用malloc
分配的对象)。这种限制来自哪里,为什么这比32位平台还要少?
答案 0 :(得分:12)
LuaJIT旨在使用32位指针。在MAP_32BIT
平台上,限制来自使用mmap和MAP_32BIT
标记。
MAP_32BIT(自Linux 2.4.20,2.6起):
将映射放入进程地址空间的前2 GB。对于64位程序,仅在x86-64上支持此标志。添加它是为了允许在前2GB内存中的某个位置分配线程堆栈,以便提高某些早期64位处理器的上下文切换性能。
基本上使用此标志限制为前31位,而不是名称所暗示的前32位。查看here,了解Linux内核中使用malloc
的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状态内的对象,可以通过使用x86
来克服,x64
将在较低的32位地址空间之外进行分配。此外,可以在32位模式下使用{{1}} {{1}}版本,并可以访问完整的4GB。
查看这些链接以获取更多信息:
答案 1 :(得分:0)
由于最近patch luajit的2GB内存限制可以解决。
要进行测试,请克隆this repo并使用定义的msvcbuild.bat gc64
符号进行构建:
XCFLAGS+= -DLUAJIT_ENABLE_GC64
或Makefile
中的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)
我使用以下代码测试内存分配:
not enough memory
在我的计算机上TypeVar
错误发生之前分配了48GB。