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 2016/07/22 19:10:14 UTC

mesos git commit: Cleanup the allocator port fragmentation logic.

Repository: mesos
Updated Branches:
  refs/heads/master 16fe3472d -> 17a1e58d3


Cleanup the allocator port fragmentation logic.

1) Renamed makePortRanges to createPorts, this function creates a
   "ports(*)" resource for the given ranges.

2) Added a new helper function 'fragment()', it fragments the
   given range bounds into a number of subranges.

3) Rename makeRange to createRange and updated its parameter
   to uint64_t to match the protobuf field.

Review: https://reviews.apache.org/r/50062/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/17a1e58d
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/17a1e58d
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/17a1e58d

Branch: refs/heads/master
Commit: 17a1e58d3f48d866ac5132cc28b2f33c2e287aac
Parents: 16fe347
Author: Guangya Liu <gy...@gmail.com>
Authored: Fri Jul 22 11:58:03 2016 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Fri Jul 22 12:10:06 2016 -0700

----------------------------------------------------------------------
 src/tests/hierarchical_allocator_tests.cpp | 109 ++++++++++++++++++------
 1 file changed, 83 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/17a1e58d/src/tests/hierarchical_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index befb94a..bb6947f 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -82,38 +82,88 @@ struct Allocation
   hashmap<SlaveID, Resources> resources;
 };
 
-static Resource
-makePortRanges(const ::mesos::Value::Range& bounds, unsigned numRanges)
+
+// Creates a "ports(*)" resource for the given ranges.
+static Resource createPorts(const ::mesos::Value::Ranges& ranges)
 {
-  unsigned numPorts = bounds.end() - bounds.begin();
-  unsigned step = numPorts / numRanges;
-  ::mesos::Value::Ranges ranges;
+  Value value;
+  value.set_type(Value::RANGES);
+  value.mutable_ranges()->CopyFrom(ranges);
 
-  ranges.mutable_range()->Reserve(numRanges);
+  Resource resource;
+  resource.set_role("*");
+  resource.set_name("ports");
+  resource.set_type(Value::RANGES);
+  resource.mutable_ranges()->CopyFrom(value.ranges());
 
-  for (unsigned i = 0; i < numRanges; ++i) {
-    Value::Range *range = ranges.add_range();
-    unsigned start = bounds.begin() + (i * step);
-    unsigned end = start + 1;
+  return resource;
+}
+
+
+// Fragments the given range bounds into a number of subranges.
+// Returns an Error if 'numRanges' is too large. E.g.
+//
+//   [1-10], 1 -> [1-10]
+//   [1-10], 2 -> [1-1,3-10]
+//   [1-10], 3 -> [1-1,3-3,5-10]
+//   [1-10], 4 -> [1-1,3-3,5-5,7-10]
+//   [1-10], 5 -> [1-1,3-3,5-5,7-7,9-10]
+//   [1-10], 6 -> Error
+//
+static Try<::mesos::Value::Ranges> fragment(
+    const ::mesos::Value::Range& bounds,
+    size_t numRanges)
+{
+  uint64_t numValues = bounds.end() - bounds.begin() + 1;
+
+  // Compute the max number of ranges.
+  //
+  // If `numValues` is even, then the maximum number of ranges is
+  // `numValues / 2`:
+  //   [1-2] -> 2 values, maximum 1 range:  [1-2]
+  //   [1-4] -> 4 values, maximum 2 ranges: [1-1,3-4]
+  //   [1-6] -> 6 values, maximum 3 ranges: [1-1,3-3,5-6]
+  //
+  // If `numValues` is odd, then the maximum number of ranges is
+  // `(numValues + 1) / 2`:
+  //   [1-1] -> 1 values, maximum 1 range:  [1-1]
+  //   [1-3] -> 3 values, maximum 2 ranges: [1-1,3-3]
+  //   [1-5] -> 5 values, maximum 3 ranges: [1-1,3-3,5-5]
+  //
+  uint64_t maxRanges;
+  if (numValues % 2 == 0) {
+    maxRanges = numValues / 2;
+  } else {
+    maxRanges = (numValues + 1) / 2;
+  }
 
-    range->set_begin(start);
-    range->set_end(end);
+  if (numRanges > maxRanges) {
+    return Error("Requested more distinct ranges than possible");
   }
 
-  Value values;
-  Resource resource;
+  // See the documentation above for the fragmentation technique.
+  // We fragment from the front of the bounds until we have the
+  // desired number of ranges.
+  ::mesos::Value::Ranges ranges;
+  ranges.mutable_range()->Reserve(numRanges);
 
-  values.set_type(Value::RANGES);
-  values.mutable_ranges()->CopyFrom(ranges);
-  resource.set_type(Value::RANGES);
-  resource.set_role("*");
-  resource.set_name("ports");
-  resource.mutable_ranges()->CopyFrom(values.ranges());
+  for (size_t i = 0; i < numRanges; ++i) {
+    Value::Range* range = ranges.add_range();
 
-  return resource;
+    range->set_begin(bounds.begin() + (i * 2));
+    range->set_end(range->begin());
+  }
+
+  // Make sure the last range covers the end of the bounds.
+  if (!ranges.range().empty()) {
+    ranges.mutable_range()->rbegin()->set_end(bounds.end());
+  }
+
+  return ranges;
 }
 
-static ::mesos::Value::Range makeRange(unsigned begin, unsigned end)
+
+static ::mesos::Value::Range createRange(uint64_t begin, uint64_t end)
 {
   ::mesos::Value::Range range;
   range.set_begin(begin);
@@ -121,6 +171,7 @@ static ::mesos::Value::Range makeRange(unsigned begin, unsigned end)
   return range;
 }
 
+
 struct Deallocation
 {
   FrameworkID frameworkId;
@@ -3455,8 +3506,11 @@ TEST_P(HierarchicalAllocator_BENCHMARK_Test, DeclineOffers)
   Resources resources = Resources::parse(
       "cpus:16;mem:2014;disk:1024").get();
 
-  Resources ports = makePortRanges(makeRange(31000, 32000), 16);
-  resources += ports;
+  Try<::mesos::Value::Ranges> ranges = fragment(createRange(31000, 32000), 16);
+  ASSERT_SOME(ranges);
+  ASSERT_EQ(16, ranges->range_size());
+
+  resources += createPorts(ranges.get());
 
   watch.start();
 
@@ -3600,8 +3654,11 @@ TEST_P(HierarchicalAllocator_BENCHMARK_Test, ResourceLabels)
   // aggregated easily by the master/allocator.
   Resources resources = Resources::parse("mem:2014;disk:1024").get();
 
-  Resources ports = makePortRanges(makeRange(31000, 32000), 16);
-  resources += ports;
+  Try<::mesos::Value::Ranges> ranges = fragment(createRange(31000, 32000), 16);
+  ASSERT_SOME(ranges);
+  ASSERT_EQ(16, ranges->range_size());
+
+  resources += createPorts(ranges.get());
 
   watch.start();