You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jp...@apache.org on 2017/10/13 22:56:32 UTC

mesos git commit: Added a benchmark test for allocating shared resources.

Repository: mesos
Updated Branches:
  refs/heads/master f569b841c -> 54e0c82dc


Added a benchmark test for allocating shared resources.

Add a benchmark for allocations test that has the following resource
configurations:

(1) REGULAR: Offers from every slave have only regular resources.
(2) SHARED: Offers from every slave have only shared resources.
(3) MIXED: Offers from every alternate slave contain only regular
    resources; and offers from every other alternate slave contain
    a shared resource.

This test is parameterized based on number of agents, number of
frameworks and resource configuration.

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


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

Branch: refs/heads/master
Commit: 54e0c82dc77e5e90a7a7aaa36bbc91a5f43d99e5
Parents: f569b84
Author: Anindya Sinha <an...@apple.com>
Authored: Fri Oct 13 11:36:22 2017 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Oct 13 16:13:48 2017 -0700

----------------------------------------------------------------------
 src/tests/hierarchical_allocator_tests.cpp | 228 ++++++++++++++++++++++++
 1 file changed, 228 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/54e0c82d/src/tests/hierarchical_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index e68e39a..48b48ad 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -5039,6 +5039,234 @@ TEST_P(HierarchicalAllocatorTestWithParam, AllocateSharedResources)
 }
 
 
