I need to write a service which applies particular layers upon the pictures (it's yet another map service, I need to put a balloon and apply watermark on a top of a picture).
Images I should apply layers on are taken at another web service, that can handle hundreds of requests per second with little delays.
func PutLayers(data []byte, tile_h, tile_w int) (*bytes.Buffer,error) {
read := bytes.NewBuffer(data)
tile, err := png.Decode(read)
if err != nil {
return new(bytes.Buffer), LayerError("cannot read input stream")
}
// Extract drawable object from the image
b := tile.Bounds()
dst := image.NewRGBA(image.Rect(0,0,b.Dx(),b.Dy()))
draw.Draw(dst, dst.Bounds(), tile, b.Min, draw.Src)
// Put baloon mark
b = balloon_img.Bounds()
draw.Draw(dst, image.Rect(tile_w/2, tile_h/2-b.Dy(), tile_w/2+b.Dx(), tile_h/2), balloon_img, image.ZP, draw.Over)
// Put watermark
b = watermark_img.Bounds()
draw.Draw(dst, image.Rect(tile_w/2-b.Dx()/2, tile_h - b.Dy() - 6, tile_w/2 + 3*b.Dx()/2, tile_h-6), watermark_img, image.ZP, draw.Over)
result := dst.SubImage(dst.Bounds())
buffer := new(bytes.Buffer)
png.Encode(buffer,result)
return buffer,nil
}
Unfortunately, it turned to be a bottleneck. It's very CPU hog and doesn't seem to be fast enough. Without this function I can handle as many requests as that service can, but I'm only able to do 70-80 RPS at max when turn it on, with 100% CPU usage.
I still hope I have foolishly done something wrong and a couple of tweaks will help me. Or kind of workaround.