signficant speedup in highlighter by compiling the regex once

i thought my little lazy regex compiling caching thing worked but
apparently not and the editor was still recompiling the regular
expressions every frame... they are now compiled when the editor is
loaded instead. this is ideal since the editor will crash on a bad
config rather than encountering a highlight and crashing then.

and obviously its a lot faster too! its hard to gauge the speed increase
since im running this editor in a VM, but the fps went from 30 to 60
frames per second after doing this so that seems good to me!
This commit is contained in:
Felix Angell 2018-04-21 19:05:20 +01:00
parent 159346ab91
commit fb72830c6b
3 changed files with 22 additions and 26 deletions

View File

@ -2,6 +2,7 @@ package cfg
import (
"errors"
"regexp"
"log"
"strconv"
"github.com/felixangell/strife"
@ -37,6 +38,7 @@ type SyntaxCriteria struct {
Match []string `toml:"match"`
Pattern string `toml:"pattern"`
CompiledPattern *regexp.Regexp
MatchList map[string]bool
}

View File

@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"runtime"
"regexp"
"strings"
"github.com/felixangell/strife"
@ -138,18 +139,30 @@ func configureAndValidate(conf *TomlConfig) {
// go through each language
// and store the matches keywords
// as a hashmap for faster lookup
// in addition to this we compile any
// regular expressions if necessary.
for _, language := range syntaxSet {
for _, syn := range language.Syntax {
syn.MatchList = map[string]bool{}
for _, item := range syn.Match {
if _, ok := syn.MatchList[item]; ok {
log.Println("Warning duplicate match item '" + item + "'")
if syn.Pattern != "" {
regex, err := regexp.Compile(syn.Pattern)
if err != nil {
log.Println(err.Error())
continue
}
syn.CompiledPattern = regex
} else {
for _, item := range syn.Match {
if _, ok := syn.MatchList[item]; ok {
log.Println("Warning duplicate match item '" + item + "'")
continue
}
syn.MatchList[item] = true
syn.MatchList[item] = true
}
}
}
}
}

View File

@ -6,7 +6,6 @@ import (
"log"
"os"
"path"
"regexp"
"runtime"
"strings"
"time"
@ -773,8 +772,6 @@ var last_w, last_h int
// editor x and y offsets
var ex, ey = 0, 0
var compiledRegex = map[string]*regexp.Regexp{}
// runs up a lexer instance
func lexFindMatches(matches *map[int]syntaxRuneInfo, currLine string, toMatch map[string]bool, bg int, fg int) {
// start up a lexer instance and
@ -807,31 +804,15 @@ func (b *Buffer) syntaxHighlightLine(currLine string) map[int]syntaxRuneInfo {
for syntaxIndex, syntax := range subjects {
if syntax.Pattern != "" {
for charIndex := 0; charIndex < len(currLine); charIndex++ {
// we have a regex pattern
// FIXME this is also very slow!
// we could easily compile all of these
// regular expressions when we load the
// syntax highlighter.
a := string(currLine[charIndex:])
// no need to compile the same regex
// pattern multiple times.
regex, ok := compiledRegex[syntax.Pattern]
if !ok {
var err error
regex, err = regexp.Compile(syntax.Pattern)
if err != nil {
log.Println(err.Error())
}
}
matched := regex.FindStringIndex(a)
matched := syntax.CompiledPattern.FindStringIndex(a)
if matched != nil {
if _, ok := matches[charIndex]; !ok {
matchedStrLen := (matched[1] - matched[0])
matches[charIndex+matched[0]] = syntaxRuneInfo{colours[syntaxIndex], -1, matchedStrLen}
charIndex = charIndex + matchedStrLen
charIndex += matchedStrLen
continue
}
}
}