Skip to content

Commit 068cf50

Browse files
committed
Recycle serialization buffers on transmission
Adds a LIFO buffer pool in the context to reuse buffers allocated on serialization. The aim is not (only) to avoid the overhead of dynamic allocation but rather to enhance the cache locality of serialization buffers.
1 parent df6ec26 commit 068cf50

File tree

5 files changed

+368
-298
lines changed

5 files changed

+368
-298
lines changed
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2024 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef DETAIL__BUFFER_POOL_HPP_
16+
#define DETAIL__BUFFER_POOL_HPP_
17+
18+
#include <mutex>
19+
#include <cassert>
20+
#include <vector>
21+
22+
#include "rcutils/allocator.h"
23+
24+
// FIXME(fuzzypixelz): indeed, we leak all allocated buffers ;)
25+
class BufferPool
26+
{
27+
public:
28+
struct Buffer
29+
{
30+
uint8_t *data;
31+
size_t size;
32+
};
33+
34+
BufferPool() = default;
35+
36+
Buffer allocate(rcutils_allocator_t *allocator, size_t size)
37+
{
38+
std::lock_guard<std::mutex> guard(mutex_);
39+
40+
if (buffers_.empty()) {
41+
uint8_t *data = static_cast<uint8_t *>(allocator->allocate(size, allocator->state));
42+
if (data == nullptr) {
43+
return {};
44+
}
45+
return Buffer {data, size};
46+
} else {
47+
Buffer buffer = buffers_.back();
48+
buffers_.pop_back();
49+
if (buffer.size < size) {
50+
uint8_t *data = static_cast<uint8_t *>(allocator->reallocate(
51+
buffer.data, size, allocator->state));
52+
if (data == nullptr) {
53+
return {};
54+
}
55+
buffer.data = data;
56+
buffer.size = size;
57+
}
58+
return buffer;
59+
}
60+
}
61+
62+
void
63+
deallocate(Buffer buffer)
64+
{
65+
std::lock_guard<std::mutex> guard(mutex_);
66+
buffers_.push_back(buffer);
67+
}
68+
69+
private:
70+
std::vector<Buffer> buffers_;
71+
std::mutex mutex_;
72+
};
73+
74+
#endif // DETAIL__BUFFER_POOL_HPP_

rmw_zenoh_cpp/src/detail/rmw_context_impl_s.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "graph_cache.hpp"
2626
#include "rmw_node_data.hpp"
27+
#include "buffer_pool.hpp"
2728

2829
#include "rmw/ret_types.h"
2930
#include "rmw/types.h"
@@ -92,6 +93,9 @@ struct rmw_context_impl_s final
9293
// Forward declaration
9394
class Data;
9495

96+
// Pool of serialization buffers.
97+
BufferPool serialization_buffer_pool;
98+
9599
private:
96100
std::shared_ptr<Data> data_{nullptr};
97101
};

0 commit comments

Comments
 (0)