如何在 Lua 中成功使用 Loki 的小对象分配器?

Posted

技术标签:

【中文标题】如何在 Lua 中成功使用 Loki 的小对象分配器?【英文标题】:How do I use Loki's Small Object Allocator in Lua successfully? 【发布时间】:2010-11-09 05:11:07 【问题描述】:

我在这里的某个地方读到有人推荐使用 Loki 的 Lua 小对象分配器来帮助提高分配性能。我通读了“现代 C++ 设计”中的部分,我认为我对使用 Loki 已经有了足够的了解,除了不使用 SmallObject - Lua 只想要原始内存,所以我拿了第一个尝试直接使用SmallObjAllocator

分配似乎正在工作,但是一旦我尝试加载脚本(使用 lua_load() 和我自己的自定义阅读器,或者使用 luaL_loadfile() 直接读取文件),一切都会完全失败。

这是我对 SmallObjAllocator 类的实现:

class MySmallAllocator : public Loki::SmallObjAllocator

  public:
    MySmallAllocator( std::size_t pageSize, 
                      std::size_t maxObjectSize, 
                      std::size_t objectAlignSize ) : Loki::SmallObjAllocator( pageSize, maxObjectSize, objectAlignSize ) 
     
    
    virtual ~MySmallAllocator() 
     
    
;
static MySmallAllocator alloc_(4096,64,4);

当我创建 Lua 状态时,我给它一个使用这个新分配器的分配函数:

masterState_ = lua_newstate(customAlloc_, &heap_);

void* customAlloc_( void* ud, void* ptr, size_t osize, size_t nsize )

  // If the new size is zero, we're destroying a block
  if (nsize == 0)
  
    alloc_.Deallocate( ptr );
    ptr = NULL;
  
  // If the original size is zero, then we're creating one
  else if (0 != nsize && 0 == osize)
  
    ptr = alloc_.Allocate( nsize, false );
  
  else
 
   alloc_.Deallocate( ptr );
   ptr = alloc_.Allocate( nsize, false );
 

 return ptr;

然后我去加载文件:

int result = luaL_loadfile(masterState_, "Global.lua" );

如果我在 Global.lua 中有一个简单的 for 循环,系统将永远不会从对 luaL_loaloadfile() 的调用中返回:

对于 i=1,100 做 本地测试 = 结尾

出了什么问题,我应该如何诊断,以及如何解决?

【问题讨论】:

我不明白投票结束“不是一个真正的问题”。甚至在我编辑它添加一个问号之前,它显然仍然是一个真正的问题,正在寻求关于 Lua API 一个令人费解的角落的帮助。 谢谢!一开始我应该把我的问题写得更好。 【参考方案1】:

我突然想到的问题是您的自定义分配器需要表现得像 C 的 realloc() 函数。这在osize != nsize 且两者均非零的情况下至关重要。在这种情况下,realloc() 的关键属性是它保留了旧块的第一个 min(osize,nsize) 字节的值作为新块的开头。

你有:

    else
    
            alloc_.Deallocate( ptr );
            ptr = alloc_.Allocate( nsize, false );
    

放弃旧分配的所有内容。

这是指定的

分配器函数必须提供一个 功能类似于 realloc,但 不完全一样。

在lua_Alloc 的文档中。

【讨论】:

【参考方案2】:

好电话!我真的不明白 realloc() 做了什么,所以你让我走上了正确的轨道。我将重新分配部分替换为下面的代码,现在一切正常,但我现在的性能实际上比我之前使用的 HeapAlloc/HeapReAlloc/HeapFree 差一些。

    void* replacementPtr = alloc_.Allocate( nsize, true );
    memcpy( replacementPtr, ptr, min(osize, nsize) );
    alloc_.Deallocate( ptr );
    ptr = replacementPtr;

我怀疑一个问题是因为 Loki 对每个块使用 malloc/free 以及大小为 > GetMaxObjectSize()...

【讨论】:

以上是关于如何在 Lua 中成功使用 Loki 的小对象分配器?的主要内容,如果未能解决你的问题,请参考以下文章

在“现代 C++ 设计”/Loki 中发现的小对象分配器是不是已被弃用以支持更新的实现?

如何使用 lua 检查 Roblox 中是不是存在对象?

Lua 垃圾回收

python为不同的对象如何分配内存的小知识

Lua垃圾收集

Lua Profiler——快速定位Lua性能问题