Add article for buffer manager
This commit is contained in:
Родитель
0aeeda5f51
Коммит
56e8c59363
|
@ -0,0 +1,56 @@
|
|||
# Buffer Manager
|
||||
|
||||
On .Net Framework (4.0 and above) and .Net Core, the library supports buffer pooling to reduce allocation and improve performance.
|
||||
|
||||
## IBufferManager
|
||||
|
||||
Application can implement this interface to manage byte array allocation and pooling. There are different pooling strategies.
|
||||
* Allocate fixed-size byte[] objects and create smaller pools of each size.
|
||||
* Allocate a large byte array and manage it like a heap.
|
||||
|
||||
The library provides a built-in buffer manager (`BufferManager`) which should be sufficient for most scenarios. If the application has a buffer manager for application data, it makes sense to use it as well for the library.
|
||||
|
||||
The buffer manager can be set to `ConnectionFactory.BufferManager` or `ConnectionListener.BufferManager`. Once it is set, most if not all byte array allocations will be through the buffer manager.
|
||||
|
||||
```
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.BufferManager = new BufferManager(64, 1024 * 1024, 50 * 1024 * 1024);
|
||||
```
|
||||
In this example, a buffer manager is created to pool buffers from 64 bytes to 1 MB with a limit of 50 MB on total memory usage.
|
||||
|
||||
## Application Responsibility
|
||||
|
||||
### Sending Messages
|
||||
|
||||
In most cases, no special actions are required for sending messages. However, if the application has a lot of binary data to transfer, it should take advantage of `Data.Buffer` to reduce allocation. `Data.Buffer` is of type `ByteBuffer` which can wrap an existing `byte[]` or `ArraySegment<byte>` which in turn can be taken from the buffer manager. The following example shows how to use pooled buffers to initialize message for send.
|
||||
```
|
||||
ArraySegment<byte> segment = bufferManager.TakeBuffer(1024);
|
||||
int len = WriteBuffer(segment); // initialize the buffer and return payload length
|
||||
ByteBuffer buffer = new ByteBuffer(segment.Array, segment.Offset, len, segment.Count);
|
||||
Message message = new Message() { BodySection = new Data() { Buffer = buffer } };
|
||||
try
|
||||
{
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferManager.ReturnBuffer(segment);
|
||||
}
|
||||
```
|
||||
|
||||
### Receiving Messages
|
||||
|
||||
The received message is backed up by a buffer taken from the buffer manager. The ownership of the message is transferred to the application after the receive call. Therefore, the application must ensure that `Message.Dispose` is called after the message is processed, otherwise a buffer is leaked (not returned to the buffer manager). To access the message body, the application should avoid reading `Message.Body` or `((Data)Message.BodySection).Binary`. Internally the library wraps the body payload in a `ByteBuffer` object, and it requires an allocation of `byte[]` with the exact size and a copy of the payload into the `byte[]` object. The recommended way to access the body is to get back the `ByteBuffer` object and process it as follows.
|
||||
```
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
try
|
||||
{
|
||||
ByteBuffer buffer = message.GetBody<ByteBuffer>();
|
||||
await ProcessBufferAsync(buffer);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
message.Dispose();
|
||||
}
|
||||
```
|
|
@ -111,4 +111,4 @@ Many async operation completion and callback invoke are triggered by an incoming
|
|||
## Advanced topics
|
||||
* [Listener](listener.md)
|
||||
* [Serialization](serialization.md)
|
||||
* Buffer Management
|
||||
* [Buffer Management](buffer_management.md)
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
href: serialization.md
|
||||
- name: Listener
|
||||
href: listener.md
|
||||
- name: Buffer Management
|
||||
href: buffer_management.md
|
||||
- name: Tracing
|
||||
href: tracing.md
|
||||
- name: Test Amqp Broker
|
||||
|
|
Загрузка…
Ссылка в новой задаче