+// Resource sharing types used for the PersistentVolumes benchmark test:
+//
+// 1. `REGULAR` uses no shared resources.
+// 2. `SHARED` only uses shared resources.
+// 3. `MIXED` uses half the agents with shared resources, and the remaining
+//    half with regular resources.
+enum Sharedness
+{
+  REGULAR,
+  SHARED,
+  MIXED
+};
+
+
+ostream& operator<<(ostream& stream, Sharedness type)
+{
+  switch (type) {
+    case REGULAR: stream << "Regular"; break;
+    case SHARED: stream << "Shared"; break;
+    case MIXED: stream << "Mixed"; break;
+    default:
+      UNREACHABLE();
+  }
+
+  return stream;
+}
+
+
+class HierarchicalAllocations_BENCHMARK_Test
+  : public HierarchicalAllocatorTestBase,
+    public WithParamInterface<std::tr1::tuple<size_t, size_t, Sharedness>> {};
+
+
+INSTANTIATE_TEST_CASE_P(
+    AllResources,
+    HierarchicalAllocations_BENCHMARK_Test,
+    ::testing::Combine(
+      ::testing::Values(1000U, 5000U, 10000U, 20000U, 30000U, 50000U),
+      ::testing::Values(1U, 50U, 100U, 200U, 500U, 1000U, 3000U, 6000U),
+      ::testing::Values(
+          Sharedness::REGULAR,
+          Sharedness::SHARED,
+          Sharedness::MIXED))
+    );
+
+
+// This benchmark simulates a number of frameworks that tests the allocation
+// times with various combinations of resources over all agents in a cluster.
+TEST_P(HierarchicalAllocations_BENCHMARK_Test, PersistentVolumes)
+{
+  size_t agentCount = std::tr1::get<0>(GetParam());
+  size_t frameworkCount = std::tr1::get<1>(GetParam());
+  Sharedness sharedness = std::tr1::get<2>(GetParam());
+
+  // Pause the clock because we want to manually drive the allocations.
+  Clock::pause();
+
+  struct OfferedResources
+  {
+    FrameworkID   frameworkId;
+    SlaveID       slaveId;
+    Resources     resources;
+  };
+
+  vector<OfferedResources> offers;
+
+  auto offerCallback = [&offers](
+      const FrameworkID& frameworkId,
+      const hashmap<string, hashmap<SlaveID, Resources>>& resources_)
+  {
+    foreachkey (const string& role, resources_) {
+      foreachpair (const SlaveID& slaveId,
+                   const Resources& resources,
+                   resources_.at(role)) {
+        offers.push_back(OfferedResources{frameworkId, slaveId, resources});
+      }
+    }
+  };
+
+  cout << "Using " << agentCount << " agents and "
+       << frameworkCount << " frameworks "
+       << "with resource sharedness " << sharedness << endl;
+
+  initialize(master::Flags(), offerCallback);
+
+  vector<FrameworkInfo> frameworks;
+  frameworks.reserve(frameworkCount);
+
+  // Create the frameworks.
+  for (size_t i = 0; i < frameworkCount; i++) {
+    FrameworkInfo framework = createFrameworkInfo({"test"});
+    if (sharedness != REGULAR) {
+      framework.add_capabilities()->set_type(
+          FrameworkInfo::Capability::SHARED_RESOURCES);
+    }
+
+    frameworks.push_back(framework);
+  }
+
+  vector<SlaveInfo> agents;
+  agents.reserve(agentCount);
+
+  Resources agentResources = Resources::parse(
+      "cpus(test):24;mem(test):4096;disk(test):3072;"
+      "ports(test):[31000-32000]").get();
+
+  // Create the agents.
+  for (size_t i = 0; i < agentCount; i++) {
+    // Add a persistent volume of size 1024 MB as follows:
+    // (1) REGULAR: Use a regular non-shared persistent volume.
+    // (2) SHARED: Use a shared persistent volume.
+    // (3) MIXED: Make every alternate slave contain a shared
+    //     persistent volume.
+    Resource volume = createPersistentVolume(
+        Megabytes(1024),
+        "test",
+        "id" + stringify(i),
+        "path" + stringify(i),
+        None(),
+        None(),
+        None());
+
+    // Make the persistent volume shared if:
+    // (1) Test mode is SHARED; or
+    // (2) Test mode is MIXED, and for every even iteration.
+    if ((sharedness == SHARED) ||
+        ((sharedness == MIXED) && (i % 2 == 0))) {
+      volume.mutable_shared();
+    }
+
+    agents.push_back(createSlaveInfo(agentResources + volume));
+  }
+
+  Stopwatch watch;
+  watch.start();
+
+  foreach (const FrameworkInfo& framework, frameworks) {
+    allocator->addFramework(framework.id(), framework, {}, true, {});
+  }
+
+  // Wait for all the `addFramework` operations to be processed.
+  Clock::settle();
+
+  watch.stop();
+
+  cout << "Added " << frameworkCount << " frameworks"
+       << " in " << watch.elapsed() << endl;
+
+  Resources _allocation = Resources::parse(
+      "cpus(test):16;mem(test):1024;disk(test):1024").get();
+
+  Try<::mesos::Value::Ranges> ranges = fragment(createRange(31000, 32000), 16);
+  ASSERT_SOME(ranges);
+  ASSERT_EQ(16, ranges->range_size());
+
+  Resource ports = createPorts(ranges.get());
+  ports.add_reservations()->CopyFrom(createStaticReservationInfo("test"));
+
+  _allocation += ports;
+
+  const Resources allocation = allocatedResources(_allocation, "*");
+
+  watch.start();
+
+  // Add the agents, using round-robin to choose which framework
+  // to allocate a slice of the slave's resources to.
+  for (size_t i = 0; i < agents.size(); i++) {
+    // Add some used resources on each agent.
+    hashmap<FrameworkID, Resources> used;
+    used[frameworks[i % frameworkCount].id()] = allocation;
+
+    allocator->addSlave(
+        agents[i].id(),
+        agents[i],
+        AGENT_CAPABILITIES(),
+        None(),
+        agents[i].resources(),
+        used);
+  }
+
+  // Wait for all the `addSlave` operations to be processed.
+  Clock::settle();
+
+  watch.stop();
+
+  cout << "Added " << agentCount << " agents"
+       << " in " << watch.elapsed() << endl;
+
+  // Now perform allocations. To ensure the test can run in a timely manner,
+  // we always perform a fixed number of allocations. We ensure we run the
+  // allocation cycle enough times such that every framework receives at least
+  // one offer.
+  size_t allocationsCount = 6;
+
+  // Now perform the allocations. Loop enough times for all the frameworks
+  // to get offered all the resources.
+  for (size_t count = 0; count < allocationsCount; count++) {
+    foreach (const OfferedResources& offer, offers) {
+      allocator->recoverResources(
+          offer.frameworkId,
+          offer.slaveId,
+          offer.resources,
+          None());
+    }
+
+    Clock::settle();
+    offers.clear();
+
+    Stopwatch watch;
+
+    watch.start();
+
+    // Advance the clock and trigger a batch allocation cycle.
+    Clock::advance(flags.allocation_interval);
+    Clock::settle();
+
+    watch.stop();
+
+    cout << "round " << count
+         << " allocate() took " << watch.elapsed()
+         << " to make " << offers.size() << " offers"
+         << endl;
+  }
+
+  Clock::resume();
+}
+
+
 class HierarchicalAllocator_BENCHMARK_Test
   : public HierarchicalAllocatorTestBase,
     public WithParamInterface<std::tuple<size_t, size_t>> {};