Thread: STL preformance question

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    630

    STL preformance question

    Hello..

    Im developing huge win32 api server using IOCP framework..

    I have a decent c++ source which uses its own buffer class to allocate BYTES (not strings), and its used to use the same memory (once allocated) so theres no need to allocate/delete it over and over again..

    I got used to STL and I really dont like own implementations of linked lists or buffer classes, and I wonder if I would use std::string instead of that buffer class, would there be any loss of preformance? I know string allocates new buffer automatically (does that affect a lot of preformance in bigger projects?).

    The other reason why I would like to use STL is to make code smaller, and easier..

    What do you think? What STL type would be better to use instead of BYTE for this purpose? std::string?

    Thanks for help

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    A std::vector<BYTE> would seem an appropriate candidate(a BYTE is a just a typedef'd unsigned char) or, perhaps, a std::deque if you wanted fast insertions at the beginning of the array as well as at the end.

    As far as I know, stl containers are likely to be at least as efficient as something similar you've designed yourself unless, perhaps, you've optimised for a particular platform and/or scenario of use.

    The text I have to hand (Josuttis, C++ Standard Library) mentions amortized constant time(O1) for insertions for both vectors and deques. This, apparently, is 'fast' (independent of the number of elements) but may be slower if the container needs resizing to insert an element. The issue of size can be resolved with the reserve member function, if you know in advance the maximum expected size of the container. Searching should be as good as searching a normal array; both containers provide random access to an internally managed array of contiguous memory.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    When you say that the C++ source uses its own buffer class that uses the same memory so there's no need to allocate and delete it over and over, what do you mean? Is this memory shared between multiple buffers? Is the buffer destroyed but the memory left around for the next time a buffer is created?

    If you use a vector (or string or deque), what will most likely happen is that if you clear the container, the memory will not be deallocated. So if you are using the same vector over and over, just inserting a bunch of stuff, then using it, then clearing the vector, then you will probably not notice much of a problem.

    If, however, the other buffer class keeps a pool of memory around independent of what instances of the class are in use, then there might be some differences. What I would do is go ahead and use the vector class. Then, after you have done a significant portion of the implementation, you should profile the code. A good profiler will tell you what code is causing the largest slowdowns. If it turns out that your code is spending a lot of time allocating and deallocating, then you can consider taking action. What usually ends up happening is that the vector (or other container) works fine and your slowdowns are in other areas of the program.

    If profiling does show a slowdown due to allocation and deallocation, then you should customize your container with an allocator. Boost has a pool allocator that you can use with STL containers that basically keeps a pool of memory for the container to use which helps avoid excessive allocation and reallocation. I would only worry about this if the profiling showed it to be necessary, but if it is necessary it is not terribly hard to implement and you still get to use the STL containers you want.

    And I agree with Ken Fitlike that vector<BYTE> sounds like the best option from what little we know of the situation.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I'm sort of lost on the no need to de-allocate and delete part? Does this mean you are allocating the chunk once and then simply using it for different buffers? If this is the case I don't think vector is what you need. Of course you could store a record structure in a vector indicating the starting offset of the chunk and the chunk size. This would be used as a lookup table into the large buffer.

    Code:
    struct BUFFER_CHUNK
    {
      DWORD dwLength;
      DWORD dwOffset;
    };
    
    std::vector<BUFFER_CHUNK *> m_vChunks;
    If this is the type of setup you are talking about then there are tree structures that can handle this type of sharing much more efficiently.

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    630
    Quote Originally Posted by Bubba
    I'm sort of lost on the no need to de-allocate and delete part? Does this mean you are allocating the chunk once and then simply using it for different buffers?
    Yes, this is what I mean..

    So whats the 'best' approach to this?

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Yes, this is what I mean..
    Could you clarify more, perhaps by answering the questions in my post?

    >> So whats the 'best' approach to this?
    As I said earlier, a vector with a pool allocator is fairly easy to implement, and would likely solve your problem (if you have one).

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    630
    Quote Originally Posted by Daved
    When you say that the C++ source uses its own buffer class that uses the same memory so there's no need to allocate and delete it over and over, what do you mean? Is this memory shared between multiple buffers? Is the buffer destroyed but the memory left around for the next time a buffer is created?

    If you use a vector (or string or deque), what will most likely happen is that if you clear the container, the memory will not be deallocated. So if you are using the same vector over and over, just inserting a bunch of stuff, then using it, then clearing the vector, then you will probably not notice much of a problem.

    If, however, the other buffer class keeps a pool of memory around independent of what instances of the class are in use, then there might be some differences. What I would do is go ahead and use the vector class. Then, after you have done a significant portion of the implementation, you should profile the code. A good profiler will tell you what code is causing the largest slowdowns. If it turns out that your code is spending a lot of time allocating and deallocating, then you can consider taking action. What usually ends up happening is that the vector (or other container) works fine and your slowdowns are in other areas of the program.

    If profiling does show a slowdown due to allocation and deallocation, then you should customize your container with an allocator. Boost has a pool allocator that you can use with STL containers that basically keeps a pool of memory for the container to use which helps avoid excessive allocation and reallocation. I would only worry about this if the profiling showed it to be necessary, but if it is necessary it is not terribly hard to implement and you still get to use the STL containers you want.

    And I agree with Ken Fitlike that vector<BYTE> sounds like the best option from what little we know of the situation.
    Sorry, because I didnt answer in my previous post.

    The buffer class handles memory when needed, it will allocate and wont delete it when processing is finished, but will use old memory instead of allocating new and deleting old memory. (Keeps a pool of memory)

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Ok. That makes sense. Using a vector (or other appropriate STL container) is the way to go. Use the boost::pool_allocator or boost::fast_pool_allocator with your STL container if you really feel like you need to have the memory pool. That way you can continue to use the standard vector container that you are familiar with without the pool affecting much code.

    http://www.boost.org/libs/pool/doc/interfaces.html

    That site has more information. If you scroll down to the pool_alloc section, there is even an example using vector and boost::pool_allocator. You don't have to build Boost to use it, just download it and include the appropriate headers.

  9. #9
    Registered User
    Join Date
    May 2006
    Posts
    630
    Hello again..

    Thanks Daved, that helped me a lot..
    I do not feel like I need to have memory pool, I just dont feel like having home-written implementations instead of professional libaries (boost, stl) in my code.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I agree. I am only saying that you can use vector (or any other STL container) without a memory pool, and your program should work fine. Only after you find out that your program is slow because it needs a memory pool would you want to add boost. I definitely agree that you should go ahead and start using the STL containers now.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. STL list.sort() question
    By dudeomanodude in forum C++ Programming
    Replies: 14
    Last Post: 01-23-2008, 02:48 PM
  2. Design layer question
    By mdoland in forum C# Programming
    Replies: 0
    Last Post: 10-19-2007, 04:22 AM
  3. STL algorithm question
    By Reggie in forum C++ Programming
    Replies: 1
    Last Post: 04-22-2003, 09:04 AM
  4. opengl DC question
    By SAMSAM in forum Game Programming
    Replies: 6
    Last Post: 02-26-2003, 09:22 PM
  5. question about STL
    By free2run in forum C++ Programming
    Replies: 2
    Last Post: 12-16-2002, 12:12 PM