summaryrefslogtreecommitdiffstats
path: root/transform
diff options
context:
space:
mode:
authorNoah Campbell <noahcampbell@gmail.com>2013-10-31 22:14:11 -0700
committerNoah Campbell <noahcampbell@gmail.com>2013-11-01 09:59:57 -0700
commit9af47f07d3f9700e233a98d7e84d85c3a30f9cd5 (patch)
tree13df4879bf1bf5f895d74029086dfce5a6b60c04 /transform
parentf4cb8e1688b1459472413f3c85cb3b6297397020 (diff)
Improve rendering time
50% speedup. Fix #91 to run the benchmark: go test -test.run=NONE -bench=".*" -test.benchmem=true ./transform/ > new.txt to compare the results: /usr/local/go/misc/benchcmp baseline.txt new.txt Speedup and memory improvements benchmark old ns/op new ns/op delta BenchmarkChain 101219 50453 -50.15% BenchmarkTransform 51625 45531 -11.80% benchmark old allocs new allocs delta BenchmarkChain 222 103 -53.60% BenchmarkTransform 135 106 -21.48% benchmark old bytes new bytes delta BenchmarkChain 23919 10998 -54.02% BenchmarkTransform 11858 10665 -10.06%
Diffstat (limited to 'transform')
-rw-r--r--transform/absurl.go29
-rw-r--r--transform/chain.go28
-rw-r--r--transform/chain_test.go19
-rw-r--r--transform/nav.go32
-rw-r--r--transform/nav_test.go28
-rw-r--r--transform/post.go8
-rw-r--r--transform/posttrans_test.go13
7 files changed, 48 insertions, 109 deletions
diff --git a/transform/absurl.go b/transform/absurl.go
index 087aba5b1..f66edab9d 100644
--- a/transform/absurl.go
+++ b/transform/absurl.go
@@ -2,38 +2,28 @@ package transform
import (
htmltran "code.google.com/p/go-html-transform/html/transform"
- "io"
"net/url"
)
-type AbsURL struct {
- BaseURL string
-}
-
-func (t *AbsURL) Apply(w io.Writer, r io.Reader) (err error) {
- var tr *htmltran.Transformer
+func AbsURL(absURL string) (trs []*htmltran.Transform, err error) {
+ var baseURL *url.URL
- if tr, err = htmltran.NewFromReader(r); err != nil {
+ if baseURL, err = url.Parse(absURL); err != nil {
return
}
- if err = t.absUrlify(tr, elattr{"a", "href"}, elattr{"script", "src"}); err != nil {
+ if trs, err = absUrlify(baseURL, elattr{"a", "href"}, elattr{"script", "src"}); err != nil {
return
}
-
- return tr.Render(w)
+ return
}
type elattr struct {
tag, attr string
}
-func (t *AbsURL) absUrlify(tr *htmltran.Transformer, selectors ...elattr) (err error) {
- var baseURL, inURL *url.URL
-
- if baseURL, err = url.Parse(t.BaseURL); err != nil {
- return
- }
+func absUrlify(baseURL *url.URL, selectors ...elattr) (trs []*htmltran.Transform, err error) {
+ var inURL *url.URL
replace := func(in string) string {
if inURL, err = url.Parse(in); err != nil {
@@ -46,9 +36,8 @@ func (t *AbsURL) absUrlify(tr *htmltran.Transformer, selectors ...elattr) (err e
}
for _, el := range selectors {
- if err = tr.Apply(htmltran.TransformAttrib(el.attr, replace), el.tag); err != nil {
- return
- }
+ mt := htmltran.MustTrans(htmltran.TransformAttrib(el.attr, replace), el.tag)
+ trs = append(trs, mt)
}
return
diff --git a/transform/chain.go b/transform/chain.go
index 1d50e8f2f..a4929b70d 100644
--- a/transform/chain.go
+++ b/transform/chain.go
@@ -1,29 +1,25 @@
package transform
import (
- "bytes"
+ htmltran "code.google.com/p/go-html-transform/html/transform"
"io"
)
-type chain struct {
- transformers []Transformer
-}
+type chain []*htmltran.Transform
-func NewChain(trs ...Transformer) Transformer {
- return &chain{transformers: trs}
+func NewChain(trs ...*htmltran.Transform) chain {
+ return trs
}
func (c *chain) Apply(w io.Writer, r io.Reader) (err error) {
- in := r
- for _, tr := range c.transformers {
- out := new(bytes.Buffer)
- err = tr.Apply(out, in)
- if err != nil {
- return
- }
- in = bytes.NewBuffer(out.Bytes())
+
+ var tr *htmltran.Transformer
+
+ if tr, err = htmltran.NewFromReader(r); err != nil {
+ return
}
- _, err = io.Copy(w, in)
- return
+ tr.ApplyAll(*c...)
+
+ return tr.Render(w)
}
diff --git a/transform/chain_test.go b/transform/chain_test.go
index b479ac1e3..594b5a5d4 100644
--- a/transform/chain_test.go
+++ b/transform/chain_test.go
@@ -15,7 +15,8 @@ func TestChainZeroTransformers(t *testing.T) {
}
func TestChainOneTransformer(t *testing.T) {
- tr := NewChain(&AbsURL{BaseURL: "http://base"})
+ absURL, _ := AbsURL("http://base")
+ tr := NewChain(absURL...)
apply(t.Errorf, tr, abs_url_tests)
}
@@ -28,19 +29,19 @@ var two_chain_tests = []test{
}
func TestChainTwoTransformer(t *testing.T) {
- tr := NewChain(
- &AbsURL{BaseURL: "http://two"},
- &NavActive{Section: "section_1"},
- )
+ absURL, _ := AbsURL("http://two")
+ nav := NavActive("section_1", "hugo-nav")
+ tr := NewChain(append(absURL, nav...)...)
apply(t.Errorf, tr, two_chain_tests)
}
func BenchmarkChain(b *testing.B) {
- tr := NewChain(
- &AbsURL{BaseURL: "http://two"},
- &NavActive{Section: "section_1"},
- )
+ absURL, _ := AbsURL("http://two")
+ nav := NavActive("section_1", "hugo-nav")
+ tr := NewChain(append(absURL, nav...)...)
+
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
apply(b.Errorf, tr, two_chain_tests)
}
diff --git a/transform/nav.go b/transform/nav.go
index 1c9ab1fb6..7783b6175 100644
--- a/transform/nav.go
+++ b/transform/nav.go
@@ -3,34 +3,10 @@ package transform
import (
htmltran "code.google.com/p/go-html-transform/html/transform"
"fmt"
- "io"
)
-type NavActive struct {
- Section string
- AttrName string
-}
-
-func (n *NavActive) Apply(w io.Writer, r io.Reader) (err error) {
- var tr *htmltran.Transformer
-
- if n.Section == "" {
- _, err = io.Copy(w, r)
- return
- }
-
- if tr, err = htmltran.NewFromReader(r); err != nil {
- return
- }
-
- if n.AttrName == "" {
- n.AttrName = "hugo-nav"
- }
-
- err = tr.Apply(htmltran.ModifyAttrib("class", "active"), fmt.Sprintf("li[%s=%s]", n.AttrName, n.Section))
- if err != nil {
- return
- }
-
- return tr.Render(w)
+func NavActive(section, attrName string) (tr []*htmltran.Transform) {
+ ma := htmltran.MustTrans(htmltran.ModifyAttrib("class", "active"), fmt.Sprintf("li[%s=%s]", attrName, section))
+ tr = append(tr, ma)
+ return
}
diff --git a/transform/nav_test.go b/transform/nav_test.go
index 8ee46f116..372d3f594 100644
--- a/transform/nav_test.go
+++ b/transform/nav_test.go
@@ -31,25 +31,11 @@ const EXPECTED_HTML_WITH_NAV_1 = `<!DOCTYPE html><html><head></head>
</body></html>`
-func TestDegenerateNoSectionSet(t *testing.T) {
- var (
- tr = new(NavActive)
- out = new(bytes.Buffer)
- )
-
- if err := tr.Apply(out, strings.NewReader(HTML_WITH_NAV)); err != nil {
- t.Errorf("Unexpected error in NavActive.Apply: %s", err)
- }
-
- if out.String() != HTML_WITH_NAV {
- t.Errorf("NavActive.Apply should simply pass along the buffer unmodified.")
- }
-}
-
func TestSetNav(t *testing.T) {
- tr := &NavActive{Section: "section_2"}
+ trs := NavActive("section_2", "hugo-nav")
+ chain := NewChain(trs...)
out := new(bytes.Buffer)
- if err := tr.Apply(out, strings.NewReader(HTML_WITH_NAV)); err != nil {
+ if err := chain.Apply(out, strings.NewReader(HTML_WITH_NAV)); err != nil {
t.Errorf("Unexpected error in Apply() for NavActive: %s", err)
}
@@ -60,11 +46,13 @@ func TestSetNav(t *testing.T) {
}
func BenchmarkTransform(b *testing.B) {
+ tr := NavActive("section_2", "hugo-nav")
+ chain := NewChain(tr...)
+ out := new(bytes.Buffer)
for i := 0; i < b.N; i++ {
- tr := &NavActive{Section: "section_2"}
- out := new(bytes.Buffer)
- if err := tr.Apply(out, strings.NewReader(HTML_WITH_NAV)); err != nil {
+ if err := chain.Apply(out, strings.NewReader(HTML_WITH_NAV)); err != nil {
b.Errorf("Unexpected error in Apply() for NavActive: %s", err)
}
+ out.Reset()
}
}
diff --git a/transform/post.go b/transform/post.go
index c9a292b56..5796f91c6 100644
--- a/transform/post.go
+++ b/transform/post.go
@@ -1,9 +1 @@
package transform
-
-import (
- "io"
-)
-
-type Transformer interface {
- Apply(io.Writer, io.Reader) error
-}
diff --git a/transform/posttrans_test.go b/transform/posttrans_test.go
index 103e73a4a..12f7df1f6 100644
--- a/transform/posttrans_test.go
+++ b/transform/posttrans_test.go
@@ -16,12 +16,9 @@ const H5_JS_CONTENT_ABS_URL = "<!DOCTYPE html><html><head><script src=\"http://u
const CORRECT_OUTPUT_SRC_HREF = "<!DOCTYPE html><html><head><script src=\"http://base/foobar.js\"></script></head><body><nav><h1>title</h1></nav><article>content <a href=\"http://base/foobar\">foobar</a>. Follow up</article></body></html>"
func TestAbsUrlify(t *testing.T) {
-
- tr := &AbsURL{
- BaseURL: "http://base",
- }
-
- apply(t.Errorf, tr, abs_url_tests)
+ tr, _ := AbsURL("http://base")
+ chain := NewChain(tr...)
+ apply(t.Errorf, chain, abs_url_tests)
}
type test struct {
@@ -35,9 +32,9 @@ var abs_url_tests = []test{
{H5_JS_CONTENT_ABS_URL, H5_JS_CONTENT_ABS_URL},
}
-type errorf func (string, ...interface{})
+type errorf func(string, ...interface{})
-func apply(ef errorf, tr Transformer, tests []test) {
+func apply(ef errorf, tr chain, tests []test) {
for _, test := range tests {
out := new(bytes.Buffer)
err := tr.Apply(out, strings.NewReader(test.content))