|
30 | 30 | "google-cloud-retail": 5, |
31 | 31 | } |
32 | 32 |
|
33 | | -def get_weighted_package_list(): |
34 | | - """Audits the packages directory and expands the list based on weights.""" |
| 33 | +def get_batches(): |
| 34 | + """Distributes packages into batches using a greedy load-balancing algorithm.""" |
35 | 35 | raw_paths = sorted(glob.glob("packages/*")) |
36 | 36 | package_paths = [p for p in raw_paths if os.path.isdir(p)] |
37 | 37 |
|
38 | | - weighted_list = [] |
| 38 | + packages_with_weights = [] |
| 39 | + total_weight = 0 |
39 | 40 | for path in package_paths: |
40 | 41 | pkg_name = os.path.basename(path) |
41 | 42 | weight = PACKAGE_WEIGHTS.get(pkg_name, 1) |
| 43 | + packages_with_weights.append((path, weight)) |
| 44 | + total_weight += weight |
42 | 45 |
|
43 | | - for _ in range(weight): |
44 | | - weighted_list.append(path) |
45 | | - |
46 | | - return weighted_list |
47 | | - |
48 | | -def get_batch_indices(): |
49 | | - """Returns a JSON string of the array of batch indices for GitHub Actions matrix.""" |
50 | | - weighted_list = get_weighted_package_list() |
51 | | - total_units = len(weighted_list) |
52 | | - num_batches = math.ceil(total_units / BATCH_SIZE) |
53 | | - |
| 46 | + num_batches = math.ceil(total_weight / BATCH_SIZE) |
54 | 47 | if num_batches == 0: |
55 | 48 | num_batches = 1 |
| 49 | + |
| 50 | + # Sort packages by weight descending (Longest Processing Time first) |
| 51 | + packages_with_weights.sort(key=lambda x: x[1], reverse=True) |
| 52 | + |
| 53 | + batches = [[] for _ in range(num_batches)] |
| 54 | + batch_weights = [0] * num_batches |
| 55 | + |
| 56 | + for path, weight in packages_with_weights: |
| 57 | + # Greedily assign the package to the currently least-loaded batch |
| 58 | + min_idx = batch_weights.index(min(batch_weights)) |
| 59 | + batches[min_idx].append(path) |
| 60 | + batch_weights[min_idx] += weight |
| 61 | + |
| 62 | + return batches |
56 | 63 |
|
57 | | - return json.dumps(list(range(num_batches))) |
| 64 | +def get_batch_indices(): |
| 65 | + """Returns a JSON string of the array of batch indices for GitHub Actions matrix.""" |
| 66 | + batches = get_batches() |
| 67 | + return json.dumps(list(range(len(batches)))) |
58 | 68 |
|
59 | 69 | def get_batch_slice(batch_index): |
60 | 70 | """Returns a space-separated string of unique package paths for a specific batch index.""" |
61 | | - weighted_list = get_weighted_package_list() |
62 | | - total_units = len(weighted_list) |
63 | | - start_idx = batch_index * BATCH_SIZE |
64 | | - |
65 | | - if start_idx >= total_units: |
| 71 | + batches = get_batches() |
| 72 | + if batch_index < 0 or batch_index >= len(batches): |
66 | 73 | return "" |
67 | | - |
68 | | - slice_window = weighted_list[start_idx : start_idx + BATCH_SIZE] |
69 | | - |
70 | | - unique_packages = [] |
71 | | - for pkg in slice_window: |
72 | | - if pkg not in unique_packages: |
73 | | - unique_packages.append(pkg) |
74 | | - |
75 | | - return " ".join(unique_packages) |
| 74 | + return " ".join(batches[batch_index]) |
76 | 75 |
|
77 | 76 | if __name__ == "__main__": |
78 | 77 | if len(sys.argv) > 1 and sys.argv[1] == "--count": |
|
0 commit comments