This commit is contained in:
Alex Hultman
2021-01-28 17:15:05 +01:00
parent 596d7fdfc0
commit af8094268c
2 changed files with 27 additions and 33 deletions
+26 -32
View File
@@ -1,5 +1,5 @@
/* /*
* Authored by Alex Hultman, 2018-2020. * Authored by Alex Hultman, 2018-2021.
* Intellectual property of third-party. * Intellectual property of third-party.
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +28,7 @@
#include <list> #include <list>
#include <cstring> #include <cstring>
/* We use std::function here, not fu2::unique_function */
#include <functional> #include <functional>
namespace uWS { namespace uWS {
@@ -76,19 +77,15 @@ struct Intersection {
std::vector<Hole> holes; std::vector<Hole> holes;
void forSubscriber(Subscriber *s, std::vector<unsigned int> &senderForMessages, std::function<void(std::pair<std::string_view, std::string_view>)> cb) { void forSubscriber(Subscriber *s, std::vector<unsigned int> &senderForMessages, std::function<void(std::pair<std::string_view, std::string_view>)> cb) {
/* How far we already emitted of the two dataChannels */ /* How far we already emitted of the two dataChannels */
std::pair<size_t, size_t> emitted = {}; std::pair<size_t, size_t> emitted = {};
//std::cout << "Subscriber: " << s << std::endl;
/* Holes are global to the entire topic tree, so we are not guaranteed to find /* Holes are global to the entire topic tree, so we are not guaranteed to find
* holes in this intersection - they are sorted, though */ * holes in this intersection - they are sorted, though */
int examinedHoles = 0; int examinedHoles = 0;
/* This is a slow path of sorts, most subscribers will be observers, not active senders */ /* This is a slow path of sorts, most subscribers will be observers, not active senders */
for (unsigned int id : senderForMessages) { for (unsigned int id : senderForMessages) {
//std::cout << "We are sender for id: " << id << std::endl;
std::pair<size_t, size_t> toEmit = {}; std::pair<size_t, size_t> toEmit = {};
std::pair<size_t, size_t> toIgnore = {}; std::pair<size_t, size_t> toIgnore = {};
@@ -135,10 +132,6 @@ struct Intersection {
}; };
struct TopicTree { struct TopicTree {
/* Sender holes */
std::map<Subscriber *, std::vector<unsigned int>> senderHoles;
private: private:
std::function<int(Subscriber *, Intersection &)> cb; std::function<int(Subscriber *, Intersection &)> cb;
@@ -147,6 +140,9 @@ private:
/* Global messageId for deduplication of overlapping topics and ordering between topics */ /* Global messageId for deduplication of overlapping topics and ordering between topics */
unsigned int messageId = 0; unsigned int messageId = 0;
/* Sender holes */
std::map<Subscriber *, std::vector<unsigned int>> senderHoles;
/* The triggered topics */ /* The triggered topics */
Topic *triggeredTopics[64]; Topic *triggeredTopics[64];
int numTriggeredTopics = 0; int numTriggeredTopics = 0;
@@ -269,6 +265,18 @@ public:
delete root; delete root;
} }
/* This is part of the fast path, so should be optimal */
std::vector<unsigned int> &getSenderFor(Subscriber *s) {
static thread_local std::vector<unsigned int> emptyVector;
auto it = senderHoles.find(s);
if (it != senderHoles.end()) {
return it->second;
}
return emptyVector;
}
void subscribe(std::string_view topic, Subscriber *subscriber) { void subscribe(std::string_view topic, Subscriber *subscriber) {
/* Start iterating from the root */ /* Start iterating from the root */
Topic *iterator = root; Topic *iterator = root;
@@ -326,13 +334,13 @@ public:
} }
void publish(std::string_view topic, std::pair<std::string_view, std::string_view> message, Subscriber *sender = nullptr) { void publish(std::string_view topic, std::pair<std::string_view, std::string_view> message, Subscriber *sender = nullptr) {
/* Add a hole for the sender if one */ /* Add a hole for the sender if one */
if (sender) { if (sender) {
senderHoles[sender].push_back(messageId); senderHoles[sender].push_back(messageId);
} }
publish(root, 0, 0, topic, message); publish(root, 0, 0, topic, message);
/* MessageIDs are reset on drain - this should be fine since messages itself are cleared on drain */
messageId++; messageId++;
} }
@@ -421,6 +429,7 @@ public:
if (!numTriggeredTopics) { if (!numTriggeredTopics) {
senderHoles.clear(); senderHoles.clear();
messageId = 0;
return; return;
} }
@@ -436,7 +445,7 @@ public:
if (min != (Subscriber *)UINTPTR_MAX) { if (min != (Subscriber *)UINTPTR_MAX) {
/* Up to 64 triggered Topics per batch */ /* Up to 64 triggered Topics per batch */
std::map<uint64_t, /*std::pair<std::string, std::string>*/ Intersection> intersectionCache; std::map<uint64_t, Intersection> intersectionCache;
/* Loop over these here */ /* Loop over these here */
std::set<Subscriber *>::iterator it[64]; std::set<Subscriber *>::iterator it[64];
@@ -492,20 +501,14 @@ public:
} }
/* Create the linear cache, {inflated, deflated} */ /* Create the linear cache, {inflated, deflated} */
/*std::pair<std::string, std::string>*/ Intersection res; Intersection res;
//std::string messageIds; // sorterade id:n för meddelanden
//std::vector<
for (auto &p : complete) { for (auto &p : complete) {
//printf("messageId = %d\n", p.first);
res.dataChannels.first.append(p.second.first); res.dataChannels.first.append(p.second.first);
res.dataChannels.second.append(p.second.second); res.dataChannels.second.append(p.second.second);
// appenda {id, längd, längd} /* Appends {id, length, length}
* We could possibly append byte offset also,
* if we want to use log2 search later. */
Hole h; Hole h;
h.lengths.first = p.second.first.length(); h.lengths.first = p.second.first.length();
h.lengths.second = p.second.second.length(); h.lengths.second = p.second.second.length();
@@ -513,24 +516,14 @@ public:
res.holes.push_back(h); res.holes.push_back(h);
} }
//can we know the messageId here and lookup if "min" is the sender?
cb(min, intersectionCache[intersection] = std::move(res)); cb(min, intersectionCache[intersection] = std::move(res));
} }
else { else {
// vi kan göra en cache som håller inflated, deflated, messageIds
// sen, för varje subscriber, kollar vi upp en vektor av messageIds - senderHoles
// sen måste vi loopa över
cb(min, intersectionCache[intersection]); cb(min, intersectionCache[intersection]);
} }
min = nextMin; min = nextMin;
} }
} }
/* Clear messages of triggered Topics */ /* Clear messages of triggered Topics */
@@ -540,6 +533,7 @@ public:
} }
numTriggeredTopics = 0; numTriggeredTopics = 0;
senderHoles.clear(); senderHoles.clear();
messageId = 0;
} }
}; };
+1 -1
View File
@@ -19,7 +19,7 @@ void testCorrectness() {
topicTree = new uWS::TopicTree([&topicTree, &actualResult](uWS::Subscriber *s, uWS::Intersection &intersection) { topicTree = new uWS::TopicTree([&topicTree, &actualResult](uWS::Subscriber *s, uWS::Intersection &intersection) {
intersection.forSubscriber(s, topicTree->senderHoles[s], [s, &actualResult](std::pair<std::string_view, std::string_view> dataChannels) { intersection.forSubscriber(s, topicTree->getSenderFor(s), [s, &actualResult](std::pair<std::string_view, std::string_view> dataChannels) {
actualResult[s].first += dataChannels.first; actualResult[s].first += dataChannels.first;
actualResult[s].second += dataChannels.second; actualResult[s].second += dataChannels.second;
}); });