187 lines
6.9 KiB
Java
187 lines
6.9 KiB
Java
package defects.xen.unit;
|
||
|
||
import java.util.*;
|
||
|
||
/**
|
||
* xen-0001: Xen credit2 balance_load() O(V²) VCPU swap-search.
|
||
*
|
||
* Models the inner double-loop in balance_load() (credit2.c:2835–2861).
|
||
* The defective version iterates all VCPUs on lrqd × orqd to find the best
|
||
* (push, pull) swap pair. The fixed version maintains runqueue lists sorted
|
||
* by avgload so the best pair is found in O(V) time.
|
||
*/
|
||
public class Xen0001CreditBalanceLoadAlgorithm {
|
||
|
||
public static class Vcpu {
|
||
final int id;
|
||
long avgload;
|
||
boolean migratable;
|
||
|
||
Vcpu(int id, long avgload, boolean migratable) {
|
||
this.id = id;
|
||
this.avgload = avgload;
|
||
this.migratable = migratable;
|
||
}
|
||
}
|
||
|
||
public static class SwapPair {
|
||
final Vcpu push; // from lrqd
|
||
final Vcpu pull; // from orqd (may be null for push-only)
|
||
final long loadDelta; // abs delta after swap
|
||
|
||
SwapPair(Vcpu push, Vcpu pull, long loadDelta) {
|
||
this.push = push;
|
||
this.pull = pull;
|
||
this.loadDelta = loadDelta;
|
||
}
|
||
}
|
||
|
||
// -----------------------------------------------------------------------
|
||
// Defective: O(V²) — full cross-product as in credit2.c
|
||
// -----------------------------------------------------------------------
|
||
public static class DefectiveBalanceLoad {
|
||
public int comparisons;
|
||
|
||
public SwapPair findBestSwap(List<Vcpu> lrqdSvc, List<Vcpu> orqdSvc,
|
||
long lLoad, long oLoad) {
|
||
comparisons = 0;
|
||
SwapPair best = null;
|
||
long bestDelta = Math.abs(lLoad - oLoad);
|
||
|
||
for (Vcpu push : lrqdSvc) {
|
||
if (!push.migratable) continue;
|
||
|
||
for (Vcpu pull : orqdSvc) {
|
||
comparisons++;
|
||
if (!pull.migratable) continue;
|
||
|
||
// delta after swapping push→orqd and pull→lrqd
|
||
long newL = lLoad - push.avgload + pull.avgload;
|
||
long newO = oLoad - pull.avgload + push.avgload;
|
||
long delta = Math.abs(newL - newO);
|
||
if (delta < bestDelta) {
|
||
bestDelta = delta;
|
||
best = new SwapPair(push, pull, delta);
|
||
}
|
||
}
|
||
|
||
// push-only consideration
|
||
long newL = lLoad - push.avgload;
|
||
long newO = oLoad + push.avgload;
|
||
long delta = Math.abs(newL - newO);
|
||
if (delta < bestDelta) {
|
||
bestDelta = delta;
|
||
best = new SwapPair(push, null, delta);
|
||
}
|
||
}
|
||
return best;
|
||
}
|
||
}
|
||
|
||
// -----------------------------------------------------------------------
|
||
// Fixed: O(V) — pick heaviest push + lightest pull from sorted lists
|
||
// -----------------------------------------------------------------------
|
||
public static class FixedBalanceLoad {
|
||
public int comparisons;
|
||
|
||
/**
|
||
* Both lrqdSvc and orqdSvc are assumed sorted descending by avgload
|
||
* (maintained at VCPU assign/weight-update time).
|
||
* Scan from highest-weight end for push, lowest-weight end for pull.
|
||
*/
|
||
public SwapPair findBestSwap(List<Vcpu> lrqdSvcSorted,
|
||
List<Vcpu> orqdSvcSorted,
|
||
long lLoad, long oLoad) {
|
||
comparisons = 0;
|
||
long currentDelta = Math.abs(lLoad - oLoad);
|
||
|
||
// Find heaviest migratable push candidate
|
||
Vcpu bestPush = null;
|
||
for (Vcpu v : lrqdSvcSorted) {
|
||
comparisons++;
|
||
if (v.migratable) { bestPush = v; break; }
|
||
}
|
||
if (bestPush == null) return null;
|
||
|
||
// Find lightest migratable pull candidate (from end of sorted list)
|
||
Vcpu bestPull = null;
|
||
for (int i = orqdSvcSorted.size() - 1; i >= 0; i--) {
|
||
comparisons++;
|
||
Vcpu v = orqdSvcSorted.get(i);
|
||
if (v.migratable) { bestPull = v; break; }
|
||
}
|
||
|
||
// Evaluate push+pull swap
|
||
SwapPair best = null;
|
||
if (bestPull != null) {
|
||
long newL = lLoad - bestPush.avgload + bestPull.avgload;
|
||
long newO = oLoad - bestPull.avgload + bestPush.avgload;
|
||
long delta = Math.abs(newL - newO);
|
||
if (delta < currentDelta) {
|
||
best = new SwapPair(bestPush, bestPull, delta);
|
||
currentDelta = delta;
|
||
}
|
||
}
|
||
// Evaluate push-only
|
||
long newL = lLoad - bestPush.avgload;
|
||
long newO = oLoad + bestPush.avgload;
|
||
long delta = Math.abs(newL - newO);
|
||
if (delta < currentDelta) {
|
||
best = new SwapPair(bestPush, null, delta);
|
||
}
|
||
return best;
|
||
}
|
||
}
|
||
|
||
// -----------------------------------------------------------------------
|
||
// Helpers
|
||
// -----------------------------------------------------------------------
|
||
|
||
/** Build a list of V VCPUs with loads evenly spread, all migratable. */
|
||
public static List<Vcpu> buildSvcList(int count, long baseLoad, boolean sorted) {
|
||
List<Vcpu> list = new ArrayList<>();
|
||
for (int i = 0; i < count; i++) {
|
||
list.add(new Vcpu(i, baseLoad + i * 10, true));
|
||
}
|
||
if (sorted) {
|
||
list.sort((a, b) -> Long.compare(b.avgload, a.avgload));
|
||
}
|
||
return list;
|
||
}
|
||
|
||
/** Compute total load for a VCPU list. */
|
||
public static long totalLoad(List<Vcpu> svc) {
|
||
return svc.stream().mapToLong(v -> v.avgload).sum();
|
||
}
|
||
|
||
public static void main(String[] args) {
|
||
System.out.println("xen-0001: credit2 balance_load O(V^2) vs O(V)");
|
||
System.out.println("=".repeat(55));
|
||
|
||
int[] sizes = {10, 50, 100, 200};
|
||
DefectiveBalanceLoad defective = new DefectiveBalanceLoad();
|
||
FixedBalanceLoad fixed = new FixedBalanceLoad();
|
||
|
||
System.out.printf("%-8s %-12s %-12s %-8s%n",
|
||
"V/rqd", "Defect ops", "Fixed ops", "Ratio");
|
||
|
||
for (int v : sizes) {
|
||
List<Vcpu> lrqd = buildSvcList(v, 100, false);
|
||
List<Vcpu> orqd = buildSvcList(v, 50, false);
|
||
long lLoad = totalLoad(lrqd);
|
||
long oLoad = totalLoad(orqd);
|
||
|
||
defective.findBestSwap(lrqd, orqd, lLoad, oLoad);
|
||
int defectOps = defective.comparisons;
|
||
|
||
List<Vcpu> lrqdSorted = buildSvcList(v, 100, true);
|
||
List<Vcpu> orqdSorted = buildSvcList(v, 50, true);
|
||
fixed.findBestSwap(lrqdSorted, orqdSorted, lLoad, oLoad);
|
||
int fixedOps = fixed.comparisons;
|
||
|
||
double ratio = (double) defectOps / fixedOps;
|
||
System.out.printf("%-8d %-12d %-12d %.1f×%n",
|
||
v, defectOps, fixedOps, ratio);
|
||
}
|
||
}
|
||
}
|