perkeep/internal/images/benchfastjpeg_test.go

138 lines
3.0 KiB
Go

/*
Copyright 2014 The Perkeep Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package images
import (
"bytes"
"image"
"image/jpeg"
"io"
"io/ioutil"
"testing"
"perkeep.org/internal/images/fastjpeg"
"perkeep.org/internal/images/resize"
)
// The decode routines being benchmarked in this file will use these bytes for
// their in-memory io.Readers.
var jpegBytes []byte
func init() {
// Create image with non-uniform color to make decoding more realistic.
// Solid color jpeg images decode faster than non-uniform images.
b := new(bytes.Buffer)
w, h := 4000, 4000
im := image.NewNRGBA(image.Rect(0, 0, w, h))
for i := range im.Pix {
switch {
case i%4 == 3:
im.Pix[i] = 255
default:
im.Pix[i] = uint8(i)
}
}
if err := jpeg.Encode(b, im, nil); err != nil {
panic(err)
}
jpegBytes = b.Bytes()
}
type decodeFunc func(r io.Reader) (image.Image, string, error)
func BenchmarkStdlib(b *testing.B) {
common(b, image.Decode)
}
func decodeDownsample(factor int) decodeFunc {
return func(r io.Reader) (image.Image, string, error) {
im, err := fastjpeg.DecodeDownsample(r, factor)
return im, "jpeg", err
}
}
func BenchmarkDjpeg1(b *testing.B) {
if !fastjpeg.Available() {
b.Skip("Skipping benchmark, djpeg unavailable.")
}
common(b, decodeDownsample(1))
}
func BenchmarkDjpeg2(b *testing.B) {
if !fastjpeg.Available() {
b.Skip("Skipping benchmark, djpeg unavailable.")
}
common(b, decodeDownsample(2))
}
func BenchmarkDjpeg4(b *testing.B) {
if !fastjpeg.Available() {
b.Skip("Skipping benchmark, djpeg unavailable.")
}
common(b, decodeDownsample(4))
}
func BenchmarkDjpeg8(b *testing.B) {
if !fastjpeg.Available() {
b.Skip("Skipping benchmark, djpeg unavailable.")
}
common(b, decodeDownsample(8))
}
func testRun(b testing.TB, decode decodeFunc) {
if !fastjpeg.Available() {
b.Skip("Skipping benchmark, djpeg unavailable.")
}
im, _, err := decode(bytes.NewReader(jpegBytes))
if err != nil {
b.Fatal(err)
}
rect := im.Bounds()
w, h := 128, 128
im = resize.Resize(im, rect, w, h)
err = jpeg.Encode(ioutil.Discard, im, nil)
if err != nil {
b.Fatal(err)
}
}
func common(b *testing.B, decode decodeFunc) {
for i := 0; i < b.N; i++ {
testRun(b, decode)
}
}
func TestStdlib(t *testing.T) {
testRun(t, decodeDownsample(1))
}
func TestDjpeg1(t *testing.T) {
testRun(t, decodeDownsample(1))
}
func TestDjpeg2(t *testing.T) {
testRun(t, decodeDownsample(2))
}
func TestDjpeg4(t *testing.T) {
testRun(t, decodeDownsample(4))
}
func TestDjpeg8(t *testing.T) {
testRun(t, decodeDownsample(8))
}