Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

image: optimize Image.At().RGBA() #15759

Open
pierrre opened this issue May 19, 2016 · 6 comments

Comments

@pierrre
Copy link

commented May 19, 2016

In the Go standard library (and x/image), we can see several calls that look like Image.At().RGBA().
These calls mostly happen in y/x loops.
They are slow because they allocate memory.

I have written a library that speeds up Image.At().RGBA().
It is available on https://github.com/pierrre/imageutil

If you call https://godoc.org/github.com/pierrre/imageutil#NewAtFunc with an image, it returns a https://godoc.org/github.com/pierrre/imageutil#AtFunc
A AtFunc returns the RGBA value (uint32) for a given pixel (x/y).
A call to NewAtFunc() allocates memory, but it only happens 1 time per image.
A call to a AtFunc doesn't allocate memory (most of the time).

There is also NewSetFunc() that helps to set RGBA values to an image.
It works the same way.

My code is just a copy/paste of the Go standard library, but organized differently.

Benchmarks!

I've written benchmarks for "encode" functions.
It only tests blank images, but it will give you an idea.

package benchimageencode

import (
    "bytes"
    "image"
    "image/color"
    "image/gif"
    "image/jpeg"
    "image/png"
    "io"
    "strconv"
    "testing"

    "golang.org/x/image/bmp"
    "golang.org/x/image/tiff"
)

func Benchmark(b *testing.B) {
    buf := new(bytes.Buffer)
    for _, tcEnc := range []struct {
        name string
        enc  func(w io.Writer, im image.Image) error
    }{
        {
            "JPEG",
            func(w io.Writer, im image.Image) error {
                return jpeg.Encode(w, im, nil)
            },
        },
        {"PNG", png.Encode},
        {
            "GIF",
            func(w io.Writer, im image.Image) error {
                return gif.Encode(w, im, nil)
            },
        },
        {"BMP", bmp.Encode},
        {
            "TIFF",
            func(w io.Writer, im image.Image) error {
                return tiff.Encode(w, im, nil)
            },
        },
    } {
        b.Run(tcEnc.name, func(b *testing.B) {
            for _, tcIm := range []struct {
                name     string
                newImage func(image.Rectangle) image.Image
            }{
                {
                    "RGBA",
                    func(r image.Rectangle) image.Image {
                        return image.NewRGBA(r)
                    },
                },
                {
                    "RGBA64",
                    func(r image.Rectangle) image.Image {
                        return image.NewRGBA64(r)
                    },
                },
                {
                    "NRGBA",
                    func(r image.Rectangle) image.Image {
                        return image.NewNRGBA(r)
                    },
                },
                {
                    "NRGBA64",
                    func(r image.Rectangle) image.Image {
                        return image.NewNRGBA64(r)
                    },
                },
                {
                    "Alpha",
                    func(r image.Rectangle) image.Image {
                        return image.NewAlpha(r)
                    },
                },
                {
                    "Alpha16",
                    func(r image.Rectangle) image.Image {
                        return image.NewAlpha16(r)
                    },
                },
                {
                    "Gray",
                    func(r image.Rectangle) image.Image {
                        return image.NewGray(r)
                    },
                },
                {
                    "Gray16",
                    func(r image.Rectangle) image.Image {
                        return image.NewGray16(r)
                    },
                },
                {
                    "Paletted",
                    func(r image.Rectangle) image.Image {
                        return image.NewPaletted(r, color.Palette{
                            color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF},
                            color.RGBA{R: 0xFF, G: 0x00, B: 0x00, A: 0xFF},
                            color.RGBA{R: 0x00, G: 0xFF, B: 0x00, A: 0xFF},
                            color.RGBA{R: 0x00, G: 0x00, B: 0xFF, A: 0xFF},
                        })
                    },
                },
                {
                    "YCbCr",
                    func(r image.Rectangle) image.Image {
                        return image.NewYCbCr(r, image.YCbCrSubsampleRatio444)
                    },
                },
                {
                    "NYCbCrA",
                    func(r image.Rectangle) image.Image {
                        return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio444)
                    },
                },
                {
                    "CMYK",
                    func(r image.Rectangle) image.Image {
                        return image.NewCMYK(r)
                    },
                },
            } {
                b.Run(tcIm.name, func(b *testing.B) {
                    for _, size := range []int{
                        10, 100, 1000,
                    } {
                        im := tcIm.newImage(image.Rect(0, 0, size, size))
                        b.Run(strconv.Itoa(size), func(b *testing.B) {
                            for i := 0; i < b.N; i++ {
                                buf.Reset()
                                err := tcEnc.enc(buf, im)
                                if err != nil {
                                    b.Fatal(err)
                                }
                            }
                        })
                    }
                })
            }
        })
    }
}

Results:

