def test_single_burst_workload_lifecycle(self): for allocator in ALLOCATORS: requested_thread_count = 2 workload = get_test_workload(uuid.uuid4(), requested_thread_count, BURST) cgroup_manager = MockCgroupManager() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator) # Add workload workload_manager.add_workload(workload) self.assertEqual( 1, cgroup_manager.container_update_counts[workload.get_id()]) # More than the requested threads should have been assigned to the only burst workload. self.assertTrue( len(cgroup_manager.container_update_map[workload.get_id()]) > requested_thread_count) # Remove workload workload_manager.remove_workload(workload.get_id()) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(workload_manager.get_cpu().get_empty_threads()))
def test_single_burst_workload_lifecycle(self): for allocator_class in [ GreedyCpuAllocator, IntegerProgramCpuAllocator ]: thread_count = 2 workload = Workload(uuid.uuid4(), thread_count, BURST) cgroup_manager = MockCgroupManager() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator_class=allocator_class) # Add workload workload_manager.add_workload(workload) self.assertEqual( 2, cgroup_manager.container_update_counts[workload.get_id()]) # All threads should have been assigned to the only burst workload. self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(cgroup_manager.container_update_map[workload.get_id()])) # No threads should have been consumed from the cpu model perspective. self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(workload_manager.get_cpu().get_empty_threads())) # Remove workload workload_manager.remove_workload(workload.get_id()) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(workload_manager.get_cpu().get_empty_threads()))
def test_single_static_workload_lifecycle(self): for allocator_class in [ GreedyCpuAllocator, IntegerProgramCpuAllocator ]: thread_count = 2 workload = Workload(uuid.uuid4(), thread_count, STATIC) cgroup_manager = MockCgroupManager() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator_class=allocator_class) # Add workload workload_manager.add_workload(workload) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT - thread_count, len(workload_manager.get_cpu().get_empty_threads())) self.assertEqual( 1, cgroup_manager.container_update_counts[workload.get_id()]) # Remove workload workload_manager.remove_workload(workload.get_id()) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(workload_manager.get_cpu().get_empty_threads()))
def test_remove_unknown_workload(self): for allocator in ALLOCATORS: unknown_workload_id = "unknown" thread_count = 2 workload = get_test_workload(uuid.uuid4(), thread_count, STATIC) workload_manager = WorkloadManager(get_cpu(), MockCgroupManager(), allocator) # Remove from empty set workload_manager.remove_workload(unknown_workload_id) # Add workload workload_manager.add_workload(workload) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT - thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Removal of an unknown workload should have no effect workload_manager.remove_workload(unknown_workload_id) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT - thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Remove workload with unknown workload, real workload should be removed workload_manager.remove_workload(unknown_workload_id) workload_manager.remove_workload(workload.get_id()) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(workload_manager.get_cpu().get_empty_threads()))
def test_remove_unknown_workload(self): for allocator_class in [ GreedyCpuAllocator, IntegerProgramCpuAllocator ]: unknown_workload_id = "unknown" thread_count = 2 workload = Workload(uuid.uuid4(), thread_count, STATIC) workload_manager = WorkloadManager(get_cpu(), MockCgroupManager(), allocator_class=allocator_class) # Remove from empty set workload_manager.remove_workload([unknown_workload_id]) # Add workload workload_manager.add_workload(workload) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT - thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Removal of an unknown workload should have no effect workload_manager.remove_workload([unknown_workload_id]) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT - thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Remove workload with unknown workload, real workload should be removed workload_manager.remove_workload(unknown_workload_id) workload_manager.remove_workload(workload.get_id()) self.assertEqual( DEFAULT_TOTAL_THREAD_COUNT, len(workload_manager.get_cpu().get_empty_threads()))
def test_single_workload_memory_settings(self): for allocator in ALLOCATORS: thread_count = 2 workload = get_test_workload(uuid.uuid4(), thread_count, STATIC) cgroup_manager = MockCgroupManager() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator) # With an empty configuration we should expect default False behavior # for all memory flags set_config_manager(ConfigManager(TestPropertyProvider({}))) workload_manager.add_workload(workload) self.assertFalse( cgroup_manager.get_memory_migrate(workload.get_id())) self.assertFalse( cgroup_manager.get_memory_spread_page(workload.get_id())) self.assertFalse( cgroup_manager.get_memory_spread_slab(workload.get_id())) workload_manager.remove_workload(workload.get_id()) # With all memory configuration options set to True we should expect all memory # flags to be set to True set_config_manager( ConfigManager( TestPropertyProvider({ TITUS_ISOLATE_MEMORY_MIGRATE: True, TITUS_ISOLATE_MEMORY_SPREAD_PAGE: True, TITUS_ISOLATE_MEMORY_SPREAD_SLAB: True, }))) workload_manager.add_workload(workload) self.assertTrue( cgroup_manager.get_memory_migrate(workload.get_id())) self.assertTrue( cgroup_manager.get_memory_spread_page(workload.get_id())) self.assertTrue( cgroup_manager.get_memory_spread_slab(workload.get_id())) workload_manager.remove_workload(workload.get_id())
def test_ip_fallback(self): w_a = Workload("a", 3, STATIC) w_b = Workload("b", 2, STATIC) w_c = Workload("c", 1, STATIC) w_d = Workload("d", 2, STATIC) cpu = get_cpu(package_count=2, cores_per_package=2, threads_per_core=2) wm = WorkloadManager(cpu, MockCgroupManager(), allocator_class=CrashingAllocator) wm.add_workload(w_a) wm.add_workload(w_b) wm.remove_workload("a") wm.add_workload(w_c) wm.remove_workload("b") wm.add_workload(w_d) self.assertEqual(3, len(wm.get_cpu().get_claimed_threads())) self.assertEqual( 3, len(wm.get_allocator().get_cpu().get_claimed_threads())) self.assertEqual(6, wm.get_fallback_allocator_calls_count())
def test_alternating_static_burst_workloads(self): for allocator in ALLOCATORS: thread_count = 2 burst0 = get_test_workload("burst0", thread_count, BURST) burst1 = get_test_workload("burst1", thread_count, BURST) static0 = get_test_workload("static0", thread_count, STATIC) static1 = get_test_workload("static1", thread_count, STATIC) cgroup_manager = MockCgroupManager() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator) # Add static workload log.info("ADDING STATIC0") workload_manager.add_workload(static0) self.__assert_container_thread_count(workload_manager.get_cpu(), cgroup_manager, [static0]) self.__assert_cpu_thread_count(workload_manager.get_cpu(), [static0]) # Add burst workload log.info("ADDING BURST0") workload_manager.add_workload(burst0) self.__assert_container_thread_count(workload_manager.get_cpu(), cgroup_manager, [static0, burst0]) self.__assert_cpu_thread_count(workload_manager.get_cpu(), [static0, burst0]) # Add static workload log.info("ADDING STATIC1") workload_manager.add_workload(static1) self.__assert_container_thread_count(workload_manager.get_cpu(), cgroup_manager, [static0, burst0, static1]) self.__assert_cpu_thread_count(workload_manager.get_cpu(), [static0, burst0, static1]) # Add burst workload log.info("ADDING BURST1") workload_manager.add_workload(burst1) self.__assert_container_thread_count( workload_manager.get_cpu(), cgroup_manager, [static0, burst0, static1, burst1]) self.__assert_cpu_thread_count(workload_manager.get_cpu(), [static0, burst0, static1, burst1]) # Remove static workload log.info("REMOVING STATIC0") workload_manager.remove_workload(static0.get_id()) self.__assert_container_thread_count(workload_manager.get_cpu(), cgroup_manager, [burst0, static1, burst1]) self.__assert_cpu_thread_count(workload_manager.get_cpu(), [burst0, static1, burst1]) # Remove static workload log.info("REMOVING BURST0") workload_manager.remove_workload(burst0.get_id()) self.__assert_container_thread_count(workload_manager.get_cpu(), cgroup_manager, [static1, burst1]) self.__assert_cpu_thread_count(workload_manager.get_cpu(), [static1, burst1])
def test_alternating_static_burst_workloads(self): for allocator_class in [ GreedyCpuAllocator, IntegerProgramCpuAllocator ]: thread_count = 2 burst0 = Workload("burst0", thread_count, BURST) burst1 = Workload("burst1", thread_count, BURST) static0 = Workload("static0", thread_count, STATIC) static1 = Workload("static1", thread_count, STATIC) cgroup_manager = MockCgroupManager() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator_class=allocator_class) # Add static workload log.info("ADDING STATIC0") workload_manager.add_workload(static0) self.assertTrue( static0.get_id() in cgroup_manager.container_update_map) self.assertEqual( thread_count, len(cgroup_manager.container_update_map[static0.get_id()])) self.assertEqual( 1, cgroup_manager.container_update_counts[static0.get_id()]) expected_free_thread_count = DEFAULT_TOTAL_THREAD_COUNT - thread_count self.assertEqual( expected_free_thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Add burst workload log.info("ADDING BURST0") workload_manager.add_workload(burst0) self.assertEqual( expected_free_thread_count, len(cgroup_manager.container_update_map[burst0.get_id()])) self.assertEqual( 2, cgroup_manager.container_update_counts[burst0.get_id()]) # No change in empty threads expected self.assertEqual( expected_free_thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Add static workload log.info("ADDING STATIC1") workload_manager.add_workload(static1) self.assertEqual( thread_count, len(cgroup_manager.container_update_map[static1.get_id()])) self.assertEqual( 1, cgroup_manager.container_update_counts[static1.get_id()]) expected_free_thread_count = expected_free_thread_count - thread_count self.assertEqual( expected_free_thread_count, len(workload_manager.get_cpu().get_empty_threads())) # The burst0 container should be updated again because the burst footprint changed after the addition of a # static workload self.assertEqual( 3, cgroup_manager.container_update_counts[burst0.get_id()]) self.assertEqual( expected_free_thread_count, len(cgroup_manager.container_update_map[burst0.get_id()])) # Add burst workload log.info("ADDING BURST1") workload_manager.add_workload(burst1) self.assertEqual( 4, cgroup_manager.container_update_counts[burst0.get_id()]) self.assertEqual( 2, cgroup_manager.container_update_counts[burst1.get_id()]) self.assertEqual( expected_free_thread_count, len(cgroup_manager.container_update_map[burst1.get_id()])) # No change in empty threads expected self.assertEqual( expected_free_thread_count, len(workload_manager.get_cpu().get_empty_threads())) # Remove static workload log.info("REMOVING STATIC0") workload_manager.remove_workload(static0.get_id()) self.assertEqual( 5, cgroup_manager.container_update_counts[burst0.get_id()]) self.assertEqual( 3, cgroup_manager.container_update_counts[burst1.get_id()]) # Empty threads should have increased expected_free_thread_count = expected_free_thread_count + thread_count self.assertEqual( expected_free_thread_count, len(workload_manager.get_cpu().get_empty_threads())) self.assertEqual( expected_free_thread_count, len(cgroup_manager.container_update_map[burst0.get_id()])) self.assertEqual( expected_free_thread_count, len(cgroup_manager.container_update_map[burst1.get_id()]))