Skip to content

Commit

Permalink
Counters optimization, step 3:
Browse files Browse the repository at this point in the history
- Added a new Segment Allocator for counters that works for O(1) time.
- Added unittests for the new allocator.
- A command has been added to the cli "counters stat" that outputs statistics on the use of counters, an example of its output is given below:

	Counters usage info
	Free blocks: 2046, counters: 8388356
	Errors external: 0, internal: 0
	size: 2, used blocks: 1, busy blocks: 0, used segments: 2
	size: 4, used blocks: 1, busy blocks: 0, used segments: 30
  • Loading branch information
stal76 authored and GeorgyKirichenko committed Aug 25, 2024
1 parent cecd7e9 commit d482fd0
Show file tree
Hide file tree
Showing 10 changed files with 623 additions and 86 deletions.
1 change: 1 addition & 0 deletions cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ std::vector<std::tuple<std::string,
{"version", "", [](const auto& args) { call(show::version, args); }},
{"latch update dataplane", "<latch name> <state>", [](const auto& args) { call(latch::dataplane_update, args); }},
{"counter", "[counter_name] <core_id>", [](const auto& args) { call(show::counter_by_name, args); }},
{"counters stat", "", [](const auto& args) { call(show::counters_stat, args); }},
{"latch update dataplane", "<latch name> <state>", [](const auto& args) { call(latch::dataplane_update, args); }},
{},
{"convert logical_module", "", [](const auto& args) { call(convert::logical_module, args); }}};
Expand Down
15 changes: 15 additions & 0 deletions cli/show.h
Original file line number Diff line number Diff line change
Expand Up @@ -924,4 +924,19 @@ void shm_tsc_set_base_value(std::string counter_name, uint32_t value)
}
}

void counters_stat()
{
interface::controlPlane controlplane;
auto [common_info, sizes_info] = controlplane.counters_stat();
auto [free_blocks, free_cells, errors_external, errors_internal] = common_info;
printf("Counters usage info\n");
printf("Free blocks: %d, counters: %d\n", free_blocks, free_cells);
printf("Errors external: %ld, internal: %ld\n", errors_external, errors_internal);

for (auto [size, used_blocks, busy_blocks, used_segments] : sizes_info)
{
printf("size: %d, used blocks: %d, busy blocks: %d, used segments: %d\n", size, used_blocks, busy_blocks, used_segments);
}
}

}
5 changes: 5 additions & 0 deletions common/icontrolplane.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ class controlPlane
return get<common::icp::requestType::convert, common::icp::convert::response>(request);
}

auto counters_stat() const
{
return get<common::icp::requestType::counters_stat, common::icp::counters_stat::response>();
}

protected:
void connectToControlPlane() const
{
Expand Down
23 changes: 21 additions & 2 deletions common/icp.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ enum class requestType : uint32_t
nat46clat_announce,
nat46clat_stats,
convert,
counters_stat,
size // size should always be at the bottom of the list, this enum allows us to find out the size of the enum list
};

Expand Down Expand Up @@ -220,6 +221,8 @@ inline const char* requestType_toString(requestType t)
return "nat46clat_stats";
case requestType::convert:
return "convert";
case requestType::counters_stat:
return "counters_stat";
case requestType::size:
return "unknown";
}
Expand Down Expand Up @@ -907,6 +910,22 @@ using response = std::vector<std::tuple<unsigned int, ///< id
std::string>>; ///< name
}

namespace counters_stat
{
using one_size_info = std::tuple<uint16_t, ///< size of segments
uint32_t, ///< used_blocks
uint32_t, ///< busy_blocks
uint32_t>; ///< used_segments

using common_info = std::tuple<uint32_t, ///< free_blocks
uint32_t, ///< free_cells_
uint64_t, ///< errors_external_
uint64_t>; ///< errors_internal_

using response = std::tuple<common_info,
std::vector<one_size_info>>;
}

using request = std::tuple<requestType,
std::variant<std::tuple<>,
acl_unwind::request,
Expand Down Expand Up @@ -974,7 +993,7 @@ using response = std::variant<std::tuple<>,
nat46clat_config::response,
nat46clat_announce::response,
nat46clat_stats::response,
convert::response>;
convert::response,
counters_stat::response>;
}

}
9 changes: 9 additions & 0 deletions controlplane/controlplane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ eResult cControlPlane::init(const std::string& jsonFilePath)
return command_convert(std::get<common::icp::convert::request>(std::get<1>(request)));
});

register_command(common::icp::requestType::counters_stat, [this]() {
return command_counters_stat();
});

if (!jsonFilePath.empty())
{
std::ifstream fromFileStream(jsonFilePath);
Expand Down Expand Up @@ -818,6 +822,11 @@ common::icp::convert::response cControlPlane::command_convert(const common::icp:
return response;
}

common::icp::counters_stat::response cControlPlane::command_counters_stat()
{
return counter_manager.full_stat();
}

common::icp::convert::response cControlPlane::convert_logical_module()
{
common::icp::convert::response response;
Expand Down
1 change: 1 addition & 0 deletions controlplane/controlplane.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class cControlPlane
common::icp::loadConfig::response command_loadConfig(const common::icp::loadConfig::request& request);
common::icp::version::response command_version();
common::icp::convert::response command_convert(const common::icp::convert::request& request);
common::icp::counters_stat::response command_counters_stat();

common::icp::convert::response convert_logical_module();

Expand Down
114 changes: 30 additions & 84 deletions controlplane/counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,108 +3,51 @@
#include <mutex>
#include <set>

#include "segment_allocator.h"
#include "type.h"

#include "common/icp.h"
#include "common/idataplane.h"
#include "common/refarray.h"

class SegmentAllocator
class counter_manager_t
{
public:
SegmentAllocator(size_t start, size_t size, size_t error_result) :
size_(size), error_result_(error_result)
static_assert((uint32_t)common::globalBase::static_counter_type::size <= YANET_CONFIG_COUNTERS_SIZE);

counter_manager_t() :
counter_shifts(YANET_CONFIG_COUNTERS_SIZE, 0)
{
Insert(start, size);
}

size_t Allocate(size_t size)
std::tuple<uint64_t, uint64_t> stats() const
{
auto iter = segments_size_.lower_bound({size, 0});
if (iter == segments_size_.end())
{
return error_result_;
}
size_t index = iter->second;

if (size < iter->first)
{
Insert(index + size, iter->first - size);
}

segments_start_.erase({index, iter->first});
segments_size_.erase(iter);
size_ -= size;

return index;
std::lock_guard<std::mutex> guard(counter_mutex);
return {YANET_CONFIG_COUNTERS_SIZE - allocator.Size(), YANET_CONFIG_COUNTERS_SIZE};
}

bool Free(size_t start, size_t size)
common::icp::counters_stat::response full_stat() const
{
auto iter_right = segments_start_.upper_bound({start, 0});
auto iter_left = (iter_right == segments_start_.begin() ? segments_start_.end() : std::prev(iter_right)); // если тот что справа самый первый, то левее уже никого
std::lock_guard<std::mutex> guard(counter_mutex);

if ((iter_left != segments_start_.end()) && (iter_left->first + iter_left->second > start))
const auto* blocks_stat = allocator.GetBlocksStat();
std::vector<common::icp::counters_stat::one_size_info> sizes_info;
for (uint16_t size = 1; size <= max_buffer_size; size++)
{
return false; // Освобождаем в отрезке который и так свободен
}
else if ((iter_right != segments_start_.end()) && (start + size > iter_right->first))
{
return false; // Освобождаем в отрезке который и так свободен
}

if ((iter_left != segments_start_.end()) && (iter_left->first + iter_left->second == start))
{ // Объединяем с левым сегментом
start = iter_left->first;
size += iter_left->second;
segments_size_.erase({iter_left->second, iter_left->first});
segments_start_.erase(iter_left);
}

if ((iter_right != segments_start_.end()) && (start + size == iter_right->first))
{ // Объединяем с правым сегментом
size += iter_right->second;
segments_size_.erase({iter_right->second, iter_right->first});
segments_start_.erase(iter_right);
const auto& block = blocks_stat[size];
if ((block.used_blocks != 0) || (block.busy_blocks != 0) || (block.used_segments != 0))
{
sizes_info.emplace_back(size, block.used_blocks, block.busy_blocks, block.used_segments);
}
}

Insert(start, size);
size_ += size;
return true;
}

size_t Size() const
{
return size_;
}

private:
std::set<std::pair<size_t, size_t>> segments_start_;
std::set<std::pair<size_t, size_t>> segments_size_;
size_t size_;
size_t error_result_;
auto [errors_external, errors_internal] = allocator.GetErrors();
common::icp::counters_stat::common_info common_info(blocks_stat[0].used_blocks, ///< free_blocks
allocator.Size(), ///< free_cells_
errors_external, ///< errors_external_
errors_internal); ///< errors_internal_

void Insert(size_t start, size_t size)
{
segments_start_.insert({start, size});
segments_size_.insert({size, start});
}
};

class counter_manager_t
{
public:
static_assert((uint32_t)common::globalBase::static_counter_type::size <= YANET_CONFIG_COUNTERS_SIZE);

counter_manager_t() :
counter_shifts(YANET_CONFIG_COUNTERS_SIZE, 0),
allocator((uint32_t)common::globalBase::static_counter_type::size, YANET_CONFIG_COUNTERS_SIZE - (uint32_t)common::globalBase::static_counter_type::size, 0)
{
}

std::tuple<uint64_t, uint64_t> stats() const
{
std::lock_guard<std::mutex> guard(counter_mutex);
return {YANET_CONFIG_COUNTERS_SIZE - allocator.Size(), YANET_CONFIG_COUNTERS_SIZE};
return {common_info, sizes_info};
}

protected:
Expand Down Expand Up @@ -161,10 +104,13 @@ class counter_manager_t
}

protected:
static constexpr uint32_t counter_index_begin = (((uint32_t)common::globalBase::static_counter_type::size + 63) / 64) * 64;
static constexpr uint32_t max_buffer_size = 64;

mutable std::mutex counter_mutex;
interface::dataPlane counter_dataplane;
std::vector<uint64_t> counter_shifts;
SegmentAllocator allocator;
SegmentAllocator<counter_index_begin, YANET_CONFIG_COUNTERS_SIZE, 64 * 64, max_buffer_size, 0> allocator;
};

template<typename key_T,
Expand Down
Loading

0 comments on commit d482fd0

Please sign in to comment.