Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Re-use gzip.Writer instead of re-creating for each manpage
This reduces a 6m30s Debian unstable rendering run to 5m30s.
  • Loading branch information
stapelberg committed Jan 15, 2017
1 parent 87c61c1 commit 2f89134
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 4 deletions.
12 changes: 11 additions & 1 deletion cmd/debiman/render.go
@@ -1,6 +1,7 @@
package main

import (
"compress/gzip"
"flag"
"fmt"
"io"
Expand Down Expand Up @@ -266,8 +267,17 @@ func renderAll(gv globalView) error {
return err
}
defer converter.Kill()

// NOTE(stapelberg): gzip’s decompression phase takes the same
// time, regardless of compression level. Hence, we invest the
// maximum CPU time once to achieve the best compression.
gzipw, err := gzip.NewWriterLevel(nil, gzip.BestCompression)
if err != nil {
return err
}

for r := range renderChan {
if err := rendermanpage(converter, r); err != nil {
if err := rendermanpage(gzipw, converter, r); err != nil {
// rendermanpage writes an error page if rendering
// failed, any returned error is severe (e.g. file
// system full) and should lead to termination.
Expand Down
4 changes: 2 additions & 2 deletions cmd/debiman/rendermanpage.go
Expand Up @@ -448,13 +448,13 @@ func rendermanpageprep(converter *convert.Process, job renderJob) (*template.Tem
}, nil
}

func rendermanpage(converter *convert.Process, job renderJob) error {
func rendermanpage(gzipw *gzip.Writer, converter *convert.Process, job renderJob) error {
t, data, err := rendermanpageprep(converter, job)
if err != nil {
return err
}

if err := writeAtomically(job.dest, true, func(w io.Writer) error {
if err := writeAtomicallyWithGz(job.dest, gzipw, func(w io.Writer) error {
return t.Execute(w, data)
}); err != nil {
return err
Expand Down
7 changes: 6 additions & 1 deletion cmd/debiman/reuse_test.go
Expand Up @@ -49,7 +49,12 @@ baz
}
defer converter.Kill()

if err := rendermanpage(converter, renderJob{
gzipw, err = gzip.NewWriterLevel(nil, gzip.BestCompression)
if err != nil {
t.Fatal(err)
}

if err := rendermanpage(gzipw, converter, renderJob{
dest: f.Name(),
src: f.Name(),
meta: meta,
Expand Down
36 changes: 36 additions & 0 deletions cmd/debiman/writeatomically.go
Expand Up @@ -59,3 +59,39 @@ func writeAtomically(dest string, compress bool, write func(w io.Writer) error)

return os.Rename(f.Name(), dest)
}

func writeAtomicallyWithGz(dest string, gzipw *gzip.Writer, write func(w io.Writer) error) error {
f, err := ioutil.TempFile(filepath.Dir(dest), "debiman-")
if err != nil {
return err
}
defer f.Close()
// TODO: defer os.Remove() in case we return before the tempfile is destroyed

// TODO(later): benchmark/support other compression algorithms. zopfli gets dos2unix from 9659B to 9274B (4% win)

bufw := bufio.NewWriter(f)
gzipw.Reset(bufw)

if err := write(gzipw); err != nil {
return err
}

if err := gzipw.Close(); err != nil {
return err
}

if err := bufw.Flush(); err != nil {
return err
}

if err := f.Chmod(0644); err != nil {
return err
}

if err := f.Close(); err != nil {
return err
}

return os.Rename(f.Name(), dest)
}

0 comments on commit 2f89134

Please sign in to comment.