前几篇文章对内存池做了两次改进和简化,因为在liunux上内存分配的malloc已经在系统的优化控制范围内了,所以一定范围内的内存分配还是交由系 统比较快,经测试基本上对于大于256字节的内存分配交由本内存池分配性能有明显提高,本次系统所有其他的对象都是构建在这个内存池之上,内存池会对用户 申请的内存作出二次归类管理
代码如下:
memeory.h
/*
* File: memorys.h:内存池管理系统
* Author: netpet
* Flower net server
*重要:实际的控制范围是最小值MinIndex*Align,最大值是(InitMemPool+MinIndex-2)*Align
* 本程序是为一体化web server产品专用设计,具有部分代码为具体产品优化而不代表普遍通用性的特性
* 程序在linux 2.46下调试通过,编辑工具netbeans 6.1 for c
*该结构用一个自增长的链表结构体保存分链表,每个结构体中包含具体链表的头部、尾部和空闲分界线指针,维护一个链表
*大致结构如下:
* MemPool
* V V V ...
* 链表1 链表2 链表3 ...
*通过这样一个结构系统就可以灵活增加减少系统池,并且可以控制池内结构,控制总数据量
* 联系方式:Email:
[email protected] QQ:51977431
* Created on 2008年5月26日, 下午4:18
*/
#ifndef _MEMORYS_H
#define _MEMORYS_H
#ifdef __cplusplus
extern "C" {
#endif
#define InitMemPool 1000 //初始化池所能拥有的数量,不能超过255*255
#define new(type) ((type *)(New(sizeof(type))))
#define sizes sizeof(MemPool)
extern long MaxMemory;
extern int Align;
extern int InitMemItem;
extern int ExpendMemItem;
extern int MinBlock;
extern long MaxBlock;
extern int MinIndex;
typedef struct _MemItem {
struct _MemItem *next;
} MemItem;
/*
*该结构体是linux 2.4.6状态下malloc申请内存时强加的协议头结构,用来记录实际内存大小
*/
struct mem_block {
int is_available; //这是一个标记
int size; //这是实际空间的大小
};
/*池集合*/
typedef struct _MemPool {
int name; //名称,同item_size,不管什么类型,申请的同一大小内存快放在同一个内存管理区域,视为同一名称,
long max_memory; //最多占用的内存
int init_item; //初始化多少item
int per_expend_item; //每次扩展时一次申请多少项
int current_item; //当前有多少项被使用
int total_item; //共有多少项
MemItem * first; //IO池头地址
MemItem * last; //IO池最后一项的地址
MemItem * current; //IO池分割空闲和使用中的分割地址
} MemPool;
/**
*取会给定结构的池结构体
*/
extern void InitPool(void); /*初始化池*/
extern void FreePool(); /*释放池*/
extern void InitItem(unsigned int name); //初始化具体项的链表
extern void *New(unsigned int size); //初始化具体项的链表
extern void ExpendItem(unsigned int name); //初始化扩展项的链表
extern void Free(void *myp); //释放具体一项
extern void PrintPool(void);
#ifdef __cplusplus
}
#endif
#endif /* _MEMORYS_H */
memorys.c
/*
* File: memorys.c:内存池管理系统
* Author: netpet
* Flower net server
*重要:实际的控制范围是最小值MinIndex*Align,最大值是(InitMemPool+MinIndex-2)*Align
* 本程序是为一体化web server产品专用设计,具有部分代码为具体产品优化而不代表普遍通用性的特性
* 程序在linux 2.46下调试通过,编辑工具netbeans 6.1 for c
*该结构用一个自增长的链表结构体保存分链表,每个结构体中包含具体链表的头部、尾部和空闲分界线指针,维护一个链表
*大致结构如下:
* MemPool
* V V V ...
* 链表1 链表2 链表3 ...
*通过这样一个结构系统就可以灵活增加减少系统池,并且可以控制池内结构,控制总数据量
* 联系方式:Email:
[email protected] QQ:51977431
* Created on 2008年5月26日, 下午4:18
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "memorys.h"
#include "log.h"
#include "config.h"
//内存池锁,现在还不确定是多锁性能更好还是总锁的性能好
pthread_mutex_t Memlock;
//内存池管理的项数范围,管理的最小为MinBlock,最大为InitMemPool*Align+MinBlock,除此之外的均交由malloc free自行管理
MemPool poolIndex[InitMemPool];
//Lock memLock;
static long totalByte;
//最大内存
long MaxMemory;
int Align;
int InitMemItem;
int ExpendMemItem;
int MinBlock;
long MaxBlock;
int MinIndex;
/*初始化池*/
void InitPool(void) {
MaxMemory = config->memory.MaxMemory;
MinIndex = config->memory.MinIndex;
Align = config->memory.Align;
InitMemItem = config->memory.InitMemItem;
ExpendMemItem = config->memory.ExpendMemItem;
MinBlock = Align*(MinIndex+1);
MaxBlock = (InitMemPool+MinIndex)*Align;
pthread_mutex_init(&Memlock, NULL);
int i;
MemPool *p;
for (i = 0; i < InitMemPool; i++) {
p = &poolIndex[i];
/*基本链表设置*/
p->name = i + MinIndex;
p->first = NULL;
p->last = NULL;
p->current = NULL;
/*设置杂项*/
p->max_memory = 0;
p->init_item = 0;
p->per_expend_item = 0;
p->current_item = 0;
p->total_item = 0;
}
printf("内存池初始化成功!\n");
}
/*
*释放内存池
*/
void FreePool() {
pthread_mutex_lock(&Memlock);
MemPool *pool;
int i;
for (i = 0; i < InitMemPool; i++) {
pool = &poolIndex[i];
if (pool->first != NULL) {
if (pool->total_item > 0) {
MemItem * mi = pool->first;
MemItem *ls;
while (mi != NULL) {
ls=mi;
mi = mi->next;
free(ls);
}
}
}
}
pthread_mutex_unlock(&Memlock);
pthread_mutex_destroy(&Memlock);
printf("Flower系统内存释放完毕!\n");
}
/*初始化项*/
void InitItem(unsigned int name) {
int blk;
MemItem *ip; /*项的链表指针*/
/*构造容器*/
MemPool *p = &poolIndex[name - MinIndex];
(p->total_item) += ((p->init_item) == 0 ? InitMemItem : (p->init_item));
p->first = (MemItem *) malloc(name * Align); /*创建第一个块*/
ip = p->first;
for (blk = 1; blk < (p->init_item == 0 ? InitMemItem : p->init_item); ++blk) {
ip->next = (MemItem *) malloc(name * Align);
ip = ip->next;
}
ip->next = NULL;
p->last = ip;
totalByte += name * Align * (p->init_item == 0 ? InitMemItem : p->init_item);
}
/*扩展当前池项的下属内存块*/
void ExpendItem(unsigned int name) {
int blk;
MemItem *ip; /*项的链表指针*/
/*构造容器*/
MemPool *p = &poolIndex[name - MinIndex];
p->total_item += (p->per_expend_item == 0 ? ExpendMemItem : p->per_expend_item);
p->last->next = (MemItem *) malloc(name * Align); /*创建第一个块*/
ip = p->last->next;
for (blk = 1; blk < (p->per_expend_item == 0 ? ExpendMemItem : p->per_expend_item); ++blk) {
ip->next = (MemItem *) malloc(name * Align);
ip = ip->next;
}
ip->next = NULL;
p->last = ip;
totalByte += name * Align * (p->per_expend_item == 0 ? ExpendMemItem : p->per_expend_item);
}
/*
*申请新的内存块
*/
void *New(unsigned int size) {
//MemItem *ip;/*项的链表指针*/
/*构造容器*/
if (totalByte > MaxMemory)
return NULL; //申请的总内存过大,请调大默认最大内存设置或者检察内寻泄露
size = (size + Align - 1) &~ (Align - 1);
if (size >= MaxBlock || size < MinBlock) {
return malloc(size);
}
size = size / Align;
MemPool *p = &poolIndex[size - MinIndex];
if (p->first == NULL)
InitItem(size);
if (p->first == NULL)
Error("当前项初始化时发生了错误,可能原因为系统内存不足%p", p);
//防止检测初始化不成功导致的意外错误
assert(p->first);
pthread_mutex_lock(&Memlock);
if (p->first->next == NULL) {
ExpendItem(size);
//防止检测扩展项不成功导致的错误
if (p->first->next == NULL)
Error("当前项扩展时发生了错误,可能会导致内存池New死锁,可能原因为系统内存不足%p", p->first);
}
MemItem *ips;
ips = p->first;
p->first = p->first->next;
p->current_item++;
pthread_mutex_unlock(&Memlock);
return ips; /*此处返回的是向后偏移过的指针*/
}
/*
*释放内存块
*/
void Free(void *myp) {
struct mem_block * realsize = (struct mem_block *) myp; //转化为Short指针
--realsize; /*向前移动short位移*/
int size = realsize->size - 9;
++realsize;
if (size >= MaxBlock || size < MinBlock) {
free(realsize);
return;
}
size = ((size + Align - 1) &~ (Align - 1)) / Align;
MemItem *ip = (MemItem *) realsize; /*转化回来*/
MemPool *p = &poolIndex[size - MinIndex];
if (p == NULL) {
Error("试图释放一个不属于池的指针,直接释放了,当前size%d\n", size);
return;
}
pthread_mutex_lock(&Memlock);
if (p->first != NULL) {
ip->next = NULL;
p->last->next = ip;
p->last = p->last->next;
p->current_item--;
} else {
Error("产生了一个野指针,,当前size:%d", size);
}
pthread_mutex_unlock(&Memlock);
return;
}
/*
*输出内存池管理的内存
*/
void PrintPool(void) {
MemPool *pool;
int i;
for (i = 0; i < InitMemPool; i++) {
pool = &poolIndex[i];
if (pool->first != NULL) {
printf("\n名称%i 共有%i 使用%i,初始化:%i 当前地址%p\n", pool->name, pool->total_item, pool->current_item, pool->init_item, pool->current);
if (pool->total_item > 0) {
MemItem * mi = pool->first;
while (mi != NULL) {
printf("--\t%p", mi);
mi = mi->next;
}
}
}
}
}