none
MaxBufferPoolSize vs MaxBufferSize

    Question

  • MaxBufferPoolSize
       Gets or sets the maximum amount of memory allocated for the buffer manager that manages the buffers required by endpoints that use this binding.

    MaxBufferSize 
        
       Gets or sets the maximum amount of memory that is allocated for use by the manager of the message buffers that receive messages from the channel.


    it is not clear to me at this point what role each of these properties have and how should i evaluate them correctly so i'll be capable to correctly alter them and have good results based of course on the average, and max size of resources requested/handled.

    can someone shed some light in this subject?

    thank you,
    ovidiu
    Tuesday, March 03, 2009 11:19 PM

Answers

  • Hello, first let's see what is a buffer and what is a buffer pool. In a nutshell, a buffer pool contains one or more buffers. They're both managed by BufferManager. When a BufferManager is created, unless MaxBufferPoolSize is 0 (which indicates no pool is used and each request will create a new buffer), a series of buffer pools will also be created. The size of the buffer in each pool will be: 128, 256, 512, until the size reaches MaxBufferSize. For example, if MaxBufferSize is 300, 3 buffer pools will be created, each contains buffers whose sizes are 128, 256, and 300.

    Now when a request comes, the BufferManager will try to find a pool whose buffers' sizes are sufficient for this message. As long as the message's size is less than MaxBufferSize, it will be able to find a suitable pool. Let's continue with our sample, and say our message size is 270. So the buffer pool with size 300 is used. In this case, it will try to take an already allocated buffer from the pool. If such a buffer exists, then just use it. Else a new buffer is allocated in the pool (in this case, a buffer with size 300 is allocated and used).



    On the other hand, if the message exceeds MaxBufferSize (for example, 350), no suitable buffer pool will be found. In this case, a buffer with size 350 is allocated and used. Up till now, you may not see a lot of difference between the two scenarios. But...



    Once the message finishes processing, the buffer will not always be released immediately. Instead, the buffer is likely to be returned to the pool for reuse if it can. In our example, we have created two buffers, one has a size 300, and the other has a size 350. The second buffer exceeds MaxBufferSize, and cannot be returned to any pools, so it can be GCed immediately. The first won't. The BufferManager will try to put it in the pool whose buffer size is 300. This will succeed as long as the sum of size of all buffers in this pool is less than MaxBufferPoolSize.



    For example, let's say our MaxBufferPoolSize is 1000. We have already processed 3 messages whose size is larger than 256 but less than 300, so the pool with buffer size 300 is used. Now the pool contains 3 buffers, and the total size of this pool is 900. Now 4 new messages come at the same time. The first 3 will happily take the already allocated buffers, and the last messages will create a new buffer. In this case, after the last message finishes processing, it will not be able to return the buffer with size 300 to the pool because by doing so, the buffer pool's size will become 1200, which exceeds MaxBufferPoolSize. So in our sample, the pool with buffer size 300 can contain a maximum of 3 buffers. If 4 messages come simultaneously, the 4th message will have to create an extra buffer on the heap, which will then have to be GCed.



    Hope now you have a clear understand of what is MaxBufferSize and what is MaxBufferPoolSize. Essentially, if you need to process a lot of large messages, you can use a large MaxBufferSize, or each request will have to create a new buffer. If your system normally have 4 concurrent requests, you may want to set the MaxBufferPoolSize 4 times as the MaxBufferSize, so while new requests don't need to allocate a new buffer each time, no extra memory is wasted. But of course, use too much memory will also decrement performance. You will have to find a balance between time and memory...


    Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, March 05, 2009 4:04 AM

