Skip to content

Commit e1bd8bb

Browse files
committedAug 24, 2023
reduce state transition allocations
1 parent 66acf1d commit e1bd8bb

File tree

2 files changed

+27
-34
lines changed

2 files changed

+27
-34
lines changed
 

‎states.go

+17-27
Original file line numberDiff line numberDiff line change
@@ -72,37 +72,26 @@ func (sr *stateRepresentation) FindHandler(ctx context.Context, trigger Trigger,
7272
}
7373

7474
func (sr *stateRepresentation) findHandler(ctx context.Context, trigger Trigger, args ...any) (result triggerBehaviourResult, ok bool) {
75-
var (
76-
possibleBehaviours []triggerBehaviour
77-
)
78-
if possibleBehaviours, ok = sr.TriggerBehaviours[trigger]; !ok {
75+
possibleBehaviours, ok := sr.TriggerBehaviours[trigger]
76+
if !ok {
7977
return
8078
}
81-
allResults := make([]triggerBehaviourResult, 0, len(possibleBehaviours))
79+
var unmet []string
8280
for _, behaviour := range possibleBehaviours {
83-
allResults = append(allResults, triggerBehaviourResult{
84-
Handler: behaviour,
85-
UnmetGuardConditions: behaviour.UnmetGuardConditions(ctx, args...),
86-
})
87-
}
88-
metResults := make([]triggerBehaviourResult, 0, len(allResults))
89-
unmetResults := make([]triggerBehaviourResult, 0, len(allResults))
90-
for _, result := range allResults {
91-
if len(result.UnmetGuardConditions) == 0 {
92-
metResults = append(metResults, result)
93-
} else {
94-
unmetResults = append(unmetResults, result)
81+
unmet = behaviour.UnmetGuardConditions(ctx, unmet[:0], args...)
82+
if len(unmet) == 0 {
83+
if result.Handler != nil && len(result.UnmetGuardConditions) == 0 {
84+
panic(fmt.Sprintf("stateless: Multiple permitted exit transitions are configured from state '%v' for trigger '%v'. Guard clauses must be mutually exclusive.", sr.State, trigger))
85+
}
86+
result.Handler = behaviour
87+
result.UnmetGuardConditions = nil
88+
} else if result.Handler == nil {
89+
result.Handler = behaviour
90+
result.UnmetGuardConditions = make([]string, len(unmet))
91+
copy(result.UnmetGuardConditions, unmet)
9592
}
9693
}
97-
if len(metResults) > 1 {
98-
panic(fmt.Sprintf("stateless: Multiple permitted exit transitions are configured from state '%v' for trigger '%v'. Guard clauses must be mutually exclusive.", sr.State, trigger))
99-
}
100-
if len(metResults) == 1 {
101-
result, ok = metResults[0], true
102-
} else if len(unmetResults) > 0 {
103-
result, ok = unmetResults[0], false
104-
}
105-
return
94+
return result, result.Handler != nil && len(result.UnmetGuardConditions) == 0
10695
}
10796

10897
func (sr *stateRepresentation) Activate(ctx context.Context) error {
@@ -210,9 +199,10 @@ func (sr *stateRepresentation) AddTriggerBehaviour(tb triggerBehaviour) {
210199
}
211200

212201
func (sr *stateRepresentation) PermittedTriggers(ctx context.Context, args ...any) (triggers []Trigger) {
202+
var unmet []string
213203
for key, value := range sr.TriggerBehaviours {
214204
for _, tb := range value {
215-
if len(tb.UnmetGuardConditions(ctx, args...)) == 0 {
205+
if len(tb.UnmetGuardConditions(ctx, unmet[:0], args...)) == 0 {
216206
triggers = append(triggers, key)
217207
break
218208
}

‎triggers.go

+10-7
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,22 @@ func (t transitionGuard) GuardConditionMet(ctx context.Context, args ...any) boo
6161
return true
6262
}
6363

64-
func (t transitionGuard) UnmetGuardConditions(ctx context.Context, args ...any) []string {
65-
unmet := make([]string, 0, len(t.Guards))
64+
func (t transitionGuard) UnmetGuardConditions(ctx context.Context, buf []string, args ...any) []string {
65+
if cap(buf) < len(t.Guards) {
66+
buf = make([]string, 0, len(t.Guards))
67+
}
68+
buf = buf[:0]
6669
for _, guard := range t.Guards {
6770
if !guard.Guard(ctx, args...) {
68-
unmet = append(unmet, guard.Description.String())
71+
buf = append(buf, guard.Description.String())
6972
}
7073
}
71-
return unmet
74+
return buf
7275
}
7376

7477
type triggerBehaviour interface {
7578
GuardConditionMet(context.Context, ...any) bool
76-
UnmetGuardConditions(context.Context, ...any) []string
79+
UnmetGuardConditions(context.Context, []string, ...any) []string
7780
GetTrigger() Trigger
7881
}
7982

@@ -90,8 +93,8 @@ func (t *baseTriggerBehaviour) GuardConditionMet(ctx context.Context, args ...an
9093
return t.Guard.GuardConditionMet(ctx, args...)
9194
}
9295

93-
func (t *baseTriggerBehaviour) UnmetGuardConditions(ctx context.Context, args ...any) []string {
94-
return t.Guard.UnmetGuardConditions(ctx, args...)
96+
func (t *baseTriggerBehaviour) UnmetGuardConditions(ctx context.Context, buf []string, args ...any) []string {
97+
return t.Guard.UnmetGuardConditions(ctx, buf, args...)
9598
}
9699

97100
type ignoredTriggerBehaviour struct {

0 commit comments

Comments
 (0)
Please sign in to comment.