forked from TrueCloudLab/restic
Optimize filter pattern matching
By replacing "**" with "", checking for this special path component can be reduced to a length-zero check. name old time/op new time/op delta FilterLines-8 44.7ms ± 5% 44.9ms ± 5% ~ (p=0.631 n=10+10) FilterPatterns/Relative-8 13.6ms ± 4% 13.4ms ± 5% ~ (p=0.165 n=10+10) FilterPatterns/Absolute-8 10.9ms ± 5% 10.7ms ± 4% ~ (p=0.052 n=10+10) FilterPatterns/Wildcard-8 53.7ms ± 5% 50.4ms ± 5% -6.00% (p=0.000 n=10+10) FilterPatterns/ManyNoMatch-8 128ms ± 2% 95ms ± 1% -25.54% (p=0.000 n=10+10) name old alloc/op new alloc/op delta FilterPatterns/Relative-8 3.57MB ± 0% 3.57MB ± 0% ~ (p=1.000 n=9+8) FilterPatterns/Absolute-8 3.57MB ± 0% 3.57MB ± 0% ~ (p=0.903 n=9+8) FilterPatterns/Wildcard-8 19.7MB ± 0% 19.7MB ± 0% -0.00% (p=0.022 n=10+9) FilterPatterns/ManyNoMatch-8 3.57MB ± 0% 3.57MB ± 0% ~ (all equal) name old allocs/op new allocs/op delta FilterPatterns/Relative-8 22.2k ± 0% 22.2k ± 0% ~ (all equal) FilterPatterns/Absolute-8 22.2k ± 0% 22.2k ± 0% ~ (all equal) FilterPatterns/Wildcard-8 88.7k ± 0% 88.7k ± 0% ~ (all equal) FilterPatterns/ManyNoMatch-8 22.2k ± 0% 22.2k ± 0% ~ (all equal)
This commit is contained in:
parent
8388e67c4b
commit
740758a5fa
1 changed files with 21 additions and 11 deletions
|
@ -12,7 +12,7 @@ import (
|
|||
var ErrBadString = errors.New("filter.Match: string is empty")
|
||||
|
||||
type patternPart struct {
|
||||
pattern string
|
||||
pattern string // First is "/" for absolute pattern; "" for "**".
|
||||
isSimple bool
|
||||
}
|
||||
|
||||
|
@ -23,25 +23,35 @@ func prepareStr(str string) ([]string, error) {
|
|||
if str == "" {
|
||||
return nil, ErrBadString
|
||||
}
|
||||
|
||||
str = filepath.ToSlash(str)
|
||||
return strings.Split(str, "/"), nil
|
||||
return splitPath(str), nil
|
||||
}
|
||||
|
||||
func preparePattern(pattern string) Pattern {
|
||||
pattern = filepath.Clean(pattern)
|
||||
pattern = filepath.ToSlash(pattern)
|
||||
|
||||
parts := strings.Split(pattern, "/")
|
||||
parts := splitPath(filepath.Clean(pattern))
|
||||
patterns := make([]patternPart, len(parts))
|
||||
for i, part := range parts {
|
||||
isSimple := !strings.ContainsAny(part, "\\[]*?")
|
||||
// Replace "**" with the empty string to get faster comparisons
|
||||
// (length-check only) in hasDoubleWildcard.
|
||||
if part == "**" {
|
||||
part = ""
|
||||
}
|
||||
patterns[i] = patternPart{part, isSimple}
|
||||
}
|
||||
|
||||
return patterns
|
||||
}
|
||||
|
||||
// Split p into path components. Assuming p has been Cleaned, no component
|
||||
// will be empty. For absolute paths, the first component is "/".
|
||||
func splitPath(p string) []string {
|
||||
parts := strings.Split(filepath.ToSlash(p), "/")
|
||||
if parts[0] == "" {
|
||||
parts[0] = "/"
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
// Match returns true if str matches the pattern. When the pattern is
|
||||
// malformed, filepath.ErrBadPattern is returned. The empty pattern matches
|
||||
// everything, when str is the empty string ErrBadString is returned.
|
||||
|
@ -93,7 +103,7 @@ func ChildMatch(pattern, str string) (matched bool, err error) {
|
|||
}
|
||||
|
||||
func childMatch(patterns Pattern, strs []string) (matched bool, err error) {
|
||||
if patterns[0].pattern != "" {
|
||||
if patterns[0].pattern != "/" {
|
||||
// relative pattern can always be nested down
|
||||
return true, nil
|
||||
}
|
||||
|
@ -116,7 +126,7 @@ func childMatch(patterns Pattern, strs []string) (matched bool, err error) {
|
|||
|
||||
func hasDoubleWildcard(list Pattern) (ok bool, pos int) {
|
||||
for i, item := range list {
|
||||
if item.pattern == "**" {
|
||||
if item.pattern == "" {
|
||||
return true, i
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +169,7 @@ func match(patterns Pattern, strs []string) (matched bool, err error) {
|
|||
if len(patterns) <= len(strs) {
|
||||
maxOffset := len(strs) - len(patterns)
|
||||
// special case absolute patterns
|
||||
if patterns[0].pattern == "" {
|
||||
if patterns[0].pattern == "/" {
|
||||
maxOffset = 0
|
||||
}
|
||||
outer:
|
||||
|
|
Loading…
Reference in a new issue