You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2018/09/27 18:59:49 UTC
[mesos] 03/10: Added a ScalarResourceQuantities type to improve
sorters performance.
This is an automated email from the ASF dual-hosted git repository.
bmahler pushed a commit to branch 1.7.x
in repository https://gitbox.apache.org/repos/asf/mesos.git
commit c3f32c5a45aa6b326328f77a1ae546ee7fd18a93
Author: Benjamin Mahler <bm...@apache.org>
AuthorDate: Sun Sep 16 16:37:38 2018 -0700
Added a ScalarResourceQuantities type to improve sorters performance.
This type replaces the use of hashmaps keyed by resource names in
favor of storing vectors of `pair<string,Value::Scalar>`, in order
to avoid the performance penalty of using hashmaps.
Running *HierarchicalAllocator_BENCHMARK_Test.DeclineOffers/21 shows
the following improvement:
Using 10000 agents and 1000 frameworks
Added 1000 frameworks in 42.49ms -> 42.85ms (no change)
Added 10000 agents in 7.69secs -> 4.89secs (normalized: 1 -> 0.64)
round 0 allocate() took 5.42secs -> 3.53secs (nomralized: 1 -> 0.65)
Review: https://reviews.apache.org/r/68731
---
src/master/allocator/sorter/drf/sorter.hpp | 26 ++++-----
src/master/allocator/sorter/random/sorter.hpp | 26 ++++-----
src/master/allocator/sorter/sorter.hpp | 84 +++++++++++++++++++++++++++
3 files changed, 108 insertions(+), 28 deletions(-)
diff --git a/src/master/allocator/sorter/drf/sorter.hpp b/src/master/allocator/sorter/drf/sorter.hpp
index 71352c8..2957a2e 100644
--- a/src/master/allocator/sorter/drf/sorter.hpp
+++ b/src/master/allocator/sorter/drf/sorter.hpp
@@ -169,14 +169,13 @@ private:
// identities of resources and not quantities.
Resources scalarQuantities;
- // We also store a map version of `scalarQuantities`, mapping
- // the `Resource::name` to aggregated scalar. This improves the
- // performance of calculating shares. See MESOS-4694.
+ // To improve the performance of calculating shares, we store
+ // a redundant but more efficient version of `scalarQuantities`.
+ // See MESOS-4694.
//
- // TODO(bmahler): Ideally we do not store `scalarQuantities`
- // redundantly here, investigate performance improvements to
- // `Resources` to make this unnecessary.
- hashmap<std::string, Value::Scalar> totals;
+ // TODO(bmahler): Can we remove `scalarQuantities` in favor of
+ // using this type whenever scalar quantities are needed?
+ ScalarResourceQuantities totals;
} total_;
// Metrics are optionally exposed by the sorter.
@@ -430,14 +429,13 @@ struct DRFSorter::Node
// the corresponding resource. See notes above.
Resources scalarQuantities;
- // We also store a map version of `scalarQuantities`, mapping
- // the `Resource::name` to aggregated scalar. This improves the
- // performance of calculating shares. See MESOS-4694.
+ // To improve the performance of calculating shares, we store
+ // a redundant but more efficient version of `scalarQuantities`.
+ // See MESOS-4694.
//
- // TODO(bmahler): Ideally we do not store `scalarQuantities`
- // redundantly here, investigate performance improvements to
- // `Resources` to make this unnecessary.
- hashmap<std::string, Value::Scalar> totals;
+ // TODO(bmahler): Can we remove `scalarQuantities` in favor of
+ // using this type whenever scalar quantities are needed?
+ ScalarResourceQuantities totals;
} allocation;
// Compares two nodes according to DRF share.
diff --git a/src/master/allocator/sorter/random/sorter.hpp b/src/master/allocator/sorter/random/sorter.hpp
index 6bfeda0..825c158 100644
--- a/src/master/allocator/sorter/random/sorter.hpp
+++ b/src/master/allocator/sorter/random/sorter.hpp
@@ -167,14 +167,13 @@ private:
// identities of resources and not quantities.
Resources scalarQuantities;
- // We also store a map version of `scalarQuantities`, mapping
- // the `Resource::name` to aggregated scalar. This improves the
- // performance of calculating shares. See MESOS-4694.
+ // To improve the performance of calculating shares, we store
+ // a redundant but more efficient version of `scalarQuantities`.
+ // See MESOS-4694.
//
- // TODO(bmahler): Ideally we do not store `scalarQuantities`
- // redundantly here, investigate performance improvements to
- // `Resources` to make this unnecessary.
- hashmap<std::string, Value::Scalar> totals;
+ // TODO(bmahler): Can we remove `scalarQuantities` in favor of
+ // using this type whenever scalar quantities are needed?
+ ScalarResourceQuantities totals;
} total_;
};
@@ -406,14 +405,13 @@ struct RandomSorter::Node
// the corresponding resource. See notes above.
Resources scalarQuantities;
- // We also store a map version of `scalarQuantities`, mapping
- // the `Resource::name` to aggregated scalar. This improves the
- // performance of calculating shares. See MESOS-4694.
+ // To improve the performance of calculating shares, we store
+ // a redundant but more efficient version of `scalarQuantities`.
+ // See MESOS-4694.
//
- // TODO(bmahler): Ideally we do not store `scalarQuantities`
- // redundantly here, investigate performance improvements to
- // `Resources` to make this unnecessary.
- hashmap<std::string, Value::Scalar> totals;
+ // TODO(bmahler): Can we remove `scalarQuantities` in favor of
+ // using this type whenever scalar quantities are needed?
+ ScalarResourceQuantities totals;
} allocation;
};
diff --git a/src/master/allocator/sorter/sorter.hpp b/src/master/allocator/sorter/sorter.hpp
index 432ccfe..68cf698 100644
--- a/src/master/allocator/sorter/sorter.hpp
+++ b/src/master/allocator/sorter/sorter.hpp
@@ -19,6 +19,7 @@
#include <functional>
#include <string>
+#include <utility>
#include <vector>
#include <mesos/resources.hpp>
@@ -148,6 +149,89 @@ public:
virtual size_t count() const = 0;
};
+// Efficient type for scalar resource quantities that avoids
+// the overhead of using `Resources`.
+//
+// TODO(bmahler): This was originally added to replace a
+// `hashmap<string, Scalar>` and hence the interface was
+// tailored to the particular usage of the map. In order
+// to move this up as a replacement of all quantities
+// (e.g. `Resources::createStrippedScalarQuantity()`),
+// this will need more functionality to do so (e.g.
+// arithmetic operators, containment check, etc).
+class ScalarResourceQuantities
+{
+public:
+ ScalarResourceQuantities()
+ {
+ // Pre-reserve space for first-class scalars.
+ quantities.reserve(4u); // [cpus, disk, gpus, mem]
+ }
+
+ // Returns true if there is a non-zero amount of
+ // the specified resource.
+ bool contains(const std::string& name) const
+ {
+ // Don't bother binary searching since we don't expect
+ // a large number of quantities.
+ foreach (auto& quantity, quantities) {
+ if (quantity.first == name) {
+ return quantity.second.value() > 0.0;
+ }
+ }
+
+ return false;
+ }
+
+ const Value::Scalar& at(const std::string& name) const
+ {
+ // Don't bother binary searching since we don't expect
+ // a large number of quantities.
+ foreach (auto& quantity, quantities) {
+ if (quantity.first == name) {
+ return quantity.second;
+ }
+ }
+
+ // TODO(bmahler): Print out the vector, need to add
+ // a `stringify(const pair<T1, T2>& p)` overload.
+ LOG(FATAL) << "Failed to find '" << name << "'";
+ }
+
+ Value::Scalar& operator[](const std::string& name)
+ {
+ // Find the location to insert while maintaining
+ // alphabetical ordering. Don't bother binary searching
+ // since we don't expect a large number of quantities.
+ auto it = quantities.begin();
+ for (; it != quantities.end(); ++it) {
+ if (it->first == name) {
+ return it->second;
+ }
+
+ if (it->first > name) {
+ break;
+ }
+ }
+
+ it = quantities.insert(it, std::make_pair(name, Value::Scalar()));
+
+ return it->second;
+ }
+
+ typedef std::vector<std::pair<std::string, Value::Scalar>>::const_iterator
+ const_iterator;
+
+ const_iterator begin() const { return quantities.begin(); }
+ const_iterator end() const { return quantities.end(); }
+
+private:
+ // List of scalar resources sorted by resource name.
+ // Arithmetic operations benefit from this sorting.
+ std::vector<std::pair<std::string, Value::Scalar>> quantities;
+};
+
+
} // namespace allocator {
} // namespace master {
} // namespace internal {