mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-10-27 05:26:56 +00:00
Reduce rule matching memory allocations
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package rule
|
||||
|
||||
import "github.com/sagernet/sing-box/adapter"
|
||||
|
||||
type ruleMatchState uint8
|
||||
|
||||
const (
|
||||
@@ -24,3 +26,23 @@ func (g ruleGroupMatch) mergeWith(other ruleGroupMatch) ruleGroupMatch {
|
||||
satisfied: g.satisfied | other.satisfied,
|
||||
}
|
||||
}
|
||||
|
||||
type ruleMatchSnapshot struct {
|
||||
ipCidrMatchSource bool
|
||||
ipCidrAcceptEmpty bool
|
||||
deferredIPCIDRMatchGroups uint8
|
||||
}
|
||||
|
||||
func snapshotRuleMatch(metadata *adapter.InboundContext) ruleMatchSnapshot {
|
||||
return ruleMatchSnapshot{
|
||||
ipCidrMatchSource: metadata.IPCIDRMatchSource,
|
||||
ipCidrAcceptEmpty: metadata.IPCIDRAcceptEmpty,
|
||||
deferredIPCIDRMatchGroups: metadata.DeferredIPCIDRMatchGroups,
|
||||
}
|
||||
}
|
||||
|
||||
func (s ruleMatchSnapshot) restore(metadata *adapter.InboundContext) {
|
||||
metadata.IPCIDRMatchSource = s.ipCidrMatchSource
|
||||
metadata.IPCIDRAcceptEmpty = s.ipCidrAcceptEmpty
|
||||
metadata.DeferredIPCIDRMatchGroups = s.deferredIPCIDRMatchGroups
|
||||
}
|
||||
|
||||
@@ -206,32 +206,32 @@ func (r *abstractLogicalRule) Match(metadata *adapter.InboundContext) bool {
|
||||
matched bool
|
||||
deferredGroups uint8
|
||||
)
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
if r.mode == C.LogicalTypeAnd {
|
||||
matched = true
|
||||
for _, rule := range r.rules {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleCache()
|
||||
if !rule.Match(&nestedMetadata) {
|
||||
metadata.ResetRuleCache()
|
||||
if !rule.Match(metadata) {
|
||||
matched = false
|
||||
deferredGroups = 0
|
||||
break
|
||||
}
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
} else {
|
||||
for _, rule := range r.rules {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleCache()
|
||||
if rule.Match(&nestedMetadata) {
|
||||
metadata.ResetRuleCache()
|
||||
if rule.Match(metadata) {
|
||||
matched = true
|
||||
if nestedMetadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
if metadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
deferredGroups = 0
|
||||
break
|
||||
}
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
if matched {
|
||||
metadata.DeferredIPCIDRMatchGroups |= deferredGroups
|
||||
}
|
||||
|
||||
@@ -52,12 +52,15 @@ func (r *RuleSetItem) Close() error {
|
||||
}
|
||||
|
||||
func (r *RuleSetItem) Match(metadata *adapter.InboundContext) bool {
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
for _, ruleSet := range r.setList {
|
||||
nestedMetadata := r.nestedMetadata(metadata)
|
||||
if ruleSet.Match(&nestedMetadata) {
|
||||
r.prepareNestedMatch(metadata)
|
||||
if ruleSet.Match(metadata) {
|
||||
snapshot.restore(metadata)
|
||||
return true
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -67,17 +70,19 @@ func (r *RuleSetItem) matchWithOuterGroups(metadata *adapter.InboundContext, out
|
||||
matched bool
|
||||
deferredGroups uint8
|
||||
)
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
for _, ruleSet := range r.setList {
|
||||
nestedMetadata := r.nestedMetadata(metadata)
|
||||
r.prepareNestedMatch(metadata)
|
||||
if provider, isProvider := ruleSet.(mergeableRuleProvider); isProvider {
|
||||
branch := provider.mergeableRule()
|
||||
if branch != nil {
|
||||
branchGroups, branchMatched := branch.evaluateForMerge(&nestedMetadata)
|
||||
branchGroups, branchMatched := branch.evaluateForMerge(metadata)
|
||||
if branchMatched {
|
||||
merged := outerGroups.mergeWith(branchGroups)
|
||||
if merged.done() {
|
||||
branchDeferredGroups := nestedMetadata.DeferredIPCIDRMatchGroups &^ uint8(merged.satisfied)
|
||||
branchDeferredGroups := metadata.DeferredIPCIDRMatchGroups &^ uint8(merged.satisfied)
|
||||
if branchDeferredGroups == 0 {
|
||||
snapshot.restore(metadata)
|
||||
metadata.DeferredIPCIDRMatchGroups &^= uint8(merged.satisfied)
|
||||
return true
|
||||
}
|
||||
@@ -88,26 +93,26 @@ func (r *RuleSetItem) matchWithOuterGroups(metadata *adapter.InboundContext, out
|
||||
continue
|
||||
}
|
||||
}
|
||||
if outerDone && ruleSet.Match(&nestedMetadata) {
|
||||
if nestedMetadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
if outerDone && ruleSet.Match(metadata) {
|
||||
if metadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
snapshot.restore(metadata)
|
||||
return true
|
||||
}
|
||||
matched = true
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
if matched {
|
||||
metadata.DeferredIPCIDRMatchGroups |= deferredGroups
|
||||
}
|
||||
return matched
|
||||
}
|
||||
|
||||
func (r *RuleSetItem) nestedMetadata(metadata *adapter.InboundContext) adapter.InboundContext {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleMatchCache()
|
||||
nestedMetadata.IPCIDRMatchSource = r.ipCidrMatchSource
|
||||
nestedMetadata.IPCIDRAcceptEmpty = r.ipCidrAcceptEmpty
|
||||
return nestedMetadata
|
||||
func (r *RuleSetItem) prepareNestedMatch(metadata *adapter.InboundContext) {
|
||||
metadata.ResetRuleMatchCache()
|
||||
metadata.IPCIDRMatchSource = r.ipCidrMatchSource
|
||||
metadata.IPCIDRAcceptEmpty = r.ipCidrAcceptEmpty
|
||||
}
|
||||
|
||||
type mergeableRuleProvider interface {
|
||||
@@ -130,17 +135,19 @@ func matchAnyHeadlessRule(rules []adapter.HeadlessRule, metadata *adapter.Inboun
|
||||
matched bool
|
||||
deferredGroups uint8
|
||||
)
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
for _, rule := range rules {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleMatchCache()
|
||||
if rule.Match(&nestedMetadata) {
|
||||
if nestedMetadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
metadata.ResetRuleMatchCache()
|
||||
if rule.Match(metadata) {
|
||||
if metadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
snapshot.restore(metadata)
|
||||
return true
|
||||
}
|
||||
matched = true
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
if matched {
|
||||
metadata.DeferredIPCIDRMatchGroups |= deferredGroups
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user