benchmark                          old ns/op      new ns/op      delta
Benchmark/JPEG/RGBA/10-8           6891           6922           +0.45%
Benchmark/JPEG/RGBA/100-8          243797         226064         -7.27%
Benchmark/JPEG/RGBA/1000-8         18211697       18183751       -0.15%
Benchmark/JPEG/RGBA64/10-8         15505          8078           -47.90%
Benchmark/JPEG/RGBA64/100-8        654661         284739         -56.51%
Benchmark/JPEG/RGBA64/1000-8       51987889       22906425       -55.94%
Benchmark/JPEG/NRGBA/10-8          15891          7327           -53.89%
Benchmark/JPEG/NRGBA/100-8         646659         257388         -60.20%
Benchmark/JPEG/NRGBA/1000-8        53610219       20396700       -61.95%
Benchmark/JPEG/NRGBA64/10-8        16586          7310           -55.93%
Benchmark/JPEG/NRGBA64/100-8       718770         256065         -64.37%
Benchmark/JPEG/NRGBA64/1000-8      55099237       20160389       -63.41%
Benchmark/JPEG/Alpha/10-8          13366          7624           -42.96%
Benchmark/JPEG/Alpha/100-8         535532         274982         -48.65%
Benchmark/JPEG/Alpha/1000-8        43495216       21314882       -50.99%
Benchmark/JPEG/Alpha16/10-8        14041          7849           -44.10%
Benchmark/JPEG/Alpha16/100-8       567633         271382         -52.19%
Benchmark/JPEG/Alpha16/1000-8      46175342       21845906       -52.69%
Benchmark/JPEG/Gray/10-8           4124           4114           -0.24%
Benchmark/JPEG/Gray/100-8          80502          81061          +0.69%
Benchmark/JPEG/Gray/1000-8         7237756        7227977        -0.14%
Benchmark/JPEG/Gray16/10-8         13816          7688           -44.35%
Benchmark/JPEG/Gray16/100-8        565986         273270         -51.72%
Benchmark/JPEG/Gray16/1000-8       46435379       21609969       -53.46%
Benchmark/JPEG/Paletted/10-8       9504           7861           -17.29%
Benchmark/JPEG/Paletted/100-8      339095         277612         -18.13%
Benchmark/JPEG/Paletted/1000-8     27374214       22215206       -18.85%
Benchmark/JPEG/YCbCr/10-8          16747          8353           -50.12%
Benchmark/JPEG/YCbCr/100-8         693129         293951         -57.59%
Benchmark/JPEG/YCbCr/1000-8        56055246       23340037       -58.36%
Benchmark/JPEG/NYCbCrA/10-8        17758          9100           -48.76%
Benchmark/JPEG/NYCbCrA/100-8       753606         331801         -55.97%
Benchmark/JPEG/NYCbCrA/1000-8      61176716       27043470       -55.79%
Benchmark/JPEG/CMYK/10-8           16301          8968           -44.98%
Benchmark/JPEG/CMYK/100-8          664311         332938         -49.88%
Benchmark/JPEG/CMYK/1000-8         53249646       26513162       -50.21%
Benchmark/PNG/RGBA/10-8            233825         234277         +0.19%
Benchmark/PNG/RGBA/100-8           1318376        1244438        -5.61%
Benchmark/PNG/RGBA/1000-8          87804961       87500804       -0.35%
Benchmark/PNG/RGBA64/10-8          234305         241012         +2.86%
Benchmark/PNG/RGBA64/100-8         1560487        1571785        +0.72%
Benchmark/PNG/RGBA64/1000-8        116953559      115641713      -1.12%
Benchmark/PNG/NRGBA/10-8           224863         215643         -4.10%
Benchmark/PNG/NRGBA/100-8          543683         477847         -12.11%
Benchmark/PNG/NRGBA/1000-8         22236178       22087216       -0.67%
Benchmark/PNG/NRGBA64/10-8         278971         229319         -17.80%
Benchmark/PNG/NRGBA64/100-8        1338571        1344189        +0.42%
Benchmark/PNG/NRGBA64/1000-8       94600702       92419064       -2.31%
Benchmark/PNG/Alpha/10-8           226913         235867         +3.95%
Benchmark/PNG/Alpha/100-8          1237592        1212220        -2.05%
Benchmark/PNG/Alpha/1000-8         87412677       86772330       -0.73%
Benchmark/PNG/Alpha16/10-8         238503         230353         -3.42%
Benchmark/PNG/Alpha16/100-8        1534150        1577323        +2.81%
Benchmark/PNG/Alpha16/1000-8       114207844      113559204      -0.57%
Benchmark/PNG/Gray/10-8            240275         224893         -6.40%
Benchmark/PNG/Gray/100-8           349896         319882         -8.58%
Benchmark/PNG/Gray/1000-8          5872431        5918043        +0.78%
Benchmark/PNG/Gray16/10-8          232315         219746         -5.41%
Benchmark/PNG/Gray16/100-8         856544         922971         +7.76%
Benchmark/PNG/Gray16/1000-8        51153358       50292261       -1.68%
Benchmark/PNG/Paletted/10-8        222739         229109         +2.86%
Benchmark/PNG/Paletted/100-8       320867         322279         +0.44%
Benchmark/PNG/Paletted/1000-8      5880143        5995715        +1.97%
Benchmark/PNG/YCbCr/10-8           264396         229815         -13.08%
Benchmark/PNG/YCbCr/100-8          1119731        944250         -15.67%
Benchmark/PNG/YCbCr/1000-8         72874727       42894471       -41.14%
Benchmark/PNG/NYCbCrA/10-8         254977         239658         -6.01%
Benchmark/PNG/NYCbCrA/100-8        1646790        1662818        +0.97%
Benchmark/PNG/NYCbCrA/1000-8       126894096      125769798      -0.89%
Benchmark/PNG/CMYK/10-8            288477         227636         -21.09%
Benchmark/PNG/CMYK/100-8           1050239        883844         -15.84%
Benchmark/PNG/CMYK/1000-8          68309463       42997860       -37.05%
Benchmark/BMP/RGBA/10-8            2357           2337           -0.85%
Benchmark/BMP/RGBA/100-8           19857          19835          -0.11%
Benchmark/BMP/RGBA/1000-8          1699880        1658537        -2.43%
Benchmark/BMP/RGBA64/10-8          5892           2893           -50.90%
Benchmark/BMP/RGBA64/100-8         370764         72362          -80.48%
Benchmark/BMP/RGBA64/1000-8        37558621       6772522        -81.97%
Benchmark/BMP/NRGBA/10-8           5587           2754           -50.71%
Benchmark/BMP/NRGBA/100-8          330937         57430          -82.65%
Benchmark/BMP/NRGBA/1000-8         32697775       5413184        -83.44%
Benchmark/BMP/NRGBA64/10-8         6067           2779           -54.19%
Benchmark/BMP/NRGBA64/100-8        379282         59023          -84.44%
Benchmark/BMP/NRGBA64/1000-8       36784396       5547886        -84.92%
Benchmark/BMP/Alpha/10-8           4947           2691           -45.60%
Benchmark/BMP/Alpha/100-8          268719         54878          -79.58%
Benchmark/BMP/Alpha/1000-8         26591321       5049983        -81.01%
Benchmark/BMP/Alpha16/10-8         5236           2747           -47.54%
Benchmark/BMP/Alpha16/100-8        290536         57670          -80.15%
Benchmark/BMP/Alpha16/1000-8       28806912       5421961        -81.18%
Benchmark/BMP/Gray/10-8            3576           3575           -0.03%
Benchmark/BMP/Gray/100-8           4829           4768           -1.26%
Benchmark/BMP/Gray/1000-8          58899          57669          -2.09%
Benchmark/BMP/Gray16/10-8          5166           2781           -46.17%
Benchmark/BMP/Gray16/100-8         287760         57665          -79.96%
Benchmark/BMP/Gray16/1000-8        28462012       5463188        -80.81%
Benchmark/BMP/Paletted/10-8        3210           3358           +4.61%
Benchmark/BMP/Paletted/100-8       4386           4546           +3.65%
Benchmark/BMP/Paletted/1000-8      58090          58225          +0.23%
Benchmark/BMP/YCbCr/10-8           6046           2999           -50.40%
Benchmark/BMP/YCbCr/100-8          387509         79009          -79.61%
Benchmark/BMP/YCbCr/1000-8         38474751       7584745        -80.29%
Benchmark/BMP/NYCbCrA/10-8         6739           3387           -49.74%
Benchmark/BMP/NYCbCrA/100-8        462438         116874         -74.73%
Benchmark/BMP/NYCbCrA/1000-8       45898191       11495621       -74.95%
Benchmark/BMP/CMYK/10-8            5594           3105           -44.49%
Benchmark/BMP/CMYK/100-8           339544         90794          -73.26%
Benchmark/BMP/CMYK/1000-8          33004703       8738049        -73.52%
Benchmark/TIFF/RGBA/10-8           2312           2509           +8.52%
Benchmark/TIFF/RGBA/100-8          4122           3509           -14.87%
Benchmark/TIFF/RGBA/1000-8         295062         288624         -2.18%
Benchmark/TIFF/RGBA64/10-8         2698           2657           -1.52%
Benchmark/TIFF/RGBA64/100-8        63975          65120          +1.79%
Benchmark/TIFF/RGBA64/1000-8       6303790        6177960        -2.00%
Benchmark/TIFF/NRGBA/10-8          1867           1850           -0.91%
Benchmark/TIFF/NRGBA/100-8         2997           3031           +1.13%
Benchmark/TIFF/NRGBA/1000-8        293275         297403         +1.41%
Benchmark/TIFF/NRGBA64/10-8        2641           2737           +3.63%
Benchmark/TIFF/NRGBA64/100-8       64303          64035          -0.42%
Benchmark/TIFF/NRGBA64/1000-8      6227868        6260150        +0.52%
Benchmark/TIFF/Alpha/10-8          4791           2631           -45.08%
Benchmark/TIFF/Alpha/100-8         270968         60194          -77.79%
Benchmark/TIFF/Alpha/1000-8        26615543       5647306        -78.78%
Benchmark/TIFF/Alpha16/10-8        5037           2701           -46.38%
Benchmark/TIFF/Alpha16/100-8       293523         68395          -76.70%
Benchmark/TIFF/Alpha16/1000-8      29014088       6497133        -77.61%
Benchmark/TIFF/Gray/10-8           1481           1431           -3.38%
Benchmark/TIFF/Gray/100-8          1652           1657           +0.30%
Benchmark/TIFF/Gray/1000-8         36243          38499          +6.22%
Benchmark/TIFF/Gray16/10-8         1728           1826           +5.67%
Benchmark/TIFF/Gray16/100-8        19916          20041          +0.63%
Benchmark/TIFF/Gray16/1000-8       1682497        1682254        -0.01%
Benchmark/TIFF/Paletted/10-8       4276           4374           +2.29%
Benchmark/TIFF/Paletted/100-8      4759           4690           -1.45%
Benchmark/TIFF/Paletted/1000-8     39673          39281          -0.99%
Benchmark/TIFF/YCbCr/10-8          5862           2863           -51.16%
Benchmark/TIFF/YCbCr/100-8         383112         90709          -76.32%
Benchmark/TIFF/YCbCr/1000-8        37969567       8576337        -77.41%
Benchmark/TIFF/NYCbCrA/10-8        6511           3511           -46.08%
Benchmark/TIFF/NYCbCrA/100-8       454029         125287         -72.41%
Benchmark/TIFF/NYCbCrA/1000-8      45109329       11977360       -73.45%
Benchmark/TIFF/CMYK/10-8           5431           3017           -44.45%
Benchmark/TIFF/CMYK/100-8          331066         96960          -70.71%
Benchmark/TIFF/CMYK/1000-8         33648362       9402967        -72.06%

benchmark                          old allocs     new allocs     delta
Benchmark/JPEG/RGBA/10-8           4              5              +25.00%
Benchmark/JPEG/RGBA/100-8          4              5              +25.00%
Benchmark/JPEG/RGBA/1000-8         4              5              +25.00%
Benchmark/JPEG/RGBA64/10-8         260            5              -98.08%
Benchmark/JPEG/RGBA64/100-8        12548          5              -99.96%
Benchmark/JPEG/RGBA64/1000-8       1016068        5              -100.00%
Benchmark/JPEG/NRGBA/10-8          260            5              -98.08%
Benchmark/JPEG/NRGBA/100-8         12548          5              -99.96%
Benchmark/JPEG/NRGBA/1000-8        1016068        5              -100.00%
Benchmark/JPEG/NRGBA64/10-8        260            5              -98.08%
Benchmark/JPEG/NRGBA64/100-8       12548          5              -99.96%
Benchmark/JPEG/NRGBA64/1000-8      1016068        5              -100.00%
Benchmark/JPEG/Alpha/10-8          260            5              -98.08%
Benchmark/JPEG/Alpha/100-8         12548          5              -99.96%
Benchmark/JPEG/Alpha/1000-8        1016068        5              -100.00%
Benchmark/JPEG/Alpha16/10-8        260            5              -98.08%
Benchmark/JPEG/Alpha16/100-8       12548          5              -99.96%
Benchmark/JPEG/Alpha16/1000-8      1016068        5              -100.00%
Benchmark/JPEG/Gray/10-8           4              4              +0.00%
Benchmark/JPEG/Gray/100-8          4              4              +0.00%
Benchmark/JPEG/Gray/1000-8         4              4              +0.00%
Benchmark/JPEG/Gray16/10-8         260            5              -98.08%
Benchmark/JPEG/Gray16/100-8        12548          5              -99.96%
Benchmark/JPEG/Gray16/1000-8       1016068        5              -100.00%
Benchmark/JPEG/Paletted/10-8       4              6              +50.00%
Benchmark/JPEG/Paletted/100-8      4              6              +50.00%
Benchmark/JPEG/Paletted/1000-8     4              6              +50.00%
Benchmark/JPEG/YCbCr/10-8          260            5              -98.08%
Benchmark/JPEG/YCbCr/100-8         12548          5              -99.96%
Benchmark/JPEG/YCbCr/1000-8        1016068        5              -100.00%
Benchmark/JPEG/NYCbCrA/10-8        260            5              -98.08%
Benchmark/JPEG/NYCbCrA/100-8       12548          5              -99.96%
Benchmark/JPEG/NYCbCrA/1000-8      1016068        5              -100.00%
Benchmark/JPEG/CMYK/10-8           260            5              -98.08%
Benchmark/JPEG/CMYK/100-8          12548          5              -99.96%
Benchmark/JPEG/CMYK/1000-8         1016068        5              -100.00%
Benchmark/PNG/RGBA/10-8            232            233            +0.43%
Benchmark/PNG/RGBA/100-8           20032          20033          +0.00%
Benchmark/PNG/RGBA/1000-8          2000032        2000033        +0.00%
Benchmark/PNG/RGBA64/10-8          232            233            +0.43%
Benchmark/PNG/RGBA64/100-8         20032          20033          +0.00%
Benchmark/PNG/RGBA64/1000-8        2000032        2000033        +0.00%
Benchmark/PNG/NRGBA/10-8           32             33             +3.12%
Benchmark/PNG/NRGBA/100-8          32             33             +3.12%
Benchmark/PNG/NRGBA/1000-8         32             33             +3.12%
Benchmark/PNG/NRGBA64/10-8         132            133            +0.76%
Benchmark/PNG/NRGBA64/100-8        10032          10033          +0.01%
Benchmark/PNG/NRGBA64/1000-8       1000032        1000033        +0.00%
Benchmark/PNG/Alpha/10-8           232            233            +0.43%
Benchmark/PNG/Alpha/100-8          20032          20033          +0.00%
Benchmark/PNG/Alpha/1000-8         2000032        2000033        +0.00%
Benchmark/PNG/Alpha16/10-8         232            233            +0.43%
Benchmark/PNG/Alpha16/100-8        20032          20033          +0.00%
Benchmark/PNG/Alpha16/1000-8       2000032        2000033        +0.00%
Benchmark/PNG/Gray/10-8            32             33             +3.12%
Benchmark/PNG/Gray/100-8           32             33             +3.12%
Benchmark/PNG/Gray/1000-8          32             33             +3.12%
Benchmark/PNG/Gray16/10-8          132            133            +0.76%
Benchmark/PNG/Gray16/100-8         10032          10033          +0.01%
Benchmark/PNG/Gray16/1000-8        1000032        1000033        +0.00%
Benchmark/PNG/Paletted/10-8        38             40             +5.26%
Benchmark/PNG/Paletted/100-8       38             40             +5.26%
Benchmark/PNG/Paletted/1000-8      38             40             +5.26%
Benchmark/PNG/YCbCr/10-8           132            33             -75.00%
Benchmark/PNG/YCbCr/100-8          10032          33             -99.67%
Benchmark/PNG/YCbCr/1000-8         1000032        33             -100.00%
Benchmark/PNG/NYCbCrA/10-8         232            233            +0.43%
Benchmark/PNG/NYCbCrA/100-8        20032          20033          +0.00%
Benchmark/PNG/NYCbCrA/1000-8       2000032        2000033        +0.00%
Benchmark/PNG/CMYK/10-8            132            33             -75.00%
Benchmark/PNG/CMYK/100-8           10032          33             -99.67%
Benchmark/PNG/CMYK/1000-8          1000032        33             -100.00%
Benchmark/BMP/RGBA/10-8            33             33             +0.00%
Benchmark/BMP/RGBA/100-8           33             33             +0.00%
Benchmark/BMP/RGBA/1000-8          33             33             +0.00%
Benchmark/BMP/RGBA64/10-8          133            34             -74.44%
Benchmark/BMP/RGBA64/100-8         10033          34             -99.66%
Benchmark/BMP/RGBA64/1000-8        1000033        34             -100.00%
Benchmark/BMP/NRGBA/10-8           133            34             -74.44%
Benchmark/BMP/NRGBA/100-8          10033          34             -99.66%
Benchmark/BMP/NRGBA/1000-8         1000033        34             -100.00%
Benchmark/BMP/NRGBA64/10-8         133            34             -74.44%
Benchmark/BMP/NRGBA64/100-8        10033          34             -99.66%
Benchmark/BMP/NRGBA64/1000-8       1000033        34             -100.00%
Benchmark/BMP/Alpha/10-8           133            34             -74.44%
Benchmark/BMP/Alpha/100-8          10033          34             -99.66%
Benchmark/BMP/Alpha/1000-8         1000033        34             -100.00%
Benchmark/BMP/Alpha16/10-8         133            34             -74.44%
Benchmark/BMP/Alpha16/100-8        10033          34             -99.66%
Benchmark/BMP/Alpha16/1000-8       1000033        34             -100.00%
Benchmark/BMP/Gray/10-8            37             37             +0.00%
Benchmark/BMP/Gray/100-8           36             36             +0.00%
Benchmark/BMP/Gray/1000-8          36             36             +0.00%
Benchmark/BMP/Gray16/10-8          133            34             -74.44%
Benchmark/BMP/Gray16/100-8         10033          34             -99.66%
Benchmark/BMP/Gray16/1000-8        1000033        34             -100.00%
Benchmark/BMP/Paletted/10-8        37             37             +0.00%
Benchmark/BMP/Paletted/100-8       36             36             +0.00%
Benchmark/BMP/Paletted/1000-8      36             36             +0.00%
Benchmark/BMP/YCbCr/10-8           133            34             -74.44%
Benchmark/BMP/YCbCr/100-8          10033          34             -99.66%
Benchmark/BMP/YCbCr/1000-8         1000033        34             -100.00%
Benchmark/BMP/NYCbCrA/10-8         133            34             -74.44%
Benchmark/BMP/NYCbCrA/100-8        10033          34             -99.66%
Benchmark/BMP/NYCbCrA/1000-8       1000033        34             -100.00%
Benchmark/BMP/CMYK/10-8            133            34             -74.44%
Benchmark/BMP/CMYK/100-8           10033          34             -99.66%
Benchmark/BMP/CMYK/1000-8          1000033        34             -100.00%
Benchmark/TIFF/RGBA/10-8           25             25             +0.00%
Benchmark/TIFF/RGBA/100-8          25             25             +0.00%
Benchmark/TIFF/RGBA/1000-8         25             25             +0.00%
Benchmark/TIFF/RGBA64/10-8         27             27             +0.00%
Benchmark/TIFF/RGBA64/100-8        27             27             +0.00%
Benchmark/TIFF/RGBA64/1000-8       27             27             +0.00%
Benchmark/TIFF/NRGBA/10-8          25             25             +0.00%
Benchmark/TIFF/NRGBA/100-8         25             25             +0.00%
Benchmark/TIFF/NRGBA/1000-8        25             25             +0.00%
Benchmark/TIFF/NRGBA64/10-8        27             27             +0.00%
Benchmark/TIFF/NRGBA64/100-8       27             27             +0.00%
Benchmark/TIFF/NRGBA64/1000-8      27             27             +0.00%
Benchmark/TIFF/Alpha/10-8          126            27             -78.57%
Benchmark/TIFF/Alpha/100-8         10026          27             -99.73%
Benchmark/TIFF/Alpha/1000-8        1000026        27             -100.00%
Benchmark/TIFF/Alpha16/10-8        126            27             -78.57%
Benchmark/TIFF/Alpha16/100-8       10026          27             -99.73%
Benchmark/TIFF/Alpha16/1000-8      1000026        27             -100.00%
Benchmark/TIFF/Gray/10-8           24             24             +0.00%
Benchmark/TIFF/Gray/100-8          24             24             +0.00%
Benchmark/TIFF/Gray/1000-8         24             24             +0.00%
Benchmark/TIFF/Gray16/10-8         25             25             +0.00%
Benchmark/TIFF/Gray16/100-8        25             25             +0.00%
Benchmark/TIFF/Gray16/1000-8       25             25             +0.00%
Benchmark/TIFF/Paletted/10-8       27             27             +0.00%
Benchmark/TIFF/Paletted/100-8      27             27             +0.00%
Benchmark/TIFF/Paletted/1000-8     27             27             +0.00%
Benchmark/TIFF/YCbCr/10-8          126            27             -78.57%
Benchmark/TIFF/YCbCr/100-8         10026          27             -99.73%
Benchmark/TIFF/YCbCr/1000-8        1000026        27             -100.00%
Benchmark/TIFF/NYCbCrA/10-8        126            27             -78.57%
Benchmark/TIFF/NYCbCrA/100-8       10026          27             -99.73%
Benchmark/TIFF/NYCbCrA/1000-8      1000026        27             -100.00%
Benchmark/TIFF/CMYK/10-8           126            27             -78.57%
Benchmark/TIFF/CMYK/100-8          10026          27             -99.73%
Benchmark/TIFF/CMYK/1000-8         1000026        27             -100.00%

benchmark                          old bytes     new bytes     delta
Benchmark/JPEG/RGBA/10-8           4400          4416          +0.36%
Benchmark/JPEG/RGBA/100-8          4400          4416          +0.36%
Benchmark/JPEG/RGBA/1000-8         4400          4416          +0.36%
Benchmark/JPEG/RGBA64/10-8         6448          4416          -31.51%
Benchmark/JPEG/RGBA64/100-8        104752        4416          -95.78%
Benchmark/JPEG/RGBA64/1000-8       8132924       4416          -99.95%
Benchmark/JPEG/NRGBA/10-8          5424          4416          -18.58%
Benchmark/JPEG/NRGBA/100-8         54576         4416          -91.91%
Benchmark/JPEG/NRGBA/1000-8        4068676       4416          -99.89%
Benchmark/JPEG/NRGBA64/10-8        6448          4416          -31.51%
Benchmark/JPEG/NRGBA64/100-8       104752        4416          -95.78%
Benchmark/JPEG/NRGBA64/1000-8      8132924       4416          -99.95%
Benchmark/JPEG/Alpha/10-8          4656          4416          -5.15%
Benchmark/JPEG/Alpha/100-8         16944         4416          -73.94%
Benchmark/JPEG/Alpha/1000-8        1020471       4416          -99.57%
Benchmark/JPEG/Alpha16/10-8        4912          4416          -10.10%
Benchmark/JPEG/Alpha16/100-8       29488         4416          -85.02%
Benchmark/JPEG/Alpha16/1000-8      2036550       4416          -99.78%
Benchmark/JPEG/Gray/10-8           4400          4400          +0.00%
Benchmark/JPEG/Gray/100-8          4400          4400          +0.00%
Benchmark/JPEG/Gray/1000-8         4400          4400          +0.00%
Benchmark/JPEG/Gray16/10-8         4912          4416          -10.10%
Benchmark/JPEG/Gray16/100-8        29488         4416          -85.02%
Benchmark/JPEG/Gray16/1000-8       2036550       4416          -99.78%
Benchmark/JPEG/Paletted/10-8       4400          4512          +2.55%
Benchmark/JPEG/Paletted/100-8      4400          4512          +2.55%
Benchmark/JPEG/Paletted/1000-8     4400          4512          +2.55%
Benchmark/JPEG/YCbCr/10-8          5219          4416          -15.39%
Benchmark/JPEG/YCbCr/100-8         44541         4416          -90.09%
Benchmark/JPEG/YCbCr/1000-8        3255826       4416          -99.86%
Benchmark/JPEG/NYCbCrA/10-8        5424          4416          -18.58%
Benchmark/JPEG/NYCbCrA/100-8       54576         4416          -91.91%
Benchmark/JPEG/NYCbCrA/1000-8      4068676       4416          -99.89%
Benchmark/JPEG/CMYK/10-8           5424          4416          -18.58%
Benchmark/JPEG/CMYK/100-8          54576         4416          -91.91%
Benchmark/JPEG/CMYK/1000-8         4068674       4416          -99.89%
Benchmark/PNG/RGBA/10-8            848947        848963        +0.00%
Benchmark/PNG/RGBA/100-8           930357        930373        +0.00%
Benchmark/PNG/RGBA/1000-8          8872468       8872480       +0.00%
Benchmark/PNG/RGBA64/10-8          850035        850051        +0.00%
Benchmark/PNG/RGBA64/100-8         1013234       1013249       +0.00%
Benchmark/PNG/RGBA64/1000-8        16897030      16897052      +0.00%
Benchmark/PNG/NRGBA/10-8           848147        848163        +0.00%
Benchmark/PNG/NRGBA/100-8          850356        850372        +0.00%
Benchmark/PNG/NRGBA/1000-8         872433        872450        +0.00%
Benchmark/PNG/NRGBA64/10-8         849235        849251        +0.00%
Benchmark/PNG/NRGBA64/100-8        933237        933253        +0.00%
Benchmark/PNG/NRGBA64/1000-8       8897022       8897035       +0.00%
Benchmark/PNG/Alpha/10-8           848946        848963        +0.00%
Benchmark/PNG/Alpha/100-8          930357        930372        +0.00%
Benchmark/PNG/Alpha/1000-8         8872497       8872518       +0.00%
Benchmark/PNG/Alpha16/10-8         850027        850043        +0.00%
Benchmark/PNG/Alpha16/100-8        1013228       1013245       +0.00%
Benchmark/PNG/Alpha16/1000-8       16897088      16897084      -0.00%
Benchmark/PNG/Gray/10-8            847955        847971        +0.00%
Benchmark/PNG/Gray/100-8           848531        848548        +0.00%
Benchmark/PNG/Gray/1000-8          854008        854023        +0.00%
Benchmark/PNG/Gray16/10-8          848251        848267        +0.00%
Benchmark/PNG/Gray16/100-8         869107        869123        +0.00%
Benchmark/PNG/Gray16/1000-8        2860163       2860184       +0.00%
Benchmark/PNG/Paletted/10-8        848019        848131        +0.01%
Benchmark/PNG/Paletted/100-8       848595        848708        +0.01%
Benchmark/PNG/Paletted/1000-8      854069        854183        +0.01%
Benchmark/PNG/YCbCr/10-8           848563        848259        -0.04%
Benchmark/PNG/YCbCr/100-8          883701        851716        -3.62%
Benchmark/PNG/YCbCr/1000-8         4084742       884739        -78.34%
Benchmark/PNG/NYCbCrA/10-8         850027        850043        +0.00%
Benchmark/PNG/NYCbCrA/100-8        1013226       1013242       +0.00%
Benchmark/PNG/NYCbCrA/1000-8       16897044      16897067      +0.00%
Benchmark/PNG/CMYK/10-8            848643        848259        -0.05%
Benchmark/PNG/CMYK/100-8           891701        851717        -4.48%
Benchmark/PNG/CMYK/1000-8          4884737       884741        -81.89%
Benchmark/BMP/RGBA/10-8            400           400           +0.00%
Benchmark/BMP/RGBA/100-8           688           688           +0.00%
Benchmark/BMP/RGBA/1000-8          3440          3440          +0.00%
Benchmark/BMP/RGBA64/10-8          1200          416           -65.33%
Benchmark/BMP/RGBA64/100-8         80688         704           -99.13%
Benchmark/BMP/RGBA64/1000-8        8003450       3456          -99.96%
Benchmark/BMP/NRGBA/10-8           800           416           -48.00%
Benchmark/BMP/NRGBA/100-8          40688         704           -98.27%
Benchmark/BMP/NRGBA/1000-8         4003453       3456          -99.91%
Benchmark/BMP/NRGBA64/10-8         1200          416           -65.33%
Benchmark/BMP/NRGBA64/100-8        80688         704           -99.13%
Benchmark/BMP/NRGBA64/1000-8       8003451       3456          -99.96%
Benchmark/BMP/Alpha/10-8           504           416           -17.46%
Benchmark/BMP/Alpha/100-8          10688         704           -93.41%
Benchmark/BMP/Alpha/1000-8         1003446       3456          -99.66%
Benchmark/BMP/Alpha16/10-8         600           416           -30.67%
Benchmark/BMP/Alpha16/100-8        20688         704           -96.60%
Benchmark/BMP/Alpha16/1000-8       2003451       3456          -99.83%
Benchmark/BMP/Gray/10-8            2464          2464          +0.00%
Benchmark/BMP/Gray/100-8           2456          2456          +0.00%
Benchmark/BMP/Gray/1000-8          2456          2456          +0.00%
Benchmark/BMP/Gray16/10-8          600           416           -30.67%
Benchmark/BMP/Gray16/100-8         20688         704           -96.60%
Benchmark/BMP/Gray16/1000-8        2003450       3456          -99.83%
Benchmark/BMP/Paletted/10-8        2464          2464          +0.00%
Benchmark/BMP/Paletted/100-8       2456          2456          +0.00%
Benchmark/BMP/Paletted/1000-8      2456          2456          +0.00%
Benchmark/BMP/YCbCr/10-8           720           416           -42.22%
Benchmark/BMP/YCbCr/100-8          32688         704           -97.85%
Benchmark/BMP/YCbCr/1000-8         3203455       3456          -99.89%
Benchmark/BMP/NYCbCrA/10-8         800           416           -48.00%
Benchmark/BMP/NYCbCrA/100-8        40688         704           -98.27%
Benchmark/BMP/NYCbCrA/1000-8       4003454       3456          -99.91%
Benchmark/BMP/CMYK/10-8            800           416           -48.00%
Benchmark/BMP/CMYK/100-8           40688         704           -98.27%
Benchmark/BMP/CMYK/1000-8          4003453       3456          -99.91%
Benchmark/TIFF/RGBA/10-8           2800          2800          +0.00%
Benchmark/TIFF/RGBA/100-8          2800          2800          +0.00%
Benchmark/TIFF/RGBA/1000-8         2800          2800          +0.00%
Benchmark/TIFF/RGBA64/10-8         2896          2896          +0.00%
Benchmark/TIFF/RGBA64/100-8        3712          3712          +0.00%
Benchmark/TIFF/RGBA64/1000-8       11008         11008         +0.00%
Benchmark/TIFF/NRGBA/10-8          2800          2800          +0.00%
Benchmark/TIFF/NRGBA/100-8         2800          2800          +0.00%
Benchmark/TIFF/NRGBA/1000-8        2800          2800          +0.00%
Benchmark/TIFF/NRGBA64/10-8        2896          2896          +0.00%
Benchmark/TIFF/NRGBA64/100-8       3712          3712          +0.00%
Benchmark/TIFF/NRGBA64/1000-8      11008         11008         +0.00%
Benchmark/TIFF/Alpha/10-8          2960          2864          -3.24%
Benchmark/TIFF/Alpha/100-8         13216         3232          -75.54%
Benchmark/TIFF/Alpha/1000-8        1006898       6912          -99.31%
Benchmark/TIFF/Alpha16/10-8        3056          2864          -6.28%
Benchmark/TIFF/Alpha16/100-8       23216         3232          -86.08%
Benchmark/TIFF/Alpha16/1000-8      2006901       6912          -99.66%
Benchmark/TIFF/Gray/10-8           1784          1784          +0.00%
Benchmark/TIFF/Gray/100-8          1784          1784          +0.00%
Benchmark/TIFF/Gray/1000-8         1784          1784          +0.00%
Benchmark/TIFF/Gray16/10-8         1816          1816          +0.00%
Benchmark/TIFF/Gray16/100-8        1992          1992          +0.00%
Benchmark/TIFF/Gray16/1000-8       3832          3832          +0.00%
Benchmark/TIFF/Paletted/10-8       7928          7928          +0.00%
Benchmark/TIFF/Paletted/100-8      7928          7928          +0.00%
Benchmark/TIFF/Paletted/1000-8     7928          7928          +0.00%
Benchmark/TIFF/YCbCr/10-8          3184          2864          -10.05%
Benchmark/TIFF/YCbCr/100-8         35232         3232          -90.83%
Benchmark/TIFF/YCbCr/1000-8        3206914       6912          -99.78%
Benchmark/TIFF/NYCbCrA/10-8        3248          2864          -11.82%
Benchmark/TIFF/NYCbCrA/100-8       43216         3232          -92.52%
Benchmark/TIFF/NYCbCrA/1000-8      4006906       6912          -99.83%
Benchmark/TIFF/CMYK/10-8           3248          2864          -11.82%
Benchmark/TIFF/CMYK/100-8          43216         3232          -92.52%
Benchmark/TIFF/CMYK/1000-8         4006903       6912          -99.83%

