内存分配
对于 McoSqlEngine 类,所有内存分配均使用 StdAllocator 类。需要替换基于内置 malloc()/free()
的分配器的应用程序可以显式创建一个分配器。这样的自定义分配器必须通过将自定义的 alloc()/free()
函数传递给其构造函数来实例化 StdAllocator 类的对象(或者,也可以子类化 SystemAllocator 类)。这必须在默认 StdAllocator 的静态构造完成之后进行。
请注意,6.5 版本之前的 SmartESQL 需要实例化一个 DynamicAllocator 对象来替换自定义内存分配器。6.5 版本及更高版本中不再包含此类。
因此,使用 SmartESQL 早期版本构建的应用程序需要进行修改。例如,不再需要
DynamicAllocator allocator(mem_alloc, mem_free, ALLOC_QUANTUM, ALLOC_RETAIN);
engine.setAllocator(&allocator);
自定义分配器在 main() 函数中只需按如下方式实例化:
int main(int argc, char** argv)
{
...
StdAllocator allocator( mem_alloc, mem_free );
…
}
在执行查询期间,可以限制 SQL 引擎使用的内存量,防止引擎从运行查询的机器上占用所有可用内存。
所有 SQL 分配器用于分配内存块的抽象类 SystemAllocator 定义如下:
class SystemAllocator
{
public:
virtual void* allocate(size_t size) = 0;
virtual void free(void* ptr) = 0;
virtual size_t allocated()
{
return 0;
}
SystemAllocator()
{
implementation = this;
}
static SystemAllocator* implementation;
};
抽象类 StdAllocator 的默认实现允许指定 alloc()
和 free()
接口,否则将使用标准 C 运行时的 malloc()
/ free()
API。新的 QuotaSysAllocator 类通过跟踪已分配的空间来扩展 StdAllocator。该类可通过以下构造函数使用,以限制已分配的内存量:
QuotaSysAllocator(size_t quota, malloc_t malloc, free_t free) :
StdAllocator(malloc,free), limit(quota), total(0){}
这里的quota
是以字节为单位的大小,用于限制已分配内存的数量。如果达到限制,分配器的 malloc()
函数将返回空值。第二个参数是从系统获取内存的函数,第三个参数是释放内存块的函数。如下:
typedef void* (*malloc_t)(size_t size);
typedef void (*free_t)(void* ptr);
为了重新定义系统分配器,应用程序创建了一个 QuotaSysAllocator 的实例。例如:
main()
{
new QuotaSysAllocator(10*1024*1024, malloc, free);
....
}
请注意,应用程序只能使用系统分配器的一个实例。当查询超出内存限制时,会发生以下情况:
QuotaSysAllocator::allocate()
返回NULL
;- 引擎的分配器检测到
NULL
并抛出 NotEnoughMemory 异常; - 该异常中断当前的 SQL 语句,并回滚当前事务(释放事务分配的所有内存)。
除了限制查询使用的内存量之外,QuotaSysAllocator 还可以被应用程序通过 get_total_heap_size()
SQL 函数请求已使用的内存统计信息。
请注意,当在 xSQL 配置文件中设置 sql_workspace_limit
参数时(默认情况下,该限制设置为 0,表示没有限制),会隐式使用 QuotaSysAllocator。
QuotaSysAllocator 功能目前尚未作为 Java、C# 或 Python API 的一部分提供。