Skip to content

Performance is ~10-30x worse than Cairo #147

Open
@usedbytes

Description

@usedbytes

Perhaps this doesn't qualify as an issue per-se, but I wanted to use draw2d as the renderer in my program (instead of Cairo). However, even in simple cases, draw2dimg performs at least 10-30x worse than the equivalent Cairo code via cgo.

Maybe I'm doing something wrong? (I hope so)

Simple benchmark test below draws filled squares with an outline, performing ~30x worse on draw2d than Cairo. When the drawn surface is 1:1 blitted to another surface, the gap closes to ~10x

package main

import (
	"flag"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
	"testing"

	"github.com/ungerik/go-cairo"
	"github.com/llgcode/draw2d/draw2dimg"
)

var dumpImage bool

func TestMain(m *testing.M) {
	flag.BoolVar(&dumpImage, "dump", false, "Dump a PNG image from each benchmark for comparison")
	flag.Parse()

	os.Exit(m.Run())
}

func BenchmarkDraw2D(b *testing.B) {
	img := image.NewRGBA(image.Rect(0, 0, 500, 500))
	ctx := draw2dimg.NewGraphicContext(img)

	for n := 0; n < b.N; n++ {
		ctx.SetStrokeColor(color.RGBA{0xff, 0x00, 0x00, 0xff})
		ctx.SetFillColor(color.RGBA{0x4d, 0x4d, 0x4d, 0xff})
		ctx.SetLineWidth(2)
		ctx.MoveTo(1, 1)
		ctx.LineTo(499, 1)
		ctx.LineTo(499, 499)
		ctx.LineTo(1, 499)
		ctx.Close()
		ctx.FillStroke()
	}

	if dumpImage {
		f, err := os.Create("draw2d.png")
		if err != nil {
			log.Fatal(err)
		}

		if err := png.Encode(f, img); err != nil {
			f.Close()
			log.Fatal(err)
		}

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

func BenchmarkCairo(b *testing.B) {
	img := cairo.NewSurface(cairo.FORMAT_ARGB32, 500, 500)

	for n := 0; n < b.N; n++ {

		img.Rectangle(0, 0, 500, 500)
		img.SetSourceRGB(0.3, 0.3, 0.3)
		img.SetLineWidth(4)
		img.FillPreserve()
		img.SetSourceRGB(1.0, 0.0, 0.0)
		img.Stroke()
	}

	if dumpImage {
		img.WriteToPNG("cairo.png")
	}
}

Results:

$ go test -v -bench=. -test.parallel 1
goos: linux
goarch: amd64
pkg: github.com/usedbytes/drawbench
BenchmarkDraw2D-4           1000           2049011 ns/op
BenchmarkCairo-4           30000             50037 ns/op
PASS
ok      github.com/usedbytes/drawbench  4.278s

The README says that draw2d is a pure-go alternative to Cairo, but unfortunately the performance difference is too high for my use-case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions