Skip to content

Commit 92657cf

Browse files
committed
implement input send cache. to cooldown the hot path in addpendinginput
1 parent 460481c commit 92657cf

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

GekkoLib/include/backend.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,13 @@ namespace Gekko {
191191
std::vector<u8> _bin_buffer;
192192

193193
u64 _last_sent_network_check;
194+
195+
struct InputCache {
196+
bool outdated = true;
197+
std::vector<InputMsg> input;
198+
};
199+
200+
InputCache player_input_cache;
201+
InputCache spectator_input_cache;
194202
};
195203
}

GekkoLib/src/backend.cpp

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ void Gekko::MessageSystem::AddInput(Frame input_frame, Handle player, u8 input[]
5151
input_q.last_added_input++;
5252
input_q.inputs.push_back(std::make_unique<u8[]>(_input_size));
5353
std::memcpy(input_q.inputs.back().get(), input, _input_size);
54+
player_input_cache.outdated = true;
5455

5556
// update history // TODO REDO WITH BACKEND REWORK..
5657
if (!remote) {
@@ -73,6 +74,7 @@ void Gekko::MessageSystem::AddSpectatorInput(Frame input_frame, u8 input[])
7374
const size_t num_players = locals.size() + remotes.size();
7475
input_q.inputs.push_back(std::make_unique<u8[]>(_input_size * num_players));
7576
std::memcpy(input_q.inputs.back().get(), input, _input_size * num_players);
77+
spectator_input_cache.outdated = true;
7678
}
7779

7880
// move the input queues along
@@ -725,17 +727,35 @@ void Gekko::MessageSystem::AddPendingInput(bool spectator)
725727
{
726728
const u32 MAX_INPUT_SIZE = 512;
727729

730+
const auto packet_type = spectator ? SpectatorInputs : Inputs;
731+
auto& input_cache = spectator ? spectator_input_cache : player_input_cache;
732+
auto& queue = spectator ? _net_spectator_queue : _net_player_queue[locals[0]->handle];
733+
728734
const u32 num_players = spectator ? _num_players : (u32)locals.size();
729735
const u32 inputs_per_packet = MAX_INPUT_SIZE / (_input_size * num_players);
730-
731-
auto& queue = spectator ? _net_spectator_queue : _net_player_queue[locals[0]->handle];
732736
const u32 q_size = (u32)queue.inputs.size();
733737

734738
if (q_size == 0) return;
735739

740+
// check if cache is valid and can be reused
741+
if (!input_cache.outdated && !input_cache.input.empty()) {
742+
// reuse cached packets, just copy from cache
743+
for (const auto& cached_msg : input_cache.input) {
744+
_pending_output.push(std::make_unique<NetData>());
745+
auto& packet = _pending_output.back();
746+
packet->pkt.header.type = packet_type;
747+
auto message = std::make_unique<InputMsg>();
748+
message->Copy(&cached_msg);
749+
packet->pkt.body = std::move(message);
750+
}
751+
return;
752+
}
753+
754+
// cache is outdated, rebuild packets
755+
input_cache.input.clear();
756+
736757
const u32 packet_count = (q_size + inputs_per_packet - 1) / inputs_per_packet;
737758
const Frame start_frame = queue.last_added_input - q_size + 1;
738-
const auto packet_type = spectator ? SpectatorInputs : Inputs;
739759

740760
for (u32 pc = 0; pc < packet_count; pc++) {
741761
const u32 input_start_idx = pc * inputs_per_packet;
@@ -745,29 +765,41 @@ void Gekko::MessageSystem::AddPendingInput(bool spectator)
745765
_pending_output.push(std::make_unique<NetData>());
746766
auto& packet = _pending_output.back();
747767
packet->pkt.header.type = packet_type;
748-
749768
auto message = std::make_unique<InputMsg>();
750769
message->start_frame = start_frame + input_start_idx;
751770

752771
if (spectator) {
753772
for (u32 i = input_start_idx; i < input_end_idx; i++) {
754773
const auto& p_input = queue.inputs.at(i);
755-
message->inputs.insert(message->inputs.end(), p_input.get(), p_input.get() + _input_size * num_players);
774+
message->inputs.insert(message->inputs.end(),
775+
p_input.get(),
776+
p_input.get() + _input_size * num_players);
756777
}
757-
} else {
778+
}
779+
else {
758780
for (u32 player = 0; player < num_players; player++) {
759781
const auto& player_queue = _net_player_queue[locals[player]->handle];
760782
for (u32 i = input_start_idx; i < input_end_idx; i++) {
761783
const auto& p_input = player_queue.inputs.at(i);
762-
message->inputs.insert(message->inputs.end(), p_input.get(), p_input.get() + _input_size);
784+
message->inputs.insert(message->inputs.end(),
785+
p_input.get(),
786+
p_input.get() + _input_size);
763787
}
764788
}
765789
}
766790

767791
message->total_size = (u16)message->inputs.size();
768792
message->input_count = input_count;
793+
794+
// cache this message before moving it
795+
InputMsg cached_msg;
796+
cached_msg.Copy(message.get());
797+
input_cache.input.push_back(std::move(cached_msg));
798+
769799
packet->pkt.body = std::move(message);
770800
}
801+
// mark cache as valid
802+
input_cache.outdated = false;
771803
}
772804

773805
void Gekko::AdvantageHistory::Init()

0 commit comments

Comments
 (0)