whitepaper: 352/169 — wave4 MEDIUM (hadoop/hbase/nova/neutron/openstack) + fix odl-0002 dup
This commit is contained in:
parent
9934133dcf
commit
835ae73b0f
82 changed files with 5931 additions and 6 deletions
149
defects/wasmer/unit/SignalVecDedupTest.java
Normal file
149
defects/wasmer/unit/SignalVecDedupTest.java
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
package unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* wasmer-0002: WasiThread signal Vec<Signal> O(n) dedup on every signal delivery.
|
||||
*
|
||||
* Models the thread.signal() hot path:
|
||||
* slow: signals stored as Vec<Signal>, contains() used for dedup => O(n) per insert
|
||||
* fast: signals stored as long bitmask => O(1) insert with automatic dedup
|
||||
*
|
||||
* Also models has_signal(query: &[Signal]):
|
||||
* slow: O(S * Q) nested loop (S=pending signals, Q=query len)
|
||||
* fast: O(Q) build query mask + O(1) bitmask AND
|
||||
*
|
||||
* The signal domain is bounded to POSIX signals 1..31 (~30 distinct values).
|
||||
* Benchmark: S signals pending, Q queries, N deliver calls.
|
||||
* slow: O(S) per deliver (contains check) + O(S*Q) per has_signal call
|
||||
* fast: O(1) per deliver + O(Q) per has_signal call
|
||||
*/
|
||||
public class SignalVecDedupTest {
|
||||
|
||||
static final int MAX_SIGNAL = 31; // POSIX signals 1..31
|
||||
|
||||
/** SLOW: Vec<Signal> with linear contains for dedup */
|
||||
static class SlowSignalSet {
|
||||
final List<Integer> signals = new ArrayList<>();
|
||||
|
||||
/** Returns ops performed */
|
||||
long signal(int sig) {
|
||||
long ops = 0;
|
||||
for (int s : signals) { ops++; if (s == sig) return ops; } // contains check
|
||||
signals.add(sig);
|
||||
return ops + 1; // add op
|
||||
}
|
||||
|
||||
/** Returns ops performed */
|
||||
long hasSignal(int[] query) {
|
||||
long ops = 0;
|
||||
for (int s : signals) {
|
||||
for (int q : query) {
|
||||
ops++;
|
||||
if (s == q) return ops;
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
}
|
||||
|
||||
/** FAST: long bitmask — O(1) insert and O(Q) query */
|
||||
static class FastSignalSet {
|
||||
long mask = 0L;
|
||||
|
||||
/** Returns ops performed (always 1: single bit-set) */
|
||||
long signal(int sig) {
|
||||
mask |= (1L << sig);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Returns ops performed: Q bit-set ops + 1 AND */
|
||||
long hasSignal(int[] query) {
|
||||
long qmask = 0L;
|
||||
for (int q : query) qmask |= (1L << q);
|
||||
return query.length + 1; // Q ops to build mask + 1 AND
|
||||
}
|
||||
}
|
||||
|
||||
static long benchSignal(boolean slow, int N, int S) {
|
||||
// Deliver N signals cycling through S distinct signal values
|
||||
SlowSignalSet slowSet = slow ? new SlowSignalSet() : null;
|
||||
FastSignalSet fastSet = slow ? null : new FastSignalSet();
|
||||
|
||||
long totalOps = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
int sig = (i % S) + 1; // signals 1..S
|
||||
if (slow) totalOps += slowSet.signal(sig);
|
||||
else totalOps += fastSet.signal(sig);
|
||||
}
|
||||
return totalOps;
|
||||
}
|
||||
|
||||
static long benchHasSignal(boolean slow, int S, int Q, int calls) {
|
||||
// S signals pending, query Q signals, repeat 'calls' times
|
||||
SlowSignalSet slowSet = slow ? new SlowSignalSet() : null;
|
||||
FastSignalSet fastSet = slow ? null : new FastSignalSet();
|
||||
|
||||
// Pre-fill with S pending signals (signals 1..S)
|
||||
for (int s = 1; s <= S; s++) {
|
||||
if (slow) slowSet.signal(s); else fastSet.signal(s);
|
||||
}
|
||||
// Query for signals that are NOT pending (worst-case: full scan required)
|
||||
// Use signals S+1..S+Q (not in the pending set)
|
||||
int[] queryArr = new int[Q];
|
||||
for (int q = 0; q < Q; q++) queryArr[q] = S + q + 1;
|
||||
|
||||
long totalOps = 0;
|
||||
for (int c = 0; c < calls; c++) {
|
||||
if (slow) totalOps += slowSet.hasSignal(queryArr);
|
||||
else totalOps += fastSet.hasSignal(queryArr);
|
||||
}
|
||||
return totalOps;
|
||||
}
|
||||
|
||||
static void testSignal(String name, int N, int S, int minSpeedup) {
|
||||
long sOps = benchSignal(true, N, S);
|
||||
long fOps = benchSignal(false, N, S);
|
||||
|
||||
double speedup = (double) sOps / fOps;
|
||||
boolean pass = sOps >= fOps * minSpeedup;
|
||||
|
||||
System.out.printf(" signal %-42s slow=%,d fast=%,d speedup=%.1fx %s%n",
|
||||
name, sOps, fOps, speedup, pass ? "PASS" : "FAIL");
|
||||
assert pass : String.format(
|
||||
"signal %s: expected speedup >=%dx, got %.1fx", name, minSpeedup, speedup);
|
||||
}
|
||||
|
||||
static void testHasSignal(String name, int S, int Q, int calls, int minSpeedup) {
|
||||
long sOps = benchHasSignal(true, S, Q, calls);
|
||||
long fOps = benchHasSignal(false, S, Q, calls);
|
||||
|
||||
double speedup = (double) sOps / fOps;
|
||||
boolean pass = sOps >= fOps * minSpeedup;
|
||||
|
||||
System.out.printf(" has_sig %-42s slow=%,d fast=%,d speedup=%.1fx %s%n",
|
||||
name, sOps, fOps, speedup, pass ? "PASS" : "FAIL");
|
||||
assert pass : String.format(
|
||||
"has_signal %s: expected speedup >=%dx, got %.1fx", name, minSpeedup, speedup);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("wasmer-0002: Signal Vec dedup");
|
||||
System.out.println("=============================");
|
||||
System.out.println("-- signal() delivery --");
|
||||
|
||||
// S=30 signals: after all 30 are in the set, each new deliver scans ~30 items
|
||||
// vs O(1) bitmask. With N=1000 delivers cycling through 30: slow costs ~15000 ops.
|
||||
testSignal("N=100 S=30 minSpeedup=10x", 100, 30, 10);
|
||||
testSignal("N=1000 S=30 minSpeedup=10x", 1000, 30, 10);
|
||||
|
||||
System.out.println("-- has_signal() query --");
|
||||
// S=30 pending, Q=10 query: slow=S*Q=300 per call, fast=Q+1=11 per call => ~27x
|
||||
testHasSignal("S=30 Q=10 calls=100 minSpeedup=15x", 30, 10, 100, 15);
|
||||
testHasSignal("S=30 Q=30 calls=100 minSpeedup=15x", 30, 30, 100, 15);
|
||||
|
||||
System.out.println("=============================");
|
||||
System.out.println("ALL PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue