diff --git src/cc/usdt.h src/cc/usdt.h index 1e1ac7c6..dcfc2409 100644 --- src/cc/usdt.h +++ src/cc/usdt.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "bcc_proc.h" #include "syms.h" @@ -31,6 +32,17 @@ namespace ebpf { class USDT; } +template<> +struct std::hash> +{ + std::size_t operator()(const std::pair& s) const noexcept + { + std::size_t h1 = std::hash{}(s.first); + std::size_t h2 = std::hash{}(s.second); + return h1 ^ (h2 << 1); // or use boost::hash_combine + } +}; + namespace USDT { using std::experimental::optional; @@ -298,6 +310,7 @@ public: class Context { std::vector> probes_; + std::unordered_map, Probe*> probe_index_; std::unordered_set modules_; optional pid_; diff --git src/cc/usdt/usdt.cc src/cc/usdt/usdt.cc index f36bf75e..0d8e977b 100644 --- src/cc/usdt/usdt.cc +++ src/cc/usdt/usdt.cc @@ -275,18 +275,20 @@ int Context::_each_module(mod_info *mod, int enter_ns, void *p) { } void Context::add_probe(const char *binpath, const struct bcc_elf_usdt *probe) { - for (auto &p : probes_) { - if (p->provider_ == probe->provider && p->name_ == probe->name) { - p->add_location(probe->pc, binpath, probe->arg_fmt); - return; - } - } - - probes_.emplace_back( - new Probe(binpath, probe->provider, probe->name, probe->semaphore, - probe->semaphore_offset, pid_, mod_match_inode_only_) - ); - probes_.back()->add_location(probe->pc, binpath, probe->arg_fmt); + // Lookup for existing probe in the index. + auto key = std::make_pair(probe->provider, probe->name); + auto it = probe_index_.find(key); + if (it == probe_index_.end()) { + // No existing probe, create a new one... + auto &new_probe = probes_.emplace_back(std::make_unique( + binpath, probe->provider, probe->name, probe->semaphore, + probe->semaphore_offset, pid_, mod_match_inode_only_ + )); + // ...and add it to the index. + it = probe_index_.emplace(key, new_probe.get()).first; + } + // Add the location to the probe. + it->second->add_location(probe->pc, binpath, probe->arg_fmt); } std::string Context::resolve_bin_path(const std::string &bin_path) { @@ -317,10 +319,9 @@ Probe *Context::get(const std::string &probe_name) { Probe *Context::get(const std::string &provider_name, const std::string &probe_name) { - for (auto &p : probes_) { - if (p->provider_ == provider_name && p->name_ == probe_name) - return p.get(); - } + if (auto it = probe_index_.find(std::make_pair(provider_name, probe_name)); + it != probe_index_.end()) + return it->second; return nullptr; }