寻找一种快速方法来填充 std::list
我有一个 Visual Studio 2008 C++ 程序,其中使用内存池的地址填充 std::list
。
我有一个使用 std::generate 工作的实现,它还不错,但是对于大池的小分配块来说它可能有点慢。
/// fill the allocation list with the memory addresses of each block
struct fill
{
fill( void* start, ulong alloc )
: start_( start ),
alloc_( alloc ),
count_( 0 )
{
};
void* operator()()
{
return ( void* )( ( ulong ) start_ + ( count_++ ) * alloc_ );
}
/// starting address
void* start_;
/// size of the blocks
ulong alloc_;
/// internal counter
int count_;
}; // struct fill
ulong begin = 0; // beginning address
ulong max_size = 0x1000; // maximum memory pool size (4KB)
ulong block_size = 0x20; // size of each memory block (32B)
std::list< void* > memory;
memory.resize( max_size / block_size ); // 128 memory blocks
std::generate( memory.begin(), memory.end(), fill( begin, block_size ) );
我只是想知道是否有人有更快或更有效的方法来填充链表。
谢谢, 保罗·H
I have a Visual Studio 2008 C++ program where I'm populating a std::list
with the addresses of a memory pool.
I have an implementation that works using std::generate
and it's not bad, but it can be a bit slow with large pools of small allocation blocks.
/// fill the allocation list with the memory addresses of each block
struct fill
{
fill( void* start, ulong alloc )
: start_( start ),
alloc_( alloc ),
count_( 0 )
{
};
void* operator()()
{
return ( void* )( ( ulong ) start_ + ( count_++ ) * alloc_ );
}
/// starting address
void* start_;
/// size of the blocks
ulong alloc_;
/// internal counter
int count_;
}; // struct fill
ulong begin = 0; // beginning address
ulong max_size = 0x1000; // maximum memory pool size (4KB)
ulong block_size = 0x20; // size of each memory block (32B)
std::list< void* > memory;
memory.resize( max_size / block_size ); // 128 memory blocks
std::generate( memory.begin(), memory.end(), fill( begin, block_size ) );
I was just wondering if anybody had a faster or more efficient method of filling the linked-list.
Thanks,
PaulH
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码会遍历该列表两次而不是一次。
因此,定义一个返回地址的迭代器可能会有所帮助,以便一切都在一次传递中完成:(
代码未经过测试,并且我遗漏了成为正确迭代器所需的一些内容 - 它需要如果没有别的,标记,并且通常欢迎后增量。)
目前它只是一个 ForwardIterator (或者如果它被标记的话将会是)。您可以轻松地将其设置为 RandomAccessIterator,但您必须为最终迭代器提供正确的大小。如果您使用
char(*)[block_size]
容器而不是void*
容器,那么我认为您可以使用boost::counting_iterator< ;char(*)[block_size]>
来填充它。但从根本上来说,std::list 的速度相当慢。除非你要在中间插入/删除(这对于内存池空闲列表来说似乎是不必要的 - 如果所有块的大小相同,你应该总是能够在最后添加和删除),否则你可能会做得更好使用向量或双端队列,或者至少使用侵入式链表。
Your code passes over the list twice instead of once.
So it might help to define an iterator that returns the addresses, so that everything is done in a single pass:
(Code not tested, and I've left out some of the stuff you need in order to be a proper iterator - it needs tagging if nothing else, and post-increment is usually welcome.)
Currently it's just a ForwardIterator (or would be, if it was tagged). You could make it a RandomAccessIterator easily enough, but you'd have to give the end iterator the correct size. If you used a container of
char(*)[block_size]
instead of a container ofvoid*
, then I think you could just use aboost::counting_iterator<char(*)[block_size]>
to populate it.Fundamentally, though,
std::list
is moderately slow at this. Unless you're going to do insert/remove in the middle (which seems unnecessary for a memory pool free list - if all the blocks are the same size you should be able to always add and remove at the end), you might do better with a vector or deque, or at least with an intrusive linked list.