Nested STL vector using way too much memory

后端 未结 6 1496
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-06 16:19

I have an STL vector My_Partition_Vector of Partition objects, defined as

struct Partition // the event log data structure
{
    in         


        
6条回答
  •  独厮守ぢ
    2021-01-06 16:55

    While I think he may be overstating the situation just a tad, I'm in general agreement with DeadMG's conclusion that what you're doing is asking for trouble.

    Although I'm generally the one looking at (whatever mess somebody has made) and saying "don't do that, just use a vector", this case might well be an exception. You're creating a huge number of objects that should be tiny. Unfortunately, a vector typically looks something like this:

    template 
    class vector { 
        T *data;
        size_t allocated;
        size_t valid;
    public:
        // ...
    };
    

    On a typical 32-bit machine, that's twelve bytes already. Since you're using a vector >, you're going to have 12 bytes for the outer vector, plus twelve more for each vector it holds. Then, when you actually store any data in your vectors, each of those needs to allocate a block of memory from the free store. Depending on how your free store is implemented, you'll typically have a minimum block size -- frequently 32 or even 64 bytes. Worse, the heap typically has some overhead of its own, so it'll add some more memory onto each block, for its own book-keeping (e.g., it might use a linked list of blocks, adding another pointer worth of data to each allocation).

    Just for grins, let's assume you average four vectors of four bytes apiece, and that your heap manager has a 32-byte minimum block size and one extra pointer (or int) for its bookkeeping (giving a real minimum of 36 bytes per block). Multiplying that out, I get 204 bytes apiece -- close enough to your 209 to believe that's reasonably close to what you're dealing with.

    The question at that point is how to deal with the problem. One possibility is to try to work behind the scenes. All the containers in the standard library use allocators to get their memory. While they default allocator gets memory directly from the free store, you can substitute a different one if you choose. If you do some looking around, you can find any number of alternative allocators, many/most of which are to help with exactly the situation you're in -- reducing wasted memory when allocating lots of small objects. A couple to look at would be the Boost Pool Allocator and the Loki small object allocator.

    Another possibility (that can be combined with the first) would be to quit using a vector > at all, and replace it with something like:

    char partitions[16];
    struct parts { 
        int part0 : 4;
        int part1 : 4;
        int part2 : 4;
        int part3 : 4;
        int part4 : 4;
        int part5 : 4;
        int part6 : 4
        int part7 : 4;
    };
    

    For the moment, I'm assuming a maximum of 8 partitions -- if it could be 16, you can add more to parts. This should probably reduce memory usage quite a bit more, but (as-is) will affect your other code. You could also wrap this up into a small class of its own that provides 2D-style addressing to minimize impact on the rest of your code.

提交回复
热议问题