postgresql之对象池(slab)

创建SlabContext

 分配对象

创建对象池

  • 分配空间
  • 初始化分配的空间
  • 将block加入循环双向链表

 

 从对象池中获取对象

从双向循环链表中获取一个block

/* grab the block from the freelist (even the new block is there) */
block = dlist_head_element(SlabBlock, node,
						&slab->freelist[slab->minFreeChunks]);

从block中获取空闲chunk的索引

/* we know index of the first free chunk in the block */
idx = block->firstFreeChunk;

获取chunk

/* compute the chunk location block start (after the block header) */
	chunk = SlabBlockGetChunk(slab, block, idx);

减少空用chunk个数

/*
	 * Update the block nfree count, and also the minFreeChunks as we've
	 * decreased nfree for a block with the minimum number of free chunks
	 * (because that's how we chose the block).
	 */
	block->nfree--;
	slab->minFreeChunks = block->nfree;

更新下一个空闲chunk索引

block->firstFreeChunk = *(int32 *) SlabChunkGetPointer(chunk);

将block重新更新到下一个循环双向链表中

/* move the whole block to the right place in the freelist */
	dlist_delete(&block->node);
	dlist_push_head(&slab->freelist[block->nfree], &block->node);

 当block中的chunk分配完后,整个block就移动到了freelist[0]的位置,freelist[0]下的循环双向链表的节点都是分配完的block

 

释放对象

根据释放对象,获取到对应的block以及chunk

SlabChunk  *chunk = SlabPointerGetChunk(pointer);
SlabBlock  *block = chunk->block;

计算当前chunk相对于block的索引

/* compute index of the chunk with respect to block start */
idx = SlabChunkIndex(slab, block, chunk);

 更新空闲chunk索引以及空闲chunk个数

/* add chunk to freelist, and update block nfree count */
*(int32 *) pointer = block->firstFreeChunk;
block->firstFreeChunk = idx;
block->nfree++;

 将当前block从现有循环双向链表中删除

/* remove the block from a freelist */
dlist_delete(&block->node);

如果释放的chunk所属的block是正用于申请空间的freelist,并且freelist也空了,则更新minFreeChunks

	/*
	 * See if we need to update the minFreeChunks field for the slab - we only
	 * need to do that if there the block had that number of free chunks
	 * before we freed one. In that case, we check if there still are blocks
	 * in the original freelist and we either keep the current value (if there
	 * still are blocks) or increment it by one (the new block is still the
	 * one with minimum free chunks).
	 *
	 * The one exception is when the block will get completely free - in that
	 * case we will free it, se we can't use it for minFreeChunks. It however
	 * means there are no more blocks with free chunks.
	 */
	if (slab->minFreeChunks == (block->nfree - 1))
	{
		/* Have we removed the last chunk from the freelist? */
		if (dlist_is_empty(&slab->freelist[slab->minFreeChunks]))
		{
			/* but if we made the block entirely free, we'll free it */
			if (block->nfree == slab->chunksPerBlock)
				slab->minFreeChunks = 0;
			else
				slab->minFreeChunks++;
		}
	}

释放block或这加入另外一个循环双向链表中

/* If the block is now completely empty, free it. */
	if (block->nfree == slab->chunksPerBlock)
	{
		free(block);
		slab->nblocks--;
		context->mem_allocated -= slab->blockSize;
	}
	else
		dlist_push_head(&slab->freelist[block->nfree], &block->node);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值