All replies

  • Hello, first let's see what is a buffer and what is a buffer pool. In a nutshell, a buffer pool contains one or more buffers. They're both managed by BufferManager. When a BufferManager is created, unless MaxBufferPoolSize is 0 (which indicates no pool is used and each request will create a new buffer), a series of buffer pools will also be created. The size of the buffer in each pool will be: 128, 256, 512, until the size reaches MaxBufferSize. For example, if MaxBufferSize is 300, 3 buffer pools will be created, each contains buffers whose sizes are 128, 256, and 300.

    Now when a request comes, the BufferManager will try to find a pool whose buffers' sizes are sufficient for this message. As long as the message's size is less than MaxBufferSize, it will be able to find a suitable pool. Let's continue with our sample, and say our message size is 270. So the buffer pool with size 300 is used. In this case, it will try to take an already allocated buffer from the pool. If such a buffer exists, then just use it. Else a new buffer is allocated in the pool (in this case, a buffer with size 300 is allocated and used).



    On the other hand, if the message exceeds MaxBufferSize (for example, 350), no suitable buffer pool will be found. In this case, a buffer with size 350 is allocated and used. Up till now, you may not see a lot of difference between the two scenarios. But...



    Once the message finishes processing, the buffer will not always be released immediately. Instead, the buffer is likely to be returned to the pool for reuse if it can. In our example, we have created two buffers, one has a size 300, and the other has a size 350. The second buffer exceeds MaxBufferSize, and cannot be returned to any pools, so it can be GCed immediately. The first won't. The BufferManager will try to put it in the pool whose buffer size is 300. This will succeed as long as the sum of size of all buffers in this pool is less than MaxBufferPoolSize.



    For example, let's say our MaxBufferPoolSize is 1000. We have already processed 3 messages whose size is larger than 256 but less than 300, so the pool with buffer size 300 is used. Now the pool contains 3 buffers, and the total size of this pool is 900. Now 4 new messages come at the same time. The first 3 will happily take the already allocated buffers, and the last messages will create a new buffer. In this case, after the last message finishes processing, it will not be able to return the buffer with size 300 to the pool because by doing so, the buffer pool's size will become 1200, which exceeds MaxBufferPoolSize. So in our sample, the pool with buffer size 300 can contain a maximum of 3 buffers. If 4 messages come simultaneously, the 4th message will have to create an extra buffer on the heap, which will then have to be GCed.



    Hope now you have a clear understand of what is MaxBufferSize and what is MaxBufferPoolSize. Essentially, if you need to process a lot of large messages, you can use a large MaxBufferSize, or each request will have to create a new buffer. If your system normally have 4 concurrent requests, you may want to set the MaxBufferPoolSize 4 times as the MaxBufferSize, so while new requests don't need to allocate a new buffer each time, no extra memory is wasted. But of course, use too much memory will also decrement performance. You will have to find a balance between time and memory...


    Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, March 05, 2009 4:04 AM
  • thanks a lot for your answer!
    Monday, March 09, 2009 9:46 PM
  • Hi Yi-Lun,
    thanks for the input.
    Just to clarify some points, I have some questions. In the first paragraph you say "For example, if MaxBufferSize is 300, 3 buffer pools will be created, each contains buffers whose sizes are 128, 256, and 300." I guess this is true if MaxBufferPoolSize is 1000? So in that case there will be 3 buffer pools, one with 3 buffers á 128 bytes, one with 3 buffers á 256 bytes, and one with 3 buffers á 300 bytes? Or will there by one with 7 buffers á 128 bytes, one with 3 buffers á 256 bytes, and one with 3 buffers á 300 bytes?
    My understanding is that even though the buffer pools are created when the BufferManager is created, the memory for the buffers themselves is allocated not before a message is received. If there is a long-running service will buffers eventually be GCed after some period of time or will memory that has been allocated by buffers remain allocated until the service host is terminated?
    Thanks in advance,
    Ulli
    Tuesday, March 10, 2009 2:34 PM
  • Hello Ulli,

    I think the Buffer pools is some kind of container and that will be blank at the time the BufferManager is created, and when a request message coming, the WCFRuntime will investigate the message size and looking for the sufficient buffer in the Pool, if it does find no corresponding buffer, it'll try to create a new buffer for that message, and then when the buffer is no longer to use it'll be returned to the Buffer Pool and ofcourse it'll not be GCed until the service is terminated.
    Wednesday, March 11, 2009 2:52 AM
  • Hi Ulli,

    If you're still interested in the inner workings of WCF's BufferManager, you can check out my post which offers a pretty detailed description of how things work under the hood.  The gist of it is that BufferManager doesn't actually pre-allocate any memory.  Memory is allocated only as messages arrive and is stored (up to MaxBufferPoolSize) in pools of buffers of sizes 128, 256, ..., MaxBufferSize.  BufferManager dynamically distributes memory between these pools to adapt to the message sizes that your service most commonly receives, so the memory allocated to each pool changes over time.  Finally, the buffers remain allocated (again, only up to MaxBufferPoolSize) until the host is terminated.

    Andrew
    Senior Program Manager, Windows Worfklow Foundation and Windows Communication Foundation
    Wednesday, September 09, 2009 11:07 PM
  • Hi Yi-Lun Luo,

    Thanks for the detailed explanation . I wanted to know whether the maxBufferSize & maxBufferPoolSize have any significance while using the TransferMode as "Streamed"

    Tuesday, January 07, 2014 11:42 AM