Replace map with unordered_map nearly everywhere, for speed.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 7 Apr 2018 09:14:51 +0000 (11:14 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 7 Apr 2018 09:15:01 +0000 (11:15 +0200)
config.cpp
httpinput.cpp
main.cpp
parse.cpp
parse.h
server.cpp
server.h

index 5a1fdd9..21e17c9 100644 (file)
@@ -7,9 +7,9 @@
 #include <string.h>
 #include <net/if.h>
 #include <sys/socket.h>
-#include <map>
 #include <string>
 #include <utility>
+#include <unordered_map>
 #include <vector>
 
 #include "tlse.h"
@@ -26,7 +26,7 @@ using namespace std;
 struct ConfigLine {
        string keyword;
        vector<string> arguments;
-       map<string, string> parameters;
+       unordered_map<string, string> parameters;
 };
 
 namespace {
@@ -211,7 +211,7 @@ bool load_file_to_string(const string &filename, size_t max_size, string *conten
        return true;
 }
 
-bool parse_tls_parameters(const map<string, string> &parameters, AcceptorConfig *acceptor)
+bool parse_tls_parameters(const unordered_map<string, string> &parameters, AcceptorConfig *acceptor)
 {
        bool has_cert = false, has_key = false;
 
index b969596..7967c76 100644 (file)
@@ -249,7 +249,7 @@ bool HTTPInput::parse_response(const string &request)
                return false;
        }
 
-       multimap<string, string> parameters = extract_headers(lines, url);
+       unordered_multimap<string, string> parameters = extract_headers(lines, url);
 
        // Remove “Content-encoding: metacube”.
        // TODO: Make case-insensitive.
index fc36861..7da6650 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -15,6 +15,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -445,7 +446,7 @@ start:
                serialize_start.tv_nsec = loaded_state.serialize_start_usec() * 1000ull;
 
                // Deserialize the streams.
-               map<string, string> stream_headers_for_url;  // See below.
+               unordered_map<string, string> stream_headers_for_url;  // See below.
                for (const StreamProto &stream : loaded_state.streams()) {
                        if (all_urls.count(stream.url()) == 0) {
                                // Delete the stream backlogs.
index f4c78fc..bec742b 100644 (file)
--- a/parse.cpp
+++ b/parse.cpp
@@ -56,9 +56,9 @@ vector<string> split_lines(const string &str)
        return ret;
 }
 
-multimap<string, string> extract_headers(const vector<string> &lines, const string &log_context)
+unordered_multimap<string, string> extract_headers(const vector<string> &lines, const string &log_context)
 {
-       multimap<string, string> parameters;
+       unordered_multimap<string, string> parameters;
        for (size_t i = 1; i < lines.size(); ++i) {
                size_t split = lines[i].find(":");
                if (split == string::npos) {
diff --git a/parse.h b/parse.h
index a56b1f4..1924cc0 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -4,8 +4,8 @@
 // Various routines that deal with parsing; both HTTP requests and more generic text.
 
 #include <stddef.h>
-#include <map>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 // Split a line on whitespace, e.g. "foo  bar baz" -> {"foo", "bar", "baz"}.
@@ -16,7 +16,7 @@ std::vector<std::string> split_lines(const std::string &str);
 
 // Extract HTTP headers from a request or response. Ignores the first line,
 // where the verb or the return code is.
-std::multimap<std::string, std::string> extract_headers(
+std::unordered_multimap<std::string, std::string> extract_headers(
        const std::vector<std::string> &lines, const std::string &log_context);
 
 // Add the new data to an existing string, looking for \r\n\r\n
index a7f579c..be583e4 100644 (file)
@@ -301,7 +301,7 @@ void Server::add_client_from_serialized(const ClientProto &client, const vector<
 
 int Server::lookup_stream_by_url(const string &url) const
 {
-       map<string, int>::const_iterator stream_url_it = stream_url_map.find(url);
+       const auto stream_url_it = stream_url_map.find(url);
        if (stream_url_it == stream_url_map.end()) {
                return -1;
        }
@@ -910,12 +910,12 @@ int Server::parse_request(Client *client)
 
        // Parse the headers, for logging purposes.
        // TODO: Case-insensitivity.
-       multimap<string, string> headers = extract_headers(lines, client->remote_addr);
-       multimap<string, string>::const_iterator referer_it = headers.find("Referer");
+       unordered_multimap<string, string> headers = extract_headers(lines, client->remote_addr);
+       const auto referer_it = headers.find("Referer");
        if (referer_it != headers.end()) {
                client->referer = referer_it->second;
        }
-       multimap<string, string>::const_iterator user_agent_it = headers.find("User-Agent");
+       const auto user_agent_it = headers.find("User-Agent");
        if (user_agent_it != headers.end()) {
                client->user_agent = user_agent_it->second;
        }
@@ -985,25 +985,25 @@ int Server::parse_request(Client *client)
                client->close_after_response = true;
                client->http_11 = false;
        } else {
-               multimap<string, string>::const_iterator connection_it = headers.find("Connection");
+               const auto connection_it = headers.find("Connection");
                if (connection_it != headers.end() && connection_it->second == "close") {
                        client->close_after_response = true;
                }
        }
 
-       map<string, int>::const_iterator stream_url_map_it = stream_url_map.find(url);
+       const auto stream_url_map_it = stream_url_map.find(url);
        if (stream_url_map_it != stream_url_map.end()) {
                // Serve a regular stream..
                client->stream = streams[stream_url_map_it->second].get();
                client->serving_hls_playlist = false;
        } else {
-               map<string, int>::const_iterator stream_hls_url_map_it = stream_hls_url_map.find(url);
+               const auto stream_hls_url_map_it = stream_hls_url_map.find(url);
                if (stream_hls_url_map_it != stream_hls_url_map.end()) {
                        // Serve HLS playlist.
                        client->stream = streams[stream_hls_url_map_it->second].get();
                        client->serving_hls_playlist = true;
                } else {
-                       map<string, string>::const_iterator ping_url_map_it = ping_url_map.find(url);
+                       const auto ping_url_map_it = ping_url_map.find(url);
                        if (ping_url_map_it == ping_url_map.end()) {
                                return 404;  // Not found.
                        } else {
@@ -1166,7 +1166,7 @@ void Server::construct_hls_playlist(Client *client)
 
 void Server::construct_204(Client *client)
 {
-       map<string, string>::const_iterator ping_url_map_it = ping_url_map.find(client->url);
+       const auto ping_url_map_it = ping_url_map.find(client->url);
        assert(ping_url_map_it != ping_url_map.end());
 
        string response;
index da20764..4ec908b 100644 (file)
--- a/server.h
+++ b/server.h
@@ -6,11 +6,11 @@
 #include <sys/epoll.h>
 #include <sys/types.h>
 #include <time.h>
-#include <map>
 #include <memory>
 #include <mutex>
 #include <queue>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #include "tlse.h"
@@ -106,13 +106,13 @@ private:
        std::vector<std::unique_ptr<Stream>> streams;
 
        // Map from URL to index into <streams>.
-       std::map<std::string, int> stream_url_map, stream_hls_url_map;
+       std::unordered_map<std::string, int> stream_url_map, stream_hls_url_map;
 
        // Map from URL to CORS Allow-Origin header (or empty string).
-       std::map<std::string, std::string> ping_url_map;
+       std::unordered_map<std::string, std::string> ping_url_map;
 
        // Map from file descriptor to client.
-       std::map<int, Client> clients;
+       std::unordered_map<int, Client> clients;
 
        // A list of all clients, ordered by the time they connected (first element),
        // and their file descriptor (second element). It is ordered by connection time
@@ -132,7 +132,7 @@ private:
        epoll_event events[EPOLL_MAX_EVENTS];
 
        // For each TLS-enabled acceptor, our private server context for its key pair.
-       std::map<const Acceptor *, TLSContext *> tls_server_contexts;
+       std::unordered_map<const Acceptor *, TLSContext *> tls_server_contexts;
 
        // The actual worker thread.
        virtual void do_work();