Как мне успешно использовать Loki's Small Object Allocator в Lua? - PullRequest
2 голосов
/ 09 июля 2009

Я читал где-то здесь, где кто-то рекомендовал использовать Loki Small Object Allocator для 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" );

Если у меня есть простой цикл for в Global.lua, система никогда не вернется из вызова на luaL_loaloadfile():

for i=1,100 do
 local test = { }
end

Что не так, как мне это диагностировать и как это исправить?

Ответы [ 2 ]

4 голосов
/ 09 июля 2009

Проблема, которая бросается в глаза, заключается в том, что ваш пользовательский распределитель должен вести себя как функция C realloc(). Это критично в случае, когда osize != nsize и оба отличны от нуля. Ключевое свойство realloc() в этом случае заключается в том, что оно сохраняет значения первых min(osize,nsize) байтов старого блока как начало нового блока.

У вас есть:

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

, который отказывается от всего содержимого старого выделения.

Это указано

Функция распределителя должна обеспечивать функциональность похожа на realloc, но не совсем то же самое.

в документации по lua_Alloc .

0 голосов
/ 09 июля 2009

Хороший звонок! Я действительно не понимал, что сделал 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 () ...

...