Skip to content

Commit 4b34960

Browse files
authored
Merge pull request #7 from gosuda/test/tla-retire-prefix
test(tla): EPaxosRetirePrefix fold domination
2 parents db4d0a5 + 8c4e9ee commit 4b34960

5 files changed

Lines changed: 155 additions & 0 deletions

File tree

epaxos/performance_benchmark_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,83 @@ func residentInstanceBytes(inst *instance) uintptr {
328328
}
329329
return bytes
330330
}
331+
332+
333+
func growResidentNode(b *testing.B, n int) *RawNode {
334+
b.Helper()
335+
rn, err := NewRawNode(Config{ID: 1, Voters: makeIDs(3)})
336+
if err != nil {
337+
b.Fatal(err)
338+
}
339+
key := []byte("bench-key")
340+
for i := 1; i <= n; i++ {
341+
ref := InstanceRef{Conf: 1, Replica: 1, Instance: InstanceNum(i)}
342+
rec := InstanceRecord{
343+
Ref: ref, Status: StatusCommitted, Seq: uint64(i), Ballot: Ballot{Replica: 1},
344+
Deps: rn.q.deps(), Command: Command{Payload: []byte("x"), ConflictKeys: [][]byte{key}},
345+
}
346+
rec.Checksum = ChecksumRecord(rec)
347+
rn.installInstance(&instance{rec: rec, phase: phaseCommitted})
348+
}
349+
return rn
350+
}
351+
352+
func BenchmarkComputeAttrsResident1k(b *testing.B) {
353+
rn := growResidentNode(b, 1000)
354+
cmd := Command{Payload: []byte("y"), ConflictKeys: [][]byte{[]byte("bench-key")}}
355+
exclude := InstanceRef{Conf: 1, Replica: 1, Instance: 1001}
356+
b.ReportAllocs()
357+
b.ResetTimer()
358+
for i := 0; i < b.N; i++ {
359+
_ = rn.computeAttrs(cmd, exclude)
360+
}
361+
}
362+
363+
func BenchmarkComputeAttrsResident100k(b *testing.B) {
364+
if testing.Short() {
365+
b.Skip("100k resident bench")
366+
}
367+
rn := growResidentNode(b, 100000)
368+
cmd := Command{Payload: []byte("y"), ConflictKeys: [][]byte{[]byte("bench-key")}}
369+
exclude := InstanceRef{Conf: 1, Replica: 1, Instance: 100001}
370+
b.ReportAllocs()
371+
b.ResetTimer()
372+
for i := 0; i < b.N; i++ {
373+
_ = rn.computeAttrs(cmd, exclude)
374+
}
375+
}
376+
377+
func BenchmarkStepPreAcceptGrown(b *testing.B) {
378+
rn := growResidentNode(b, 1000)
379+
b.ReportAllocs()
380+
b.ResetTimer()
381+
for i := 0; i < b.N; i++ {
382+
ref := InstanceRef{Conf: 1, Replica: 2, Instance: InstanceNum(i + 1)}
383+
cmd := Command{ID: CommandID{Client: 9, Sequence: uint64(i + 1)}, Payload: []byte("z"), ConflictKeys: [][]byte{[]byte("bench-key")}}
384+
msg := Message{Type: MsgPreAccept, From: 2, To: 1, Ref: ref, Ballot: Ballot{Replica: 2}, Command: cmd}
385+
_ = rn.Step(msg)
386+
}
387+
}
388+
389+
func BenchmarkRetireExecuted(b *testing.B) {
390+
b.ReportAllocs()
391+
for i := 0; i < b.N; i++ {
392+
b.StopTimer()
393+
rn, err := NewRawNode(Config{ID: 1, Voters: makeIDs(3), RetainExecutedPerLane: 8})
394+
if err != nil {
395+
b.Fatal(err)
396+
}
397+
for j := 1; j <= 64; j++ {
398+
ref := InstanceRef{Conf: 1, Replica: 1, Instance: InstanceNum(j)}
399+
rec := InstanceRecord{
400+
Ref: ref, Status: StatusExecuted, Seq: uint64(j), Ballot: Ballot{Replica: 1},
401+
Deps: rn.q.deps(), Command: Command{Payload: []byte("x"), ConflictKeys: [][]byte{[]byte("k")}},
402+
}
403+
rec.Checksum = ChecksumRecord(rec)
404+
rn.installInstance(&instance{rec: rec, phase: phaseCommitted})
405+
rn.executed.add(ref)
406+
}
407+
b.StartTimer()
408+
rn.retireExecuted()
409+
}
410+
}

tests/tla_model_check.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ for cfg in tla/KVOmissionRecovery.cfg; do
190190
done
191191

192192
run_tlc tla/Quorum.tla tla/Quorum.cfg
193+
194+
for cfg in tla/EPaxosRetirePrefix.cfg; do
195+
run_tlc tla/EPaxosRetirePrefix.tla "$cfg"
196+
done
197+
193198
for cfg in tla/EPaxosVoterBootstrapSize1.cfg tla/EPaxosVoterBootstrapSize2.cfg tla/EPaxosVoterBootstrapSize3.cfg tla/EPaxosVoterBootstrapSize4.cfg tla/EPaxosVoterBootstrapSize5.cfg tla/EPaxosVoterBootstrapSize6.cfg tla/EPaxosVoterBootstrapCrashPrefix.cfg tla/EPaxosVoterBootstrapRace.cfg tla/EPaxosVoterBootstrapFair.cfg; do
194199
run_tlc tla/EPaxosVoterBootstrap.tla "$cfg"
195200
done

