简体   繁体   English

Go的PNG编码速度很慢

[英]PNG encoding with Go is slow

I'm acquiring frames from my built in webcam with go-opencv. 我正在使用go-opencv从内置的网络摄像头获取帧。 The time it takes to acquire an image from the camera is ~50ms. 从相机获取图像所需的时间约为50毫秒。 The time to encode the PNG is ~300ms. 编码PNG的时间约为300毫秒。 Encoding a JPEG is 3x faster, but still horribly slow. 编码JPEG的速度快了3倍,但仍然非常慢。

Why is this running so slowly? 为什么运行这么慢?

Note : I've written similar code against NodeJS, executed on the same machine, and have absolutely no problem hitting 30fps w/ additional image processing. 注意 :我已经针对NodeJS编写了类似的代码,在同一台机器上执行,并且在达到30fps且带有附加图像处理的情况下绝对没有问题。 For me, this removes hardware issues from the equation. 对我来说,这消除了方程式中的硬件问题。

My code looks like this: 我的代码如下所示:

import (
    "fmt"
    "image/png"

    "github.com/lazywei/go-opencv/opencv"
)

camera := opencv.NewCameraCapture(0)
if camera == nil {
    panic("Unable to open camera.")
}
defer camera.Release()

for {
    if camera.GrabFrame() {
        img := camera.RetrieveFrame(1)
        if img != nil {
            frame := img.ToImage()
            buffer := new(bytes.Buffer)
            png.Encode(buffer, frame)
        } else {
            fmt.Println("Unable to capture frame")
        }
    }

}

Disabling compression improves encoding performance by an order of magnitude on my machine. 禁用压缩可将计算机上的编码性能提高一个数量级。 That may be a start if you don't want to look for png packages outside the standard library. 如果您不想在标准库之外查找png包,那可能是一个开始。

I also tried the BufferPool (new in Go 1.9), but it didn't make a difference compared to an encoder with a nil BufferPool. 我还尝试了BufferPool (Go 1.9中的新增功能),但是与使用零BufferPool的编码器相比,它没有什么区别。 Perhaps I did it wrong. 也许我做错了。 The docs are unfortunately very, erm, concise. 不幸的是,文档非常简洁。

package main

import (
    "bytes"
    "image"
    "image/png"
    "os"
    "testing"
)

func BenchmarkPNG_Encode(b *testing.B) {
    img, buf := loadImage(b)

    b.ResetTimer()

    for i := 0; i < b.N; i++ {
            buf.Reset()
            png.Encode(buf, img)
    }
}

func BenchmarkPNG_Encoder(b *testing.B) {
    img, buf := loadImage(b)
    enc := &png.Encoder{}

    b.ResetTimer()

    for i := 0; i < b.N; i++ {
            buf.Reset()
            enc.Encode(buf, img)
    }
}

func BenchmarkPNG_Encoder_NoCompression(b *testing.B) {
    img, buf := loadImage(b)
    enc := &png.Encoder{
            CompressionLevel: png.NoCompression,
    }

    b.ResetTimer()

    for i := 0; i < b.N; i++ {
            buf.Reset()
            enc.Encode(buf, img)
    }
}

func loadImage(b *testing.B) (image.Image, *bytes.Buffer) {
    // foo.png PNG 1920x1053 1920x1053+0+0 8-bit sRGB 251KB 0.000u 0:00.000
    f, err := os.Open("foo.png")
    if err != nil {
            b.Fatal(err)
    }

    img, err := png.Decode(f)
    if err != nil {
            b.Fatal(err)
    }
    f.Close()

    buf := &bytes.Buffer{}
    // grow the buffer once
    (&png.Encoder{CompressionLevel: png.NoCompression}).Encode(buf, img)

    return img, buf
}

Again, this was on my machine with a roughly 1920x1080 pixel image -- a random screenshot; 再次,这是在我的机器上,具有大约1920x1080像素的图像-随机屏幕截图; not sure how much this will differ from, say, a photo. 不知道这与照片有什么不同。 YMMV. 因人而异。

$ go test -v -bench . -benchmem 
goos: linux
goarch: amd64
BenchmarkPNG_Encode-8                         10         119289121 ns/op          884964 B/op         38 allocs/op
BenchmarkPNG_Encoder-8                        10         118001658 ns/op          884932 B/op         37 allocs/op
BenchmarkPNG_Encoder_NoCompression-8         100          13050664 ns/op          807156 B/op        212 allocs/op

It's interesting that no compression causes many more allocations than with compression though. 有趣的是,没有压缩比使用压缩导致更多的分配。

Why is this running so slowly? 为什么运行这么慢?

Measure! 测量! Go has nice profiling tools built in eg into go test . Go有内置的好分析工具,例如go test

Most probably it is the PNG encoder which is pure, "unoptimized" Go. PNG编码器很可能是纯的,“未优化”的Go。 If this is not fast enough for you you might want to consider contributing a faster PNG encoder. 如果这还不够快,那么您可能要考虑提供更快的PNG编码器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM