From 2185a730d2ead8265b26263e1d6c6ca187c0c28e Mon Sep 17 00:00:00 2001 From: Meow <197331664+Meo597@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:30:16 +0800 Subject: [PATCH] perf(router): adjust the order of rules to optimize performance (#5267) --- app/router/condition.go | 14 ----------- app/router/config.go | 56 ++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/app/router/condition.go b/app/router/condition.go index c8cf4e8d..083cbfaf 100644 --- a/app/router/condition.go +++ b/app/router/condition.go @@ -47,20 +47,6 @@ var matcherTypeMap = map[Domain_Type]strmatcher.Type{ Domain_Full: strmatcher.Full, } -func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) { - matcherType, f := matcherTypeMap[domain.Type] - if !f { - return nil, errors.New("unsupported domain type", domain.Type) - } - - matcher, err := matcherType.New(domain.Value) - if err != nil { - return nil, errors.New("failed to create domain matcher").Base(err) - } - - return matcher, nil -} - type DomainMatcher struct { matchers strmatcher.IndexMatcher } diff --git a/app/router/config.go b/app/router/config.go index e9f0e02c..9f6a4844 100644 --- a/app/router/config.go +++ b/app/router/config.go @@ -32,27 +32,18 @@ func (r *Rule) Apply(ctx routing.Context) bool { func (rr *RoutingRule) BuildCondition() (Condition, error) { conds := NewConditionChan() - if len(rr.Domain) > 0 { - matcher, err := NewMphMatcherGroup(rr.Domain) - if err != nil { - return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err) - } - errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)") - conds.Add(matcher) - } - - if len(rr.UserEmail) > 0 { - conds.Add(NewUserMatcher(rr.UserEmail)) - } - - if rr.VlessRouteList != nil { - conds.Add(NewPortMatcher(rr.VlessRouteList, MatcherAsType_VlessRoute)) - } - if len(rr.InboundTag) > 0 { conds.Add(NewInboundTagMatcher(rr.InboundTag)) } + if len(rr.Networks) > 0 { + conds.Add(NewNetworkMatcher(rr.Networks)) + } + + if len(rr.Protocol) > 0 { + conds.Add(NewProtocolMatcher(rr.Protocol)) + } + if rr.PortList != nil { conds.Add(NewPortMatcher(rr.PortList, MatcherAsType_Target)) } @@ -65,8 +56,20 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) { conds.Add(NewPortMatcher(rr.LocalPortList, MatcherAsType_Local)) } - if len(rr.Networks) > 0 { - conds.Add(NewNetworkMatcher(rr.Networks)) + if rr.VlessRouteList != nil { + conds.Add(NewPortMatcher(rr.VlessRouteList, MatcherAsType_VlessRoute)) + } + + if len(rr.UserEmail) > 0 { + conds.Add(NewUserMatcher(rr.UserEmail)) + } + + if len(rr.Attributes) > 0 { + configuredKeys := make(map[string]*regexp.Regexp) + for key, value := range rr.Attributes { + configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value) + } + conds.Add(&AttributeMatcher{configuredKeys}) } if len(rr.Geoip) > 0 { @@ -94,16 +97,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) { errors.LogWarning(context.Background(), "Due to some limitations, in UDP connections, localIP is always equal to listen interface IP, so \"localIP\" rule condition does not work properly on UDP inbound connections that listen on all interfaces") } - if len(rr.Protocol) > 0 { - conds.Add(NewProtocolMatcher(rr.Protocol)) - } - - if len(rr.Attributes) > 0 { - configuredKeys := make(map[string]*regexp.Regexp) - for key, value := range rr.Attributes { - configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value) + if len(rr.Domain) > 0 { + matcher, err := NewMphMatcherGroup(rr.Domain) + if err != nil { + return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err) } - conds.Add(&AttributeMatcher{configuredKeys}) + errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)") + conds.Add(matcher) } if conds.Len() == 0 {