My library should also speed up "copy" function (from an image type to another).

The modifications in the standard library and x/image are really straightforward:

  • replace all \.At\(.*\)\.RGBA\(\) to a call to a AtFunc
  • call NewAtFunc() before a "y/x" loop

The image/jpeg.toYCbCr() is tricky.
You need to call NewAtFunc in image/jpeg.encoder.writeSOS() and pass the AtFunc to toYCbCr().

I also had to move my library to the standard library, because the go tool complained about bad imports...

As you can see: https://github.com/pierrre/imageutil
my code is tested and it returns the same results as the standard library.

@bradfitz bradfitz added this to the Unplanned milestone May 19, 2016
@bradfitz

This comment has been minimized.

Copy link
Member

commented May 19, 2016

To @nigeltao for triage.

@nigeltao

This comment has been minimized.

Copy link
Contributor

commented May 22, 2016

Yeah, encoding arbitrary images can be faster, although I wouldn't do it this way. Ideally, we shouldn't call any functions at all per-pixel, inside the inner loop. We want zero calls, rather than one (the AtFunc) or two (At and then RGBA). Instead, I think you'd want something like a

ToRGBA64(dst []color.RGBA64, sRect image.Rectangle) (dRect image.Rectangle)

method (although that name isn't great) to do the conversion in batches, similar to the way that e.g. the io.Reader interface deals with []byte and not byte, and a compress/zlib.Reader implements io.Reader and not io.ByteReader.

In hindsight, maybe the core image.Image method should have been this instead of At, but we can't change that until Go 2.

For completeness, a separate approach (type switching on the source image type) is taken by the image/draw and golang.org/x/image/draw pacages.

@pierrre

This comment has been minimized.

Copy link
Author

commented May 23, 2016

We want zero calls

I agree

Instead, I think you'd want something like a

ToRGBA64(dst []color.RGBA64, sRect image.Rectangle) (dRect image.Rectangle)

Do you mean a ToRGBA64() method for all image types? (in the Image interface)

How do you determine the size of sRect?
Does it have the same size as dst?

Is dRect really useful?

This approach requires to allocate a large slice of color.RGBA64.
Do you think it will be faster than 1 function call per pixel?

It also requires to rewrite all "image encode" functions in a non trivial way.

In hindsight, maybe the core image.Image method should have been this instead of At, but we can't change that until Go 2.

Of course.

It should be relatively easy to write a function NewToRGBA64Func(m image.Image) ToRGBA64Func and a type type ToRGBA64Func func(dst []color.RGBA64, sRect image.Rectangle).
(do you really need dRect image.Rectangle)?

It doesn't change the Image interface.

For completeness, a separate approach (type switching on the source image type) is taken by the image/draw and golang.org/x/image/draw pacages.

This approach requires to write a specific code for each image type.

@nigeltao

This comment has been minimized.

Copy link
Contributor

commented May 23, 2016

I mean that ToRGBA64 should be a method that encoders look for. We can't add any methods to the image.Image interface in Go 1.x, though. The sRect and dRect are meant to be 2-D equivalent to the io.ReaderAt interface.

Yes, it will mean allocating, but I still suspect that it will be significantly faster than 1 function call per pixel.

@nigeltao

This comment has been minimized.

Copy link
Contributor

commented Oct 21, 2017

This has come up again in https://go-review.googlesource.com/c/go/+/72370 "image/draw: reduce drawPaletted allocations for special source cases"

I'm still not sure what the right answer is in the long term, but just noting an idea in the short term, before I forget it:


We could add AtDotRGBA methods to all the concrete image types, such as *image.RGBA. m.AtDotRGBA(x, y) is conceptually equivalent to m.At(x, y).RGBA(), except that it avoid the allocation and indirection of the color.Color interface. The AtDotRGBA name is admittedly awkward but tries to avoid ambiguity with the existing method names: RGBAAt is already taken and has different semantics.

An alternative is to add a RGBA64At(x, y) method to all of the concrete image types, not just *image.RGBA64. The concept is very similar to AtDotRGBA but it returns one color.RGBA64 value instead of four uint32 values.

(Yes, in hindsight, color.Color's RGBA method should have been named RGBA64, and return one color.RGBA64 value instead of four uint32 values. But that ship has sailed until at least Go 2.0, if not beyond).

We can't change the image.Image interface, for backwards compatibility, but encoders (or image/draw) can sniff for this AtDotRGBA or RGBA64At method.

The subtle difference between this idea and the OP is that the OP is asking for a function or method that returns a function typed variable, and e.g. the jpeg encoder would call that function inside the inner loop. This idea adds a method that returns (4 x uint32) or returns (1 x color.RGBA64). The difference in the jpeg package would be

f := imageutil.NewAtFunc(m)
// f has function type.
r, g, b, a := f(x, y)

versus

f := imageutil.NewAtter(m)
// f has interface type.
r, g, b, a := f.AtDotRGBA(x, y)

where the atter type and NewAtter's body is is:

type atter interface{ AtDotRGBA(etc) (etc) } // TODO: atter is a terrible name.

if a, ok := m.(atter); ok {
  return a
}
return makeFallbackAtter(m)

To repeat, I'm not saying that this idea is a good idea (or a better idea than the OP), but I still wanted to record it.

Long term, I'd still like some sort of bulk-operations method, analgous to io.Reader instead of io.ByteReader, but it might not be an either/or decision and it might be possible to do both.

@gopherbot

This comment has been minimized.

Copy link

commented Oct 22, 2017

Change https://golang.org/cl/72370 mentions this issue: image/draw: reduce drawPaletted allocations for special source cases

gopherbot pushed a commit that referenced this issue Oct 25, 2017
drawPaletted has to discover R,G,B,A color values of each source image
pixel in a given rectangle. Doing that by calling image.Image.At()
method returning color.Color interface is quite taxing allocation-wise
since interface values go through heap. Introduce special cases for some
concrete source types by fetching color values using type-specific
methods.

name        old time/op    new time/op    delta
Paletted-4    7.62ms ± 4%    3.72ms ± 3%   -51.20%  (p=0.008 n=5+5)

name        old alloc/op   new alloc/op   delta
Paletted-4     480kB ± 0%       0kB ± 0%   -99.99%  (p=0.000 n=4+5)

name        old allocs/op  new allocs/op  delta
Paletted-4      120k ± 0%        0k ± 0%  -100.00%  (p=0.008 n=5+5)

Updates #15759.

Change-Id: I0ce1770ff600ac80599541aaad4c2c826855c8fb
Reviewed-on: https://go-review.googlesource.com/72370
Reviewed-by: Nigel Tao <nigeltao@golang.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.