Click here to Skip to main content
6,934,508 members and growing! (13,690 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » STL » Memory Allocation     Intermediate License: The Code Project Open License (CPOL)

A Custom Block Allocator for Speeding Up VC++ STL

By Joaquín M López Muñoz

A block allocator for use with STL containers that greatly improves speed in programs doing massive data insertions and extractions.
VC7, VC7.1, VC8.0, Windows, STL, VS2005, Dev
Posted:10 May 2000
Updated:30 Oct 2006
Views:133,014
Bookmarked:45 times
printPrint Friendly   add Share
      Discuss Discuss   Broken Article?Report  
41 votes for this article.
Popularity: 7.02 Rating: 4.35 out of 5

1
1 vote, 5.9%
2

3
3 votes, 17.6%
4
13 votes, 76.5%
5

Introduction

block_allocator is a custom STL allocator for use with STL as implemented in Microsoft VC++. Rather than doing allocations on a per-node basis, block_allocator allocates memory in fixed sized chunks, and delivers portions of these chunks as requested. Typical speed improvements of 40% have been obtained with respect to the default allocator. The size of the chunks, set by the user, should not be too little (reduced speed improvements) nor too large (memory wasted). Experiment and see what sizes fit best to your application.

block_allocator can substitute for the default allocator in the following containers:

  • list,
  • set,
  • multiset,
  • map,
  • multimap,
and WON'T work with other containers such as vector or queue. Note however that vector and queue already perform allocation in chunks. The usage of block_allocator is fairly simple, for instance:
// block allocated list of ints with chunks of 1024 elements
std::list<int,block_allocator<int,1024> > l;
Normal containers and block allocated containers can coexist without problems.

Compatibility mode with MSVC++ 6.0/7.0

Due to limitations of the standard library provided with these compilers, the mode of usage explained above does not work here. To circumvent this problem one must proceed as follows: For each of the containers supported, there's an associated block allocated container derived from it thru use of block_allocator. You have to define an activating macro for each container to be defined prior to the inclusion of blockallocator.h:

  • list -> block_allocated_list (macro DEFINE_BLOCK_ALLOCATED_LIST),
  • set -> block_allocated_set (macro DEFINE_BLOCK_ALLOCATED_SET),
  • multiset -> block_allocated_multiset (macro DEFINE_BLOCK_ALLOCATED_MULTISET),
  • map -> block_allocated_map (macro DEFINE_BLOCK_ALLOCATED_MAP),
  • multimap -> block_allocated_multimap (macro DEFINE_BLOCK_ALLOCATED_MULTIMAP),

To use block allocation based STL in your application, define the corresponding activating macro, include blockallocator.h and then change your declarations as follows:

  • list<type> -> block_allocated_list<type,chunk_size>
  • set<key> -> block_allocated_set<key,chunk_size>
  • multiset<key> -> block_allocated_multiset<key,chunk_size>
  • map<key,type> -> block_allocated_map<key,type,chunk_size>
  • multimap<key,type> -> block_allocated_multimap<key,type,chunk_size>

where chunk_size is the size of the chunks. You can enter too the other optional template parameters (see MSVC++ STL docs for more info).

The MSVC++ 6.0/7.0 compatibility mode can also be used in MSVC++ 7.1, so you need not modify your block_allocator-related code when porting legacy code to 7.1.

Multithreading issues

Each block allocated container instance uses its own block_allocator, so no multithreading problems should arise as long as your program conveniently protects their containers for concurrent access (or if no two threads access the same container instance). This is the same scenario posed by regular STL classes (remember operations on containers are not guarded by CRITICAL_SECTIONs or anything similar), so the moral of it all is: If your program was multithread safe without block_allocator, it'll continue to be with it.

Version history

  • 29th Feb, 2000 - 1.1
    • Initial release in CodeProject.
  • 22nd Mar, 2001 - 1.2
    • Included definitions for operator== and operator!=. The lack of these caused linking errors when invoking list::swap() and similar methods. The funny thing about it is that no one ever reported this seemingly important bug, so either swap() is not that much used or not that many people use block_allocator!
  • 25th Oct, 2006 - 1.3
    • block_allocator now works with MSVC++ 7.1 and 8.0. Thanks to James May for helping with testing this new version of the code.
  • 30th Oct, 2006 - 1.4
    • Fixed some typedefs incorrectly made private in block_allocated_list, block_allocated_set, etc.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Joaquín M López Muñoz


Member

Location: Spain Spain

Other popular STL articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 58 (Total in Forum: 58) (Refresh)FirstPrevNext
Generalblock_allocated_list::sort() 2x slower than a standard stl::list()? PinmemberPet12321:33 26 May '08  
GeneralRe: block_allocated_list::sort() 2x slower than a standard stl::list()? PinmemberJoaquín M López Muñoz23:45 27 May '08  
GeneralLow Fragmentation Heap PinmemberPaul Sanders (AlpineSoft)9:00 26 Oct '07  
GeneralFree Heap block 347970 modified at 348394 after it was freed PinmemberNyarlatotep8:33 19 Dec '06  
GeneralRe: Free Heap block 347970 modified at 348394 after it was freed PinmemberNyarlatotep8:46 19 Dec '06  
GeneralRe: Free Heap block 347970 modified at 348394 after it was freed PinmemberNyarlatotep9:26 19 Dec '06  
GeneralRe: Free Heap block 347970 modified at 348394 after it was freed PinmemberJoaquín M López Muñoz3:29 20 Dec '06  
GeneralRe: Free Heap block 347970 modified at 348394 after it was freed PinmemberNyarlatotep4:04 20 Dec '06  
GeneralExcellent! and weird effect Pinsupporterpeterchen10:20 14 Nov '06  
GeneralRe: Excellent! and weird effect PinmemberJoaquín M López Muñoz11:35 14 Nov '06  
peterchen wrote:
The code in question uses a few hundred map[int, {16 byte struct}] instances, each map containing only a few (10..30) items. using block_allocator with small chunk sizes (128) I have about the same performance as std::map. Going to larger chunk sizes, performance radically degrades (half speed at 1024 bytes chunk size)

If maps sizes top at 30 or so why do you choose a chunk size that high? I'd try setting chunk_size to something closer to 30.

peterchen wrote:
Q:
Do you know a pathological case with your allcoator that may cause this?

No. My hunch about what can be going on is related to the observation above: if you have chunks of 128 elements and each map occupy only around 20% of each associated chunk, you get lots of wasted memory and possibly poor locality. Try lowering the chunk size.

peterchen wrote:
Can your code be modified quickly so all maps of a given type use the same block allocator instance. This way I could test the effect is purely memory locality.

I can't check it right now, but it should be easy to hack this for a try:
  1. In class block_allocator, make the members head and tail static.
  2. Delete all constructors of block_allocator.
  3. Move the head/tail initialization code:
          head.next=reinterpret_cast<chunk *>(&tail);
    tail.previous=reinterpret_cast<chunk *>(&head);
    to some initialization routine of your program (this procedure must be done exactly once).
Please keep me informed about your progress. Hope this helps,

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
Want a Boost forum in Code Project? Vote here[^]!

GeneralRe: Excellent! and weird effect Pinsupporterpeterchen12:49 14 Nov '06  
GeneralProblem with block_allocated_list::const_iterator in VS2005 PinmemberWocki21:41 26 Oct '06  
AnswerRe: Problem with block_allocated_list::const_iterator in VS2005 PinmemberJoaquín M López Muñoz22:46 26 Oct '06  
Generalthank you! Pinmemberwb20:28 26 Oct '06  
Generalchunk size Pinmemberslonial3:34 17 Feb '06  
Generalwhy do you need to define MSVC_STL_list_node? PinsussAnonymous10:07 24 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinmemberJoaquín M López Muñoz12:15 24 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinsussAnonymous21:47 24 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinmemberJoaquín M López Muñoz5:11 25 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinsussAnonymous10:03 26 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinsussAnonymous10:05 26 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinmemberJoaquín M López Muñoz10:48 26 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinsussAnonymous11:51 26 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinmemberJoaquín M López Muñoz12:32 26 Aug '04  
GeneralRe: why do you need to define MSVC_STL_list_node? PinsussAnonymous21:54 26 Aug '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+PgUp/PgDown to switch pages.

PermaLink | Privacy | Terms of Use
Last Updated: 30 Oct 2006
Editor: Sean Ewington
Copyright 2000 by Joaquín M López Muñoz
Everything else Copyright © CodeProject, 1999-2010
Web20 | Advertise on the Code Project