def test_assign_two_workloads_empty_cpu_ip(self): """ Workload 0: 2 threads --> (p:0 c:0 t:0) (p:0 c:1 t:0) Workload 1: 1 thread --> (p:1 c:0 t:0) """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator(cpu) w0 = Workload(uuid.uuid4(), 2, STATIC) w1 = Workload(uuid.uuid4(), 1, STATIC) allocator.assign_threads(w0) allocator.assign_threads(w1) self.assertEqual(3, len(cpu.get_claimed_threads())) packages = cpu.get_packages() # WORKLOAD 0 core00 = packages[0].get_cores()[0] core01 = packages[0].get_cores()[1] thread0 = core00.get_threads()[0] self.assertEqual(0, thread0.get_id()) self.assertTrue(thread0.is_claimed()) thread1 = core01.get_threads()[0] self.assertEqual(1, thread1.get_id()) self.assertTrue(thread1.is_claimed()) # WORKLOAD 1 core00 = packages[1].get_cores()[0] thread4 = core00.get_threads()[0] self.assertEqual(4, thread4.get_id()) self.assertTrue(thread4.is_claimed())
def test_shared_core_violation(self): allocator = IntegerProgramCpuAllocator() # Claim all thread but one cpu = get_cpu() w = get_test_workload(uuid.uuid4(), len(cpu.get_threads()) - 1, STATIC) workloads = {w.get_id(): w} request = AllocateThreadsRequest(cpu, w.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() log.info("{}".format(cpu)) violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(0, len(violations)) # Assign another workload which will force core sharing w = get_test_workload(uuid.uuid4(), 1, STATIC) workloads[w.get_id()] = w request = AllocateThreadsRequest(cpu, w.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() log.info("{}".format(cpu)) violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(1, len(violations))
def test_one_cross_package_violation(self): cpu = get_cpu() allocator = IntegerProgramCpuAllocator(cpu) w = Workload(uuid.uuid4(), 9, STATIC) allocator.assign_threads(w) violations = get_cross_package_violations(cpu) self.assertEqual(1, len(violations))
def test_filling_holes_ip(self): """ Initialize with fragmented placement, then fill the instance. Result should be less fragmented, with the first workload completely filling a socket. | a | | a | | | | a | | a | | ------------- | | | a | | a | | a | | a | | """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator() # Initialize fragmented workload wa = get_test_workload(uuid.uuid4(), 8, STATIC) p0 = cpu.get_packages()[0] p0.get_cores()[0].get_threads()[0].claim(wa.get_id()) p0.get_cores()[1].get_threads()[1].claim(wa.get_id()) p0.get_cores()[2].get_threads()[0].claim(wa.get_id()) p0.get_cores()[3].get_threads()[1].claim(wa.get_id()) p1 = cpu.get_packages()[1] p1.get_cores()[0].get_threads()[1].claim(wa.get_id()) p1.get_cores()[1].get_threads()[0].claim(wa.get_id()) p1.get_cores()[2].get_threads()[1].claim(wa.get_id()) p1.get_cores()[3].get_threads()[0].claim(wa.get_id()) self.assertEqual(8, len(cpu.get_empty_threads())) # Fill the rest of the CPU w0 = get_test_workload(uuid.uuid4(), 2, STATIC) w1 = get_test_workload(uuid.uuid4(), 3, STATIC) w2 = get_test_workload(uuid.uuid4(), 1, STATIC) w3 = get_test_workload(uuid.uuid4(), 2, STATIC) workload_map = {wa.get_id(): wa} workloads = [w0, w1, w2, w3] __workloads = [wa] for w in workloads: __workloads.append(w) workload_map[w.get_id()] = w request = get_no_usage_threads_request(cpu, __workloads) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(0, len(cpu.get_empty_threads())) # first workload should be filling completely a socket to avoid cross-socket job layout for package in cpu.get_packages(): if package.get_cores()[0].get_threads()[0].get_workload_ids( ) != wa.get_id(): continue ids = [ t.get_workload_ids() for core in package.get_cores() for t in core.get_threads() ] self.assertListEqual(ids, [wa.get_id()] * 8)
def test_one_cross_package_violation(self): cpu = get_cpu() allocator = IntegerProgramCpuAllocator() w = get_test_workload(uuid.uuid4(), 9, STATIC) request = get_no_usage_threads_request(cpu, [w]) cpu = allocator.assign_threads(request).get_cpu() violations = get_cross_package_violations(cpu) self.assertEqual(1, len(violations))
def test_one_cross_package_violation(self): cpu = get_cpu() allocator = IntegerProgramCpuAllocator() w = get_test_workload(uuid.uuid4(), 9, STATIC) request = AllocateThreadsRequest(cpu, w.get_id(), {w.get_id(): w}, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() violations = get_cross_package_violations(cpu) self.assertEqual(1, len(violations))
def test_cache_ip(self): """ [add a=2, add b=2, remove b=2, add c=2, remove a=2, add d=2] should lead to the following cache entries: (state=[], req=[2]) (state=[2], req=[2,2]) (state=[2,2], req=[2,0]) [cache hit] [cache hit] (state=[2,2], req=[2,2]) but different layout """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator() workloads = {} workload = get_test_workload("a", 2, STATIC) workloads[workload.get_id()] = workload request = AllocateThreadsRequest(cpu, workload.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(1, len(allocator._IntegerProgramCpuAllocator__cache)) workload = get_test_workload("b", 2, STATIC) workloads[workload.get_id()] = workload request = AllocateThreadsRequest(cpu, workload.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(2, len(allocator._IntegerProgramCpuAllocator__cache)) request = AllocateThreadsRequest(cpu, "b", workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.free_threads(request).get_cpu() self.assertEqual(3, len(allocator._IntegerProgramCpuAllocator__cache)) workloads.pop("b") workload = get_test_workload("c", 2, STATIC) workloads[workload.get_id()] = workload request = AllocateThreadsRequest(cpu, workload.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(3, len(allocator._IntegerProgramCpuAllocator__cache)) request = AllocateThreadsRequest(cpu, "a", workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.free_threads(request).get_cpu() self.assertEqual(4, len(allocator._IntegerProgramCpuAllocator__cache)) workloads.pop("a") workload = get_test_workload("d", 2, STATIC) workloads[workload.get_id()] = workload request = AllocateThreadsRequest(cpu, workload.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) allocator.assign_threads(request).get_cpu() self.assertEqual(5, len(allocator._IntegerProgramCpuAllocator__cache))
def test_assign_ten_threads_empty_cpu_ip(self): """ Workload 0: 10 threads --> (p:0 c:[0-7] t:[0-9]) | 1 | 1 | 1 | 1 | | 1 | 1 | | | | ------------- | | 1 | 1 | 1 | 1 | | | | | | """ for allocator in [ IntegerProgramCpuAllocator(), forecast_ip_alloc_simple ]: cpu = get_cpu() w = get_test_workload(uuid.uuid4(), 10, STATIC) request = get_no_usage_threads_request(cpu, [w]) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(10, len(cpu.get_claimed_threads())) threads_per_socket = [] for p in cpu.get_packages(): ths = [] for c in p.get_cores(): for t in c.get_threads(): if t.is_claimed(): ths.append(t) threads_per_socket.append(len(ths)) self.assertEqual(5, threads_per_socket[0]) self.assertEqual(5, threads_per_socket[1])
def test_assign_two_workloads_empty_cpu_ip(self): """ Workload 0: 2 threads --> (p:0 c:0 t:0) (p:0 c:1 t:0) Workload 1: 1 thread --> (p:1 c:0 t:0) """ for allocator in [ IntegerProgramCpuAllocator(), forecast_ip_alloc_simple ]: cpu = get_cpu() w0 = get_test_workload(uuid.uuid4(), 2, STATIC) w1 = get_test_workload(uuid.uuid4(), 1, STATIC) request0 = get_no_usage_threads_request(cpu, [w0]) cpu = allocator.assign_threads(request0).get_cpu() request1 = get_no_usage_threads_request(cpu, [w0, w1]) cpu = allocator.assign_threads(request1).get_cpu() self.assertEqual(3, len(cpu.get_claimed_threads())) ids_per_socket = [] for pid, p in enumerate(cpu.get_packages()): r = [] for cid, c in enumerate(p.get_cores()): for tid, t in enumerate(c.get_threads()): if t.is_claimed(): self.assertEqual(1, len(t.get_workload_ids())) r.append((t.get_workload_ids()[0], c.get_id())) ids_per_socket.append(r) for r in ids_per_socket: # each workload should be on a different socket self.assertEqual(1, len(set([e[0] for e in r])))
def __init__(self, cpu=None, allocator=IntegerProgramCpuAllocator()): if cpu is None: cpu = get_cpu() self.__workload_manager = WorkloadManager(cpu, MockCgroupManager(), allocator) self.__create_event_handler = CreateEventHandler(self.__workload_manager) self.__free_event_handler = FreeEventHandler(self.__workload_manager) self.__rebalance_event_handler = RebalanceEventHandler(self.__workload_manager)
def test_ip_fallback(self): w_a = get_test_workload("a", 3, STATIC) w_b = get_test_workload("b", 2, STATIC) w_c = get_test_workload("c", 1, STATIC) w_d = get_test_workload("d", 2, STATIC) cpu = get_cpu(package_count=2, cores_per_package=2, threads_per_core=2) allocator = FallbackCpuAllocator(CrashingAllocator(), IntegerProgramCpuAllocator()) request = get_no_usage_threads_request(cpu, [w_a]) cpu = allocator.assign_threads(request).get_cpu() request = get_no_usage_threads_request(cpu, [w_a, w_b]) cpu = allocator.assign_threads(request).get_cpu() request = get_no_usage_threads_request(cpu, [w_b, w_a]) cpu = allocator.free_threads(request).get_cpu() request = get_no_usage_threads_request(cpu, [w_b, w_c]) cpu = allocator.assign_threads(request).get_cpu() request = get_no_usage_threads_request(cpu, [w_c, w_b]) cpu = allocator.free_threads(request).get_cpu() request = get_no_usage_threads_request(cpu, [w_c, w_d]) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(3, len(cpu.get_claimed_threads())) self.assertEqual(6, allocator.get_fallback_allocator_calls_count())
def test_thread_allocation_computation(self): for allocator in [IntegerProgramCpuAllocator(), GreedyCpuAllocator()]: static_thread_count = 2 burst_thread_count = 4 w_static = get_test_workload("s", static_thread_count, STATIC) w_burst = get_test_workload("b", burst_thread_count, BURST) cgroup_manager = MockCgroupManager() registry = Registry() workload_manager = WorkloadManager(get_cpu(), cgroup_manager, allocator) workload_manager.set_registry(registry, {}) workload_manager.add_workload(w_static) workload_manager.add_workload(w_burst) workload_manager.report_metrics({}) total_thread_count = len(workload_manager.get_cpu().get_threads()) expected_burst_allocation_size = total_thread_count - static_thread_count self.assertTrue( gauge_value_equals(registry, ALLOCATED_SIZE_KEY, total_thread_count)) self.assertTrue( gauge_value_equals(registry, UNALLOCATED_SIZE_KEY, 0)) self.assertTrue( gauge_value_equals(registry, STATIC_ALLOCATED_SIZE_KEY, static_thread_count)) self.assertTrue( gauge_value_equals(registry, BURST_ALLOCATED_SIZE_KEY, expected_burst_allocation_size)) self.assertTrue( gauge_value_equals(registry, BURST_REQUESTED_SIZE_KEY, burst_thread_count)) self.assertTrue( gauge_value_equals(registry, OVERSUBSCRIBED_THREADS_KEY, 0)) # Claim every thread for the burst workload which will oversubscribe the static threads for t in workload_manager.get_cpu().get_threads(): t.claim(w_burst.get_id()) workload_manager.report_metrics({}) self.assertTrue( gauge_value_equals(registry, ALLOCATED_SIZE_KEY, total_thread_count)) self.assertTrue( gauge_value_equals(registry, UNALLOCATED_SIZE_KEY, 0)) self.assertTrue( gauge_value_equals(registry, STATIC_ALLOCATED_SIZE_KEY, static_thread_count)) self.assertTrue( gauge_value_equals(registry, BURST_ALLOCATED_SIZE_KEY, total_thread_count)) self.assertTrue( gauge_value_equals(registry, BURST_REQUESTED_SIZE_KEY, burst_thread_count)) self.assertTrue( gauge_value_equals(registry, OVERSUBSCRIBED_THREADS_KEY, static_thread_count))
def test_cache_ip(self): """ [add a=2, add b=2, remove b=2, add c=2, remove a=2, add d=2] should lead to the following cache entries: (state=[], req=[2]) (state=[2], req=[2,2]) (state=[2,2], req=[2,0]) [cache hit] [cache hit] (state=[2,2], req=[2,2]) but different layout """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator() w_a = get_test_workload("a", 2, STATIC) w_b = get_test_workload("b", 2, STATIC) w_c = get_test_workload("c", 2, STATIC) w_d = get_test_workload("d", 2, STATIC) workloads = [w_a] request = get_no_usage_threads_request(cpu, workloads) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(1, len(allocator._IntegerProgramCpuAllocator__cache)) workloads = [w_a, w_b] request = get_no_usage_threads_request(cpu, workloads) allocator.assign_threads(request).get_cpu() self.assertEqual(2, len(allocator._IntegerProgramCpuAllocator__cache)) cpu = allocator.free_threads(request).get_cpu() self.assertEqual(3, len(allocator._IntegerProgramCpuAllocator__cache)) workloads = [w_a, w_c] request = get_no_usage_threads_request(cpu, workloads) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(3, len(allocator._IntegerProgramCpuAllocator__cache)) workloads = [w_c, w_a] request = get_no_usage_threads_request(cpu, workloads) cpu = allocator.free_threads(request).get_cpu() self.assertEqual(4, len(allocator._IntegerProgramCpuAllocator__cache)) workloads = [w_c, w_d] request = get_no_usage_threads_request(cpu, workloads) allocator.assign_threads(request).get_cpu() self.assertEqual(5, len(allocator._IntegerProgramCpuAllocator__cache))
def test_assign_two_threads_empty_cpu_ip(self): """ Workload 0: 2 threads --> (p:0 c:0 t:0) (p:0 c:1 t:0) """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator(cpu) w = Workload(uuid.uuid4(), 2, STATIC) allocator.assign_threads(w) self.assertEqual(2, len(cpu.get_claimed_threads())) # Expected core and threads core00 = cpu.get_packages()[0].get_cores()[0] core01 = cpu.get_packages()[0].get_cores()[1] thread0 = core00.get_threads()[0] self.assertEqual(0, thread0.get_id()) self.assertTrue(thread0.is_claimed()) thread1 = core01.get_threads()[0] self.assertEqual(1, thread1.get_id()) self.assertTrue(thread1.is_claimed())
def test_shared_core_violation(self): allocator = IntegerProgramCpuAllocator() # Claim all thread but one cpu = get_cpu() w_0 = get_test_workload(uuid.uuid4(), len(cpu.get_threads()) - 1, STATIC) request = get_no_usage_threads_request(cpu, [w_0]) cpu = allocator.assign_threads(request).get_cpu() log.info("{}".format(cpu)) violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(0, len(violations)) # Assign another workload which will force core sharing w_1 = get_test_workload(uuid.uuid4(), 1, STATIC) request = get_no_usage_threads_request(cpu, [w_0, w_1]) cpu = allocator.assign_threads(request).get_cpu() log.info("{}".format(cpu)) violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(1, len(violations))
def test_assign_ten_threads_empty_cpu_ip(self): """ Workload 0: 10 threads --> (p:0 c:[0-7] t:[0-9]) | 1 | 1 | 1 | 1 | | 1 | 1 | | | | ------------- | | 1 | 1 | 1 | 1 | | | | | | """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator(cpu) w = Workload(uuid.uuid4(), 10, STATIC) allocator.assign_threads(w) self.assertEqual(10, len(cpu.get_claimed_threads())) expected_thread_ids = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12] thread_ids = [thread.get_id() for thread in cpu.get_claimed_threads()] thread_ids.sort() self.assertEqual(expected_thread_ids, thread_ids)
def test_shared_core_violation(self): cpu = get_cpu() violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(0, len(violations)) # Claim 1 thread on every core dummy_workload_id = uuid.uuid4() for p in cpu.get_packages(): for c in p.get_cores(): c.get_threads()[0].claim(dummy_workload_id) violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(0, len(violations)) # Assign another workload which will force core sharing allocator = IntegerProgramCpuAllocator(cpu) w = Workload(uuid.uuid4(), 2, STATIC) allocator.assign_threads(w) violations = get_shared_core_violations(cpu) log.info("shared core violations: {}".format(violations)) self.assertEqual(2, len(violations))
def test_is_isolated(self): real_allocators = [GreedyCpuAllocator(), IntegerProgramCpuAllocator()] for allocator in real_allocators: wm = WorkloadManager(get_cpu(), MockCgroupManager(), allocator) self.assertFalse(wm.is_isolated(uuid.uuid4())) for allocator in real_allocators: workload = get_test_workload(uuid.uuid4(), DEFAULT_TOTAL_THREAD_COUNT, STATIC) wm = WorkloadManager(get_cpu(), MockCgroupManager(), allocator) wm.add_workload(workload) self.assertTrue(wm.is_isolated(workload.get_id())) wm = WorkloadManager(get_cpu(), MockCgroupManager(), NoopCpuAllocator()) self.assertTrue(wm.is_isolated(uuid.uuid4()))
def test_ip_fallback(self): w_a = get_test_workload("a", 3, STATIC) w_b = get_test_workload("b", 2, STATIC) w_c = get_test_workload("c", 1, STATIC) w_d = get_test_workload("d", 2, STATIC) cpu = get_cpu(package_count=2, cores_per_package=2, threads_per_core=2) allocator = FallbackCpuAllocator(CrashingAllocator(), IntegerProgramCpuAllocator()) workloads = {} workloads[w_a.get_id()] = w_a request = AllocateThreadsRequest(cpu, w_a.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() workloads[w_b.get_id()] = w_b request = AllocateThreadsRequest(cpu, w_b.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() request = AllocateThreadsRequest(cpu, "a", workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.free_threads(request).get_cpu() workloads.pop("a") workloads[w_c.get_id()] = w_c request = AllocateThreadsRequest(cpu, w_c.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() request = AllocateThreadsRequest(cpu, "b", workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.free_threads(request).get_cpu() workloads.pop("b") workloads[w_d.get_id()] = w_d request = AllocateThreadsRequest(cpu, w_d.get_id(), workloads, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request).get_cpu() self.assertEqual(3, len(cpu.get_claimed_threads())) self.assertEqual(6, allocator.get_fallback_allocator_calls_count())
def test_no_cross_packages_placement_no_bad_affinity_ip(self): w_a = get_test_workload("a", 3, STATIC) w_b = get_test_workload("b", 2, STATIC) w_c = get_test_workload("c", 1, STATIC) w_d = get_test_workload("d", 2, STATIC) cpu = get_cpu(package_count=2, cores_per_package=2, threads_per_core=2) workload_manager = WorkloadManager(cpu, MockCgroupManager(), IntegerProgramCpuAllocator()) workload_manager.add_workload(w_a) workload_manager.add_workload(w_b) workload_manager.add_workload(w_c) workload_manager.add_workload(w_d) self.assertEqual( 0, len(get_cross_package_violations(workload_manager.get_cpu()))) self.assertEqual(0, len(workload_manager.get_cpu().get_empty_threads()))
def test_assign_two_workloads_empty_cpu_ip(self): """ Workload 0: 2 threads --> (p:0 c:0 t:0) (p:0 c:1 t:0) Workload 1: 1 thread --> (p:1 c:0 t:0) """ for allocator in [ IntegerProgramCpuAllocator(), forecast_ip_alloc_simple ]: cpu = get_cpu() w0 = get_test_workload(uuid.uuid4(), 2, STATIC) w1 = get_test_workload(uuid.uuid4(), 1, STATIC) request0 = AllocateThreadsRequest(cpu, w0.get_id(), {w0.get_id(): w0}, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request0).get_cpu() request1 = AllocateThreadsRequest(cpu, w1.get_id(), { w0.get_id(): w0, w1.get_id(): w1 }, {}, DEFAULT_TEST_REQUEST_METADATA) cpu = allocator.assign_threads(request1).get_cpu() self.assertEqual(3, len(cpu.get_claimed_threads())) ids_per_socket = [] for pid, p in enumerate(cpu.get_packages()): r = [] for cid, c in enumerate(p.get_cores()): for tid, t in enumerate(c.get_threads()): if t.is_claimed(): self.assertEqual(1, len(t.get_workload_ids())) r.append((t.get_workload_ids()[0], c.get_id())) ids_per_socket.append(r) for r in ids_per_socket: # each workload should be on a different socket self.assertEqual(1, len(set([e[0] for e in r]))) # assigned threads should be on different coreds core_ids = [e[1] for e in r] self.assertEqual(len(set(core_ids)), len(core_ids))
def __assign_workload(cpu, workload): request = get_no_usage_threads_request(cpu, [workload]) return IntegerProgramCpuAllocator().assign_threads(request).get_cpu()
def __assign_workload(cpu, workload): request = AllocateThreadsRequest(cpu, workload.get_id(), {workload.get_id(): workload}, {}, DEFAULT_TEST_REQUEST_METADATA) return IntegerProgramCpuAllocator().assign_threads(request).get_cpu()
def __get_default_workload_manager(): cpu = get_cpu() return WorkloadManager(cpu, MockCgroupManager(), IntegerProgramCpuAllocator())
def test_cache_ip(self): """ [add a=2, add b=2, remove b=2, add c=2, remove a=2, add d=2] should lead to the following cache entries: (state=[], req=[2]) (state=[2], req=[2,2]) (state=[2,2], req=[2,0]) [cache hit] [cache hit] (state=[2,2], req=[2,2]) but different layout """ cpu = get_cpu() allocator = IntegerProgramCpuAllocator(cpu) allocator.assign_threads(Workload("a", 2, STATIC)) self.assertEqual(1, len(allocator._IntegerProgramCpuAllocator__cache)) allocator.assign_threads(Workload("b", 2, STATIC)) self.assertEqual(2, len(allocator._IntegerProgramCpuAllocator__cache)) allocator.free_threads("b") self.assertEqual(3, len(allocator._IntegerProgramCpuAllocator__cache)) allocator.assign_threads(Workload("c", 2, STATIC)) self.assertEqual(3, len(allocator._IntegerProgramCpuAllocator__cache)) allocator.free_threads("a") self.assertEqual(4, len(allocator._IntegerProgramCpuAllocator__cache)) allocator.assign_threads(Workload("d", 2, STATIC)) self.assertEqual(5, len(allocator._IntegerProgramCpuAllocator__cache))
OVERSUBSCRIBED_THREADS_KEY, STATIC_ALLOCATED_SIZE_KEY, BURST_ALLOCATED_SIZE_KEY, \ BURST_REQUESTED_SIZE_KEY, ALLOCATED_SIZE_KEY, UNALLOCATED_SIZE_KEY from titus_isolate.model.processor.config import get_cpu from titus_isolate.model.processor.utils import DEFAULT_TOTAL_THREAD_COUNT, is_cpu_full from titus_isolate.monitor.oversubscribe_free_thread_provider import OversubscribeFreeThreadProvider from titus_isolate.utils import set_config_manager, set_workload_monitor_manager config_logs(logging.DEBUG) set_config_manager(ConfigManager(TestPropertyProvider({}))) set_workload_monitor_manager(TestWorkloadMonitorManager()) forecast_ip_alloc_simple = ForecastIPCpuAllocator( TestCpuUsagePredictorManager(), ConfigManager(TestPropertyProvider({})), OversubscribeFreeThreadProvider(DEFAULT_TOTAL_THRESHOLD)) LEGACY_ALLOCATORS = [IntegerProgramCpuAllocator(), GreedyCpuAllocator()] OVERSUBSCRIBING_ALLOCATORS = [forecast_ip_alloc_simple] ALLOCATORS = LEGACY_ALLOCATORS + OVERSUBSCRIBING_ALLOCATORS class TestWorkloadManager(unittest.TestCase): def test_single_static_workload_lifecycle(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) # Add workload
self.pod = None def set_pod(self, pod: V1Pod): self.pod = pod def get_pod(self, pod_name: str) -> Optional[V1Pod]: return self.pod forecast_ip_alloc_simple = ForecastIPCpuAllocator( TestCpuUsagePredictorManager(), ConfigManager(TestPropertyProvider({})), OversubscribeFreeThreadProvider(0.1)) ALLOCATORS = [ NaiveCpuAllocator(), IntegerProgramCpuAllocator(), GreedyCpuAllocator(), forecast_ip_alloc_simple ] OVER_ALLOCATORS = [NaiveCpuAllocator(), forecast_ip_alloc_simple] set_workload_monitor_manager(TestWorkloadMonitorManager()) class TestCpu(unittest.TestCase): def test_assign_one_thread_empty_cpu(self): """ Workload 0: 1 thread --> (p:0 c:0 t:0) """ for allocator in ALLOCATORS: cpu = get_cpu() self.assertEqual(DEFAULT_TOTAL_THREAD_COUNT,