impl new acceleration structure for components, not exploited yet

disable funky load at first msg
This commit is contained in:
Green Sky 2024-02-28 18:34:26 +01:00
parent 52e95ca654
commit 89f065a610
No known key found for this signature in database

View File

@ -10,6 +10,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <algorithm>
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <cassert> #include <cassert>
@ -17,6 +18,8 @@
// https://youtu.be/CU2exyhYPfA // https://youtu.be/CU2exyhYPfA
// everything assumes a single fragment registry
namespace Message::Components { namespace Message::Components {
// ctx // ctx
@ -32,9 +35,23 @@ namespace Message::Components {
// all message fragments of this contact // all message fragments of this contact
struct ContactFragments final { struct ContactFragments final {
// kept up-to-date by events // kept up-to-date by events
entt::dense_set<FragmentID> frags; //entt::dense_set<FragmentID> frags;
struct InternalEntry {
// indecies into the sorted arrays
size_t i_b;
size_t i_e;
};
entt::dense_map<FragmentID, InternalEntry> frags;
// add 2 sorted contact lists for both range begin and end // add 2 sorted contact lists for both range begin and end
std::vector<FragmentID> sorted_begin;
std::vector<FragmentID> sorted_end;
// api
// return true if it was actually inserted
bool insert(FragmentHandle frag);
bool erase(FragmentID frag);
// update? (just erase() + insert())
}; };
// all LOADED message fragments // all LOADED message fragments
@ -78,12 +95,13 @@ void MessageFragmentStore::handleMessage(const Message3Handle& m) {
if (!m.registry()->ctx().contains<Message::Components::OpenFragments>()) { if (!m.registry()->ctx().contains<Message::Components::OpenFragments>()) {
m.registry()->ctx().emplace<Message::Components::OpenFragments>(); m.registry()->ctx().emplace<Message::Components::OpenFragments>();
#if 0
// TODO: move this to async // TODO: move this to async
// TODO: move this to tick and just respect the dirty // TODO: move this to tick and just respect the dirty
FragmentHandle most_recent_fag; FragmentHandle most_recent_fag;
uint64_t most_recent_ts{0}; uint64_t most_recent_ts{0};
if (m.registry()->ctx().contains<Message::Components::ContactFragments>()) { if (m.registry()->ctx().contains<Message::Components::ContactFragments>()) {
for (const auto fid : m.registry()->ctx().get<Message::Components::ContactFragments>().frags) { for (const auto& [fid, si] : m.registry()->ctx().get<Message::Components::ContactFragments>().frags) {
auto fh = _fs.fragmentHandle(fid); auto fh = _fs.fragmentHandle(fid);
if (!static_cast<bool>(fh) || !fh.all_of<FragComp::MessagesTSRange, FragComp::MessagesContact>()) { if (!static_cast<bool>(fh) || !fh.all_of<FragComp::MessagesTSRange, FragComp::MessagesContact>()) {
// TODO: remove at this point? // TODO: remove at this point?
@ -92,6 +110,7 @@ void MessageFragmentStore::handleMessage(const Message3Handle& m) {
const uint64_t f_ts = fh.get<FragComp::MessagesTSRange>().begin; const uint64_t f_ts = fh.get<FragComp::MessagesTSRange>().begin;
if (f_ts > most_recent_ts) { if (f_ts > most_recent_ts) {
// this makes no sense, we retry to load the first fragment on every new message and bail here, bc it was already
if (m.registry()->ctx().contains<Message::Components::LoadedContactFragments>()) { if (m.registry()->ctx().contains<Message::Components::LoadedContactFragments>()) {
if (m.registry()->ctx().get<Message::Components::LoadedContactFragments>().frags.contains(fh)) { if (m.registry()->ctx().get<Message::Components::LoadedContactFragments>().frags.contains(fh)) {
continue; // already loaded continue; // already loaded
@ -106,6 +125,7 @@ void MessageFragmentStore::handleMessage(const Message3Handle& m) {
if (static_cast<bool>(most_recent_fag)) { if (static_cast<bool>(most_recent_fag)) {
loadFragment(*m.registry(), most_recent_fag); loadFragment(*m.registry(), most_recent_fag);
} }
#endif
} }
auto& fuid_open = m.registry()->ctx().get<Message::Components::OpenFragments>().fuid_open; auto& fuid_open = m.registry()->ctx().get<Message::Components::OpenFragments>().fuid_open;
@ -193,7 +213,7 @@ void MessageFragmentStore::handleMessage(const Message3Handle& m) {
if (!m.registry()->ctx().contains<Message::Components::ContactFragments>()) { if (!m.registry()->ctx().contains<Message::Components::ContactFragments>()) {
m.registry()->ctx().emplace<Message::Components::ContactFragments>(); m.registry()->ctx().emplace<Message::Components::ContactFragments>();
} }
m.registry()->ctx().get<Message::Components::ContactFragments>().frags.emplace(fh); m.registry()->ctx().get<Message::Components::ContactFragments>().insert(fh);
// loaded contact frag // loaded contact frag
if (!m.registry()->ctx().contains<Message::Components::LoadedContactFragments>()) { if (!m.registry()->ctx().contains<Message::Components::LoadedContactFragments>()) {
@ -252,7 +272,7 @@ void MessageFragmentStore::loadFragment(Message3Registry& reg, FragmentHandle fh
if (!reg.ctx().contains<Message::Components::ContactFragments>()) { if (!reg.ctx().contains<Message::Components::ContactFragments>()) {
reg.ctx().emplace<Message::Components::ContactFragments>(); reg.ctx().emplace<Message::Components::ContactFragments>();
} }
reg.ctx().get<Message::Components::ContactFragments>().frags.emplace(fh); reg.ctx().get<Message::Components::ContactFragments>().insert(fh);
// mark loaded // mark loaded
if (!reg.ctx().contains<Message::Components::LoadedContactFragments>()) { if (!reg.ctx().contains<Message::Components::LoadedContactFragments>()) {
@ -535,7 +555,7 @@ float MessageFragmentStore::tick(float time_delta) {
} }
const auto& loaded_frags = msg_reg->ctx().get<Message::Components::LoadedContactFragments>().frags; const auto& loaded_frags = msg_reg->ctx().get<Message::Components::LoadedContactFragments>().frags;
for (const FragmentID fid : msg_reg->ctx().get<Message::Components::ContactFragments>().frags) { for (const auto& [fid, si] : msg_reg->ctx().get<Message::Components::ContactFragments>().frags) {
if (loaded_frags.contains(fid)) { if (loaded_frags.contains(fid)) {
continue; continue;
} }
@ -545,14 +565,14 @@ float MessageFragmentStore::tick(float time_delta) {
if (!static_cast<bool>(fh)) { if (!static_cast<bool>(fh)) {
std::cerr << "MFS error: frag is invalid\n"; std::cerr << "MFS error: frag is invalid\n";
// WHAT // WHAT
msg_reg->ctx().get<Message::Components::ContactFragments>().frags.erase(fid); msg_reg->ctx().get<Message::Components::ContactFragments>().erase(fid);
return 0.05f; return 0.05f;
} }
if (!fh.all_of<FragComp::MessagesTSRange>()) { if (!fh.all_of<FragComp::MessagesTSRange>()) {
std::cerr << "MFS error: frag has no range\n"; std::cerr << "MFS error: frag has no range\n";
// ???? // ????
msg_reg->ctx().get<Message::Components::ContactFragments>().frags.erase(fid); msg_reg->ctx().get<Message::Components::ContactFragments>().erase(fid);
return 0.05f; return 0.05f;
} }
@ -585,7 +605,7 @@ float MessageFragmentStore::tick(float time_delta) {
uint64_t frag_oldest_ts {}; uint64_t frag_oldest_ts {};
// find newest frag in range // find newest frag in range
for (const FragmentID fid : msg_reg->ctx().get<Message::Components::ContactFragments>().frags) { for (const auto& [fid, si] : msg_reg->ctx().get<Message::Components::ContactFragments>().frags) {
// we want to find the last and first fragment of the range (if not all hits are loaded, we did something wrong) // we want to find the last and first fragment of the range (if not all hits are loaded, we did something wrong)
if (!loaded_frags.contains(fid)) { if (!loaded_frags.contains(fid)) {
continue; continue;
@ -867,10 +887,92 @@ bool MessageFragmentStore::onEvent(const Fragment::Events::FragmentConstruct& e)
if (!msg_reg->ctx().contains<Message::Components::ContactFragments>()) { if (!msg_reg->ctx().contains<Message::Components::ContactFragments>()) {
msg_reg->ctx().emplace<Message::Components::ContactFragments>(); msg_reg->ctx().emplace<Message::Components::ContactFragments>();
} }
msg_reg->ctx().get<Message::Components::ContactFragments>().frags.emplace(e.e); msg_reg->ctx().get<Message::Components::ContactFragments>().insert(e.e);
_event_check_queue.push(ECQueueEntry{e.e, frag_contact}); _event_check_queue.push(ECQueueEntry{e.e, frag_contact});
return false; return false;
} }
bool Message::Components::ContactFragments::insert(FragmentHandle frag) {
if (frags.contains(frag)) {
return false;
}
// both sorted arrays are sorted ascending
// so for insertion we search for the last index that is <= and insert after it
// or we search for the first > (or end) and insert before it <---
// since equal fragments are UB, we can assume they are only > or <
size_t begin_index {0};
{ // begin
const auto pos = std::find_if(
sorted_begin.cbegin(),
sorted_begin.cend(),
[frag](const FragmentID a) -> bool {
const auto begin_a = frag.registry()->get<FragComp::MessagesTSRange>(a).begin;
const auto begin_frag = frag.get<FragComp::MessagesTSRange>().begin;
if (begin_a > begin_frag) {
return true;
} else if (begin_a < begin_frag) {
return false;
} else {
// equal ts, we need to fall back to id (id can not be equal)
return isLess(frag.get<FragComp::ID>().v, frag.registry()->get<FragComp::ID>(a).v);
}
}
);
begin_index = std::distance(sorted_begin.cbegin(), pos);
// we need to insert before pos (end is valid here)
sorted_begin.insert(pos, frag);
}
size_t end_index {0};
{ // end
const auto pos = std::find_if_not(
sorted_end.cbegin(),
sorted_end.cend(),
[frag](const FragmentID a) -> bool {
const auto end_a = frag.registry()->get<FragComp::MessagesTSRange>(a).end;
const auto end_frag = frag.get<FragComp::MessagesTSRange>().end;
if (end_a > end_frag) {
return true;
} else if (end_a < end_frag) {
return false;
} else {
// equal ts, we need to fall back to id (id can not be equal)
return isLess(frag.get<FragComp::ID>().v, frag.registry()->get<FragComp::ID>(a).v);
}
}
);
end_index = std::distance(sorted_end.cbegin(), pos);
// we need to insert before pos (end is valid here)
sorted_end.insert(pos, frag);
}
frags.emplace(frag, InternalEntry{begin_index, end_index});
return true;
}
bool Message::Components::ContactFragments::erase(FragmentID frag) {
auto frags_it = frags.find(frag);
if (frags_it == frags.end()) {
return false;
}
assert(sorted_begin.size() == sorted_end.size());
assert(sorted_begin.size() > frags_it->second.i_b);
sorted_begin.erase(sorted_begin.begin() + frags_it->second.i_b);
sorted_end.erase(sorted_end.begin() + frags_it->second.i_e);
frags.erase(frags_it);
return true;
}