peakzhang 发表于 2008-7-13 23:15:10

问一个内存申请的问题

我看到的handle_input函数如下:
int Dgram_Endpoint::handle_input (ACE_HANDLE)
{
char buf;
ACE_INET_Addr from_addr;
ssize_t nbytes = this->endpoint_.recv (buf, sizeof(buf), from_addr);

ACE_Message_Block *mb = NULL;
ACE_NEW_RETURN(mb, ACE_Message_Block(nbytes, ACE_Message_Block::MB_DATA, 0, buf), -1);
mb->wr_ptr(nbytes);
this->task_mgr.putq(mb);
return 0;
}
这里每一个数据包到来都要ACE_NEW_RETURN一下,后面的处理函数通过调用mb->release()函数释放内存。
我们都知道系统的new和delete操作都是很费时间的事情,所以我想知道有没有好一点的办法能使线程的处理数据包的开销小一点。

peakzhang 发表于 2008-7-13 23:15:17

使用内存池即可,ACE支持的。详情见程序员指南,你可以自己定制分配器,使用内存池的形式处理。

peakzhang 发表于 2008-7-13 23:15:55

ACE_Cached_Allocator
ACE_Cached_Allocator预先分配内存,然后使用它自己内部的机制来管理此内存。这样的预分配发
生在类的构造器中。所以,如果你使用此分配器,你的内存管理方案仅仅在开始时使用OS分配接口来完
成预分配。在那以后,ACE_Cached_Allocator将照管所有的内存分配和释放。
为什么要这样做呢?答案是性能和可预测性。设想一个必须高度可预测的实时系统:通过OS来分配
内存将涉及昂贵和不可预测的OS内核调用;相反,ACE_Cached_Allocator不会涉及这样的调用。在构造器中预分配的内存在空闲表中进行内部管理。该表将若干内存chunk作为它的节点。这些chunk可以是任何复杂的数据类型,你可以按你所希望的那样规定它们的实际类型。后面的例子会说明怎样去做。 在此系统中分配和释放涉及固定数量的空闲表指针操作。当用户请求内存chunk时,他将获得一个指针,而空闲表被调整。当用户释放内存时,它将回到空闲表中。如此循环往复,直到ACE_Cached_Allocator被销毁,所有的内存随之被归还给OS。在内存被用于实时系统时,需要考虑chunk
的内部碎片。
下面的例子演示ACE_Cached_Allocator是怎样被用于预分配内存,然后处理内存请求的。

#include "ace/Malloc.h"
//A chunk of size 1K is created. In our case we decided to use a simple array
//as the type for the chunk. Instead of this we could use any struct or class
//that we think is appropriate.
typedef char MEMORY_BLOCK;
//Create an ACE_Cached_Allocator which is passed in the type of the
//“chunk” that it must pre-allocate and assign on the free list.
// Since the Cached_Allocator is a template class we can pretty much
//pass it ANY type we think is appropriate to be a memory block.
typedef ACE_Cached_Allocator<MEMORY_BLOCK,ACE_SYNCH_MUTEX> Allocator;
class MessageManager
{
public:
//The constructor is passed the number of chunks that the allocator
//should pre-allocate and maintain on its free list.
MessageManager(int n_blocks):
allocator_(n_blocks),message_count_(0)
{
mesg_array_=new char*;
}
//Allocate memory for a message using the Allocator. Remember the message
//in an array and then increase the message count of valid messages
//on the message array.
void allocate_msg(const char *msg)
{
mesg_array_=allocator_.malloc(ACE_OS::strlen(msg)+1);
ACE_OS::strcpy(mesg_array_,msg);
message_count_++;
}
//Free all the memory that was allocated. This will cause the chunks
//to be returned to the allocator’s internal free list
//and NOT to the OS.
void free_all_msg()
{
for(int i=0;i<message_count_;i++)
allocator_.free(mesg_array_);
message_count_=0;
}
//Just show all the currently allocated messages in the message array.
void display_all_msg()
{
for(int i=0;i<message_count_;i++)
ACE_OS::printf("%s\n",mesg_array_);
}
private:
char **mesg_array_;
Allocator allocator_;
int message_count_;
};
int main(int argc, char* argv[])
{
if(argc<2)
{
ACE_DEBUG((LM_DEBUG, "Usage: %s <Number of blocks>\n", argv));
exit(1);
}
int n_blocks=ACE_OS::atoi(argv);
//Instantiate the Memory Manager class and pass in the number of blocks
//you want on the internal free list.
MessageManager mm(n_blocks);
//Use the Memory Manager class to assign messages and free them.
//Run this in your favorite debug environment and you will notice that the
//amount of memory your program uses after Memory Manager has been
//instantiated remains the same. That means the Cached Allocator
//controls or manages all the memory for the application.
//Do forever.
while(1)
{
//allocate the messages somewhere
ACE_DEBUG((LM_DEBUG,"\n\n\nAllocating Messages\n"));
for(int i=0; i<n_blocks;i++){
ACE_OS::sprintf(message,"Message %d: Hi There",i);
mm.allocate_msg(message);
}
//show the messages
ACE_DEBUG((LM_DEBUG,"Displaying the messages\n"));
ACE_OS::sleep(2);
mm.display_all_msg();
//free up the memory for the messages.
ACE_DEBUG((LM_DEBUG,"Releasing Messages\n"));
ACE_OS::sleep(2);
mm.free_all_msg();
}
return 0;
}

这个简单的例子包含了一个消息管理器,它对缓存式分配器进行实例化。该分配器随即用于无休止地分配、显示和释放消息。但是,该应用的内存使用并没有变化。你可以通过你喜欢的调试工具来检查这一点。

peakzhang 发表于 2008-7-13 23:16:09

那么问题来了,
ACE_Message_block 提供了 Allocator参数 ,可以带入ACE_CACHED_ALLOCATOR
但如果这样的话,仍然要new 一个ACE_Message_block 加到 ACE_Message_Queue 当中去。

如果要 ACE_CACHED_ALLOCATOR 保存 ACE_Message_block 的话 这个该怎么做呢?

const CACHE_SIZE = 1024*64;
typedef char MEMORY_BLOCK;

typedef ACE_Cached_Allocator<MEMORY_BLOCK,ACE_SYNCH_MUTEX>MESSAGEDATA_Allocator;
typedef ACE_Cached_Allocator<ACE_Message_Block,ACE_SYNCH_MUTEX>MESSAGEBLOCK_Allocator;


    ACE_Message_Block *mb = (ACE_Message_Block *)m_pMssageData_allocator->malloc();
    int ret = mb->init(....);

编译倒是能过,感觉似乎不太对
页: [1]
查看完整版本: 问一个内存申请的问题