tests/tla_model_check_runner.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
)
2929

3030
FAST_PROFILE = (
31+
("tla/EPaxosRetirePrefix.tla", "tla/EPaxosRetirePrefix.cfg"),
3132
("tla/ReadyAdvance.tla", "tla/ReadyAdvance.cfg"),
3233
("tla/ReadyAdvance.tla", "tla/ReadyAdvanceCapped.cfg"),
3334
("tla/Quorum.tla", "tla/Quorum.cfg"),
@@ -46,6 +47,7 @@
4647
)
4748

4849
FULL_PROFILE = (
50+
("tla/EPaxosRetirePrefix.tla", "tla/EPaxosRetirePrefix.cfg"),
4951
*(("tla/EPaxos.tla", cfg) for cfg in ("tla/EPaxos.cfg", "tla/EPaxosKVConflict.cfg", "tla/EPaxosThreeReplica.cfg")),
5052
*(("tla/ReadyAdvance.tla", cfg) for cfg in ("tla/ReadyAdvance.cfg", "tla/ReadyAdvanceCapped.cfg")),
5153
*(("tla/EPaxosResponses.tla", cfg) for cfg in ("tla/EPaxosResponses.cfg", "tla/EPaxosResponsesFive.cfg")),

tla/EPaxosRetirePrefix.cfg

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
SPECIFICATION Spec
2+
CONSTANTS
3+
MaxI = 3
4+
MaxS = 3
5+
Lanes = {l1, l2}
6+
INVARIANT Inv
7+
CHECK_DEADLOCK FALSE

tla/EPaxosRetirePrefix.tla

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---- MODULE EPaxosRetirePrefix ----
2+
EXTENDS Naturals, FiniteSets
3+
4+
\* Two lanes, instances 1..MaxI. Folding a present instance advances folded
5+
\* and retains max seq. Invariant: folded instances are absent from present,
6+
\* and retiredMaxSeq is monotonic and bounded.
7+
8+
CONSTANTS MaxI, MaxS, Lanes
9+
10+
VARIABLES seq, present, folded, retiredMaxSeq
11+
12+
vars == <<seq, present, folded, retiredMaxSeq>>
13+
14+
TypeOK ==
15+
/\ seq \in [Lanes -> [1..MaxI -> 1..MaxS]]
16+
/\ present \in [Lanes -> SUBSET (1..MaxI)]
17+
/\ folded \in [Lanes -> 0..MaxI]
18+
/\ retiredMaxSeq \in [Lanes -> 0..MaxS]
19+
20+
Init ==
21+
/\ seq = [lane \in Lanes |-> [i \in 1..MaxI |-> 1]]
22+
/\ present = [lane \in Lanes |-> {}]
23+
/\ folded = [lane \in Lanes |-> 0]
24+
/\ retiredMaxSeq = [lane \in Lanes |-> 0]
25+
26+
Install(lane, i, s) ==
27+
/\ i \in 1..MaxI
28+
/\ s \in 1..MaxS
29+
/\ i > folded[lane]
30+
/\ present' = [present EXCEPT ![lane] = @ \union {i}]
31+
/\ seq' = [seq EXCEPT ![lane][i] = s]
32+
/\ UNCHANGED <<folded, retiredMaxSeq>>
33+
34+
FoldOne(lane) ==
35+
/\ folded[lane] < MaxI
36+
/\ (folded[lane] + 1) \in present[lane]
37+
/\ LET n == folded[lane] + 1 IN
38+
/\ folded' = [folded EXCEPT ![lane] = n]
39+
/\ present' = [present EXCEPT ![lane] = @ \ {n}]
40+
/\ retiredMaxSeq' =
41+
[retiredMaxSeq EXCEPT ![lane] =
42+
IF seq[lane][n] > retiredMaxSeq[lane] THEN seq[lane][n] ELSE retiredMaxSeq[lane]]
43+
/\ UNCHANGED seq
44+
45+
Next ==
46+
\/ \E lane \in Lanes, i \in 1..MaxI, s \in 1..MaxS: Install(lane, i, s)
47+
\/ \E lane \in Lanes: FoldOne(lane)
48+
49+
Spec == Init /\ [][Next]_vars
50+
51+
\* Folded prefix is disjoint from present; retired max seq never exceeds MaxS
52+
\* and is at least the seq of any still-folded boundary instance when defined.
53+
Inv ==
54+
/\ TypeOK
55+
/\ \A lane \in Lanes:
56+
/\ \A i \in present[lane]: i > folded[lane]
57+
/\ retiredMaxSeq[lane] \in 0..MaxS
58+
/\ \A i \in 1..MaxI:
59+
(i <= folded[lane]) => (seq[lane][i] <= retiredMaxSeq[lane])
60+
61+
====

0 commit comments

Comments
 (0)