I really liked the turkey, and I thought the solution looked elegant, so I had a go at it in CoffeeScript and node-canvas: https://gist.github.com/1475034
All requests in less than 66 ms, mean less than 19 ms.
AppEngine instances, unless they're running in a special backend instance, exist in a special containerized machine. These machines are very slow and don't have much RAM - 600 MHz and 128 MB. Based on the source that was posted on the blog, this app was running on a normal instance, as the source did not contain a backends.yaml file.
So it makes sense that a Core 2 Duo running at 2.13 GHz and slow CoffeeScript would be ~2x as fast. My personal experience of running Go code locally (on a Core i5 2500K) versus on a normal AppEngine instance showed a slowdown of around 6x or more.
This was interesting because I've never seen Go used in production yet. However, the solution is not optimal for performance (as his benchmarking suggests is one of the goals).
If there is a finite number of possible images and each image takes CPU time to generate, then why not lazy cache the images in a CDN after generating them once?
This works exactly as you describe - the app sets a cache header on the response and Google's geographically distributed front end servers will serve the cached response. You get all this for free by using App Engine.
The more complicated something is, the more chances for failure there are. Remember, this was only for compositing the image that would be shared to google plus -- the one in the browser is done client-side.
I'm working on a game with highly-stylized art that includes a lot of blobs of single colour. It surprised me at first, but the artists have had real gains using JPG instead of PNG. Also, strangely the artifacts give the art a kind of "texturized" finish that's actually kind of pleasant on tablet screens.
Maybe it's for performance reasons. I have a web server in go that generate (big) png on the fly and most of the time is spent in the png encoding (mostly the compression). PNG encoding is a heavy task.
Maybe its just me but all blogpost about go read like they where checked by a marketing guru after the have been written. The always enforce the same basic points, it always sound the same. If I somebody says "go" my mind alwasys jumps to "feels like a interpreted language".
> somebody says "go" my mind alwasys jumps to "feels like a interpreted language".
Because it does! I'm a pretty hardcore Pythonista who has never really gotten very far with compiled languages. I wrote a simple shell in C, once, but beyond that they never felt right. Somehow, Go manages to get things sufficiently "right" for me.
But more importantly, I think Go has a very strong chance of being the Clojure moment for Algol-derived languages. It's trying to address many of the same problems, and taking a similarly refreshing and pragmatic approach. Not to mention that the system-level language ecosystem is quite overdue for some reinvigoration. The glowing tone of so many Go posts may be, in part, due to a fundamental yearning for something that gets so much right -- something like Go -- to finally take off.
Well I'm the guy who runs that particular blog, and I can tell you I'm no marketing guru. While Reinaldo and I edited the post together, I'm pretty sure that the line was in his original text. (Just checked: it was.)
Maybe people keep saying Go feels like an interpreted language because it feels like an interpreted language? :-)
Well, when you're looking at posts by someone who loves a language about that language, its not really that surprising to see positive feedback in it; and that feedback is often about the expressive syntax being nice (edit <-- and that its fast).
...but that said, I wouldn't mind some impartial coverage.
Its stuck me several times how defensive and no-I'm-right the go crowd gets when anyone dislikes it. Try jumping on the google group sometime.
Anyone remember that academic paper about relative speeds of c, go and something or another? As I recall Andrew went out of his way to reimplement the whole thing in go, and make a few snarky comments about "I wonder where they got those bench marks from, because that's not what I saw".
Long answer, the Go authors (Rob Pike et all) have a pedantic issue with exceptions as implemented in Python, Java, etc. They feel they conflate errors and exceptions. Errors, unlike exceptions, are an expected part of the programming process. Exceptions, on the other hand should be for exceptional circumstances.
here is an a typical example of the Go community's attitude:
"""
I _especially_ don't want exceptions to become an oft-used alternative to multiple levels of error return, as at that point they deteriorate to action at a distance and make understanding large code bases much harder. Been there, done that, got the scars to prove it. (Mostly from C++ and not from Java, but I've seen enough Java to have a healthy fear of runtime exceptions.)
"""
Not really, no. I've always found them more trouble than they're worth. Explicit, in-line error handling works much better for me.
I'm not sure what you mean by "over and over again," in this context, though. There are only three error checks of that kind in this program. It's an unusual program anyway, in that _any_ error condition jumps to the same path: displaying the default image. In most programs you want finer control over error handling than what's shown here.
Reading the same code I also cringed, but for a different reason: the validity of `paths` is tied to the validity of `err`; you should never look at at `paths` without first checking `err`. We can solve this much better using sum types (also known as discriminate unions):
// Pseudo Go:
maybe_paths := filepath.Glob(dir + "/*.png")
case maybe_paths of {
Some paths: {
// Do things with paths
}
None: {
// Handle error case
}
}
This makes it impossible to use `paths` if `Glob` returns an error, as `paths` won't be in scope!
Furthermore, not having sum types forces us to include a distinguish value `null` for reference (pointer) types, as a way to communicate "no value". This is bad as now we cannot distinguish references that should never be `null` from those than can be `null`.
The two decades of experience we've had since the 90s, building things with exceptions, have fairly adequately demonstrated that they're not superior to return codes, despite their (apparent) theoretical advantages.
A lot of people in this sub-thread don't buy that return codes are inferior, but they really are. The issue is that the low level code can detect the error and knows some strategies that could be done about it but it's only the high level code that knows what's best (here's the best possible approach [1]). If your library is used by a batch job running on some network-detached headless server it will probably have to handle errors differently than a fat client would.
There's insufficient data to draw conclusions about the performance of the infrastructure. The application probably ran on a shared machine. We don't know the impact of the other processes running on the machine. We don't know how many requests the application handled in parallel, so we cannot divide by latency to get throughput. We don't know if the application ran on a modern machine.
[+] [-] biot|14 years ago|reply
[+] [-] yesbabyyes|14 years ago|reply
All requests in less than 66 ms, mean less than 19 ms.
[+] [-] ariwilson|14 years ago|reply
So it makes sense that a Core 2 Duo running at 2.13 GHz and slow CoffeeScript would be ~2x as fast. My personal experience of running Go code locally (on a Core i5 2500K) versus on a normal AppEngine instance showed a slowdown of around 6x or more.
[+] [-] jphackworth|14 years ago|reply
[+] [-] alexchamberlain|14 years ago|reply
[+] [-] danielrhodes|14 years ago|reply
If there is a finite number of possible images and each image takes CPU time to generate, then why not lazy cache the images in a CDN after generating them once?
[+] [-] enneff|14 years ago|reply
[+] [-] luriel|14 years ago|reply
[+] [-] cma|14 years ago|reply
[+] [-] curiouskat|14 years ago|reply
I have been thinking Go might be a good choice for a websocket proxy, like node.js is used in Juggernaut (http://flask.pocoo.org/snippets/80/).
[+] [-] enneff|14 years ago|reply
[+] [-] ars|14 years ago|reply
The images this generates have mostly flat areas of all one color - it should have been a png.
[+] [-] JabavuAdams|14 years ago|reply
[+] [-] canop_fr|14 years ago|reply
Here's (from my blog) a pprof profile of my server : http://canop.org/pub/pprof4353.0.svg so that you can see the burden.
(I didn't make comparisons with other languages so I don't know if Go's png encoder is fast or not, I suspect it isn't)
[+] [-] bostonvaulter2|14 years ago|reply
[+] [-] unknown|14 years ago|reply
[deleted]
[+] [-] nickik|14 years ago|reply
[+] [-] callahad|14 years ago|reply
Because it does! I'm a pretty hardcore Pythonista who has never really gotten very far with compiled languages. I wrote a simple shell in C, once, but beyond that they never felt right. Somehow, Go manages to get things sufficiently "right" for me.
But more importantly, I think Go has a very strong chance of being the Clojure moment for Algol-derived languages. It's trying to address many of the same problems, and taking a similarly refreshing and pragmatic approach. Not to mention that the system-level language ecosystem is quite overdue for some reinvigoration. The glowing tone of so many Go posts may be, in part, due to a fundamental yearning for something that gets so much right -- something like Go -- to finally take off.
[+] [-] enneff|14 years ago|reply
Maybe people keep saying Go feels like an interpreted language because it feels like an interpreted language? :-)
[+] [-] shadowmint|14 years ago|reply
...but that said, I wouldn't mind some impartial coverage.
Its stuck me several times how defensive and no-I'm-right the go crowd gets when anyone dislikes it. Try jumping on the google group sometime.
Anyone remember that academic paper about relative speeds of c, go and something or another? As I recall Andrew went out of his way to reimplement the whole thing in go, and make a few snarky comments about "I wonder where they got those bench marks from, because that's not what I saw".
[+] [-] comex|14 years ago|reply
[+] [-] BarkMore|14 years ago|reply
[+] [-] billmcneale|14 years ago|reply
Didn't we learn in the 90's that exceptions are far, far superior to return codes?
[+] [-] timtadh|14 years ago|reply
Long answer, the Go authors (Rob Pike et all) have a pedantic issue with exceptions as implemented in Python, Java, etc. They feel they conflate errors and exceptions. Errors, unlike exceptions, are an expected part of the programming process. Exceptions, on the other hand should be for exceptional circumstances.
I did not say that as well as they do so see what Pike has to say about the issue here: http://groups.google.com/group/golang-nuts/browse_thread/thr...
here is an a typical example of the Go community's attitude:
""" I _especially_ don't want exceptions to become an oft-used alternative to multiple levels of error return, as at that point they deteriorate to action at a distance and make understanding large code bases much harder. Been there, done that, got the scars to prove it. (Mostly from C++ and not from Java, but I've seen enough Java to have a healthy fear of runtime exceptions.) """
[+] [-] enneff|14 years ago|reply
I'm not sure what you mean by "over and over again," in this context, though. There are only three error checks of that kind in this program. It's an unusual program anyway, in that _any_ error condition jumps to the same path: displaying the default image. In most programs you want finer control over error handling than what's shown here.
[+] [-] tibbe|14 years ago|reply
Furthermore, not having sum types forces us to include a distinguish value `null` for reference (pointer) types, as a way to communicate "no value". This is bad as now we cannot distinguish references that should never be `null` from those than can be `null`.
[+] [-] ariwilson|14 years ago|reply
[+] [-] jemfinch|14 years ago|reply
[+] [-] hasmoo|14 years ago|reply
[+] [-] unknown|14 years ago|reply
[deleted]
[+] [-] danssig|14 years ago|reply
[1] http://www.gigamonkeys.com/book/beyond-exception-handling-co...
[+] [-] wallunit|14 years ago|reply
[1] http://news.ycombinator.com/item?id=3351407
[2] http://google-turkey.appspot.com/thumb/295552a0
[+] [-] liruqi|14 years ago|reply
[+] [-] obtu|14 years ago|reply
[+] [-] anacrolix|14 years ago|reply
[deleted]
[+] [-] cma|14 years ago|reply
[+] [-] adamio|14 years ago|reply
[+] [-] BarkMore|14 years ago|reply
[+] [-] freakinjoe|14 years ago|reply
[deleted]