From 95e7ad8a7bbb8ed370121167d84d288ad450b6d8 Mon Sep 17 00:00:00 2001 From: Oliver Steele Date: Sun, 9 Jul 2017 13:12:30 -0400 Subject: [PATCH] Fix a perf regression; update benchmarks --- README.md | 10 ++++------ helpers/html.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ helpers/strings.go | 41 ----------------------------------------- site/write.go | 3 ++- tags/cache.go | 11 ++++++++++- 5 files changed, 61 insertions(+), 49 deletions(-) create mode 100644 helpers/html.go diff --git a/README.md b/README.md index 28e5d30..01c3ed9 100644 --- a/README.md +++ b/README.md @@ -80,12 +80,10 @@ These will probably not change. | Executable | Options | Time | |------------|-----------------------------|---------------| | jekyll | | 18.53s | -| gojekyll | single-threaded; cold cache | 3.31s ± 0.07s | -| gojekyll | single-threaded; warm cache | 2.50s ± 0.04s | -| gojekyll | multi-threaded | 1.51s ± 0.01s | -| gojekyll | multi-threaded | 0.80s ± 0.09s | - -This isn't an apples-to-ranges comparison. Gojekyll doesn't use all the plugins that Jekyll does. In particular, `jekyll-mentions` parses each page's HTML. This could slow Gojekyll down once it's added. +| gojekyll | single-threaded; cold cache | 2.96s ± 0.09s | +| gojekyll | single-threaded; warm cache | 2.51s ± 0.04s | +| gojekyll | multi-threaded; cold cache | 1.37s ± 0.03s | +| gojekyll | multi-threaded; warm cache | 0.80s ± 0.06s | There's currently no way to disable the cache. It was disabled off by re-building the executable. diff --git a/helpers/html.go b/helpers/html.go new file mode 100644 index 0000000..f30a195 --- /dev/null +++ b/helpers/html.go @@ -0,0 +1,45 @@ +package helpers + +import ( + "bytes" + "io" + + "golang.org/x/net/html" +) + +// ApplyToHTMLText applies a filter only to the text within an HTML document. +func ApplyToHTMLText(doc []byte, fn func(string) string) []byte { + z := html.NewTokenizer(bytes.NewReader(doc)) + buf := new(bytes.Buffer) + body := false +outer: + for { + tt := z.Next() + switch tt { + case html.ErrorToken: + if z.Err() == io.EOF { + break outer + } + panic(z.Err()) + case html.StartTagToken, html.EndTagToken: + tn, _ := z.TagName() + if string(tn) == "body" { + body = tt == html.StartTagToken + } + case html.TextToken: + if body { + s := (string(z.Text())) + _, err := buf.WriteString(fn(s)) + if err != nil { + panic(err) + } + continue outer + } + } + _, err := buf.Write(z.Raw()) + if err != nil { + panic(err) + } + } + return buf.Bytes() +} diff --git a/helpers/strings.go b/helpers/strings.go index 4846fda..c58afe0 100644 --- a/helpers/strings.go +++ b/helpers/strings.go @@ -1,11 +1,7 @@ package helpers import ( - "bytes" - "io" "regexp" - - "golang.org/x/net/html" ) // LeftPad left-pads s with spaces to n wide. It's an alternative to http://left-pad.io. @@ -60,40 +56,3 @@ func StringArrayToMap(strings []string) map[string]bool { } return stringMap } - -// ApplyToHTMLText applies a filter only to the text within an HTML document. -func ApplyToHTMLText(doc []byte, fn func(string) string) []byte { - z := html.NewTokenizer(bytes.NewReader(doc)) - buf := new(bytes.Buffer) - body := false -outer: - for { - tt := z.Next() - switch tt { - case html.ErrorToken: - if z.Err() == io.EOF { - break outer - } - panic(z.Err()) - case html.StartTagToken, html.EndTagToken: - tn, _ := z.TagName() - if string(tn) == "body" { - body = tt == html.StartTagToken - } - case html.TextToken: - if body { - s := (string(z.Text())) - _, err := buf.WriteString((fn(s))) - if err != nil { - panic(err) - } - continue outer - } - } - _, err := buf.Write(z.Raw()) - if err != nil { - panic(err) - } - } - return buf.Bytes() -} diff --git a/site/write.go b/site/write.go index 0a35646..37765c7 100644 --- a/site/write.go +++ b/site/write.go @@ -42,7 +42,8 @@ func (s *Site) WriteDocument(w io.Writer, p pages.Document) error { if err != nil { return err } - return p.Write(w, s) + _, err = w.Write(c) + return err } // WritePages writes output files. diff --git a/tags/cache.go b/tags/cache.go index 6644f04..de7e657 100644 --- a/tags/cache.go +++ b/tags/cache.go @@ -9,6 +9,15 @@ import ( "path/filepath" ) +var disableCache = false + +func init() { + s := os.Getenv("GOJEKYLL_DISABLE_CACHE") + if s != "" && s != "0" && s != "false" { + disableCache = true + } +} + // withFileCache looks (header, content) up in a user-specific file cache. // If found, it writes the file contents. Else it calls fn to write to // both the writer and the file system. @@ -32,7 +41,7 @@ func withFileCache(header string, content string, fn func() (string, error)) (st // WriteFile truncates the file before writing it, so ignore empty files. // If the writer actually wrote an empty file, we'll end up gratuitously // re-running it, which is okay. - if b, err := ioutil.ReadFile(cachefile); err == nil && len(b) > 0 { + if b, err := ioutil.ReadFile(cachefile); err == nil && len(b) > 0 && !disableCache { return string(b), err } s, err := fn()