

From zero to Go: launching on the Google homepage in 24 hours - enneff
http://blog.golang.org/2011/12/from-zero-to-go-launching-on-google.html

======
biot
I'm curious to know how many instances were required and what the cost would
have been had someone been billed for it.

------
yesbabyyes
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.

~~~
ariwilson
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.

~~~
yesbabyyes
I can't argue with that, though I'm running this on just one core (single
process).

If I was better with the v8 profiler I would check to see how much time it
spends in JS land vs C, since node-canvas is all C, as well as the http
parser.

~~~
ariwilson
Go runs on a single core unless you start using channels and/or threading
libraries. So it should be apples-to-apples.

~~~
adgar
Go runs on a single core if you use channels anyway unless you specify an
environment variable (something like GO_MAX_PROCS). Not sure about threading
libraries since I haven't really considered using them in Go. I'm actually
curious what people are using them for in Go - maybe games?

~~~
4ad
GOMAXPROCS it is :-).

It's a quick fixup, the runtime will eventually schedule on multiple threads
without needing the user to specify anything.

------
danielrhodes
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?

~~~
enneff
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.

------
curiouskat
How is Go's websocket support?

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
It's great <http://golang.org/pkg/websocket/>

~~~
nl
Do websockets work on AppEngine(Go)?

~~~
enneff
No.

------
ars
This is quite offtopic, but if even programmers are using jpeg when they
should use png, what hope is there for anyone else?

The images this generates have mostly flat areas of all one color - it should
have been a png.

~~~
bostonvaulter2
Would the size of the png's be smaller?

~~~
enneff
We chose JPEG because the files were smaller and the encoding faster. The
images looked fine in either case.

------
nickik
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".

~~~
enneff
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? :-)

~~~
jbarham
I've done a fair bit of Go programming (<https://github.com/jbarham>), but
have programmed professionally mostly in Python for the past 10 years, and for
me Go does feel an interpreted language because it requires so few type
declarations compared to mainstream statically typed languages like C++ or
Java.

Checking the app source code for the article at [http://code.google.com/p/go-
thanksgiving/source/browse/app/a...](http://code.google.com/p/go-
thanksgiving/source/browse/app/app.go), the only type declaration I can see in
the body of a function is in a type switch where it obviously makes sense.
Otherwise the code uses the combined declaration and assignment := operator
([http://golang.org/doc/go_spec.html#Short_variable_declaratio...](http://golang.org/doc/go_spec.html#Short_variable_declarations))
which is type-safe because it infers the types from the value(s) on the right
hand side. IMO this is even better than working w/ a dynamically typed
language like Python because the required parameter type declarations in the
function declaration tell you the types you're dealing with, but unlike C++ or
Java you don't have to repeat that information back to the compiler.

~~~
alexchamberlain
C++11 has support for inferring types;
<http://en.wikipedia.org/wiki/C%2B%2B11#Type_inference>.

------
comex
Is Go's character type signed? If so, it's possible to make p negative, in
which case this wouldn't apply:

    
    
            if p >= len(em) {
                panic(fmt.Sprintf("element index out of range %s: "+
                    "%d >= %d", t, p, len(em)))
            }
    

although Go would still do its own runtime check for the dereference.

~~~
BarkMore
The variable "p" is a rune. Although the rune type can have negative values, p
will only have values >= 0 in this code.

~~~
comex
How so? If the character is any value less than '0' (say, '!'), p will be set
to a negative value.

~~~
BarkMore
'0' has the decimal value 48, not zero. '!' has the decimal value 33. Here's a
demo program that you can run from your browser:
<http://play.golang.org/p/qAKG9j5E4V>

All characters have values greater than or equal to zero.

~~~
Dylan16807
comex said less than '0'. 33 minus 48 is negative.

------
billmcneale
I can't help but cringe whenever I read Go code because the following:

    
    
            paths, err := filepath.Glob(dir + "/*.png")
            if err != nil {
                panic(err)
            }
    

is repeated over and over again.

Didn't we learn in the 90's that exceptions are far, far superior to return
codes?

~~~
tibbe
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`.

~~~
enneff
This kind of fussy type system is at odds with Go's design goals. It would
make the language more abstracted from the underlying machine for little gain.
I can't think of an instance of the issue you describe causing problems in
real Go code.

~~~
masklinn
> This kind of fussy type system is at odds with Go's design goals.

There is nothing fussy about it, and the only way in which it's at odds with
Go's design goals is that Go's design goals include things like "fuck you,
only core types get to be generic", "that these mistakes were resolved 20
years ago does not mean we're not going to re-introduce them" and "if we give
it a different name it's not the same thing, nah nah nah".

------
wallunit
The pirate easter egg [1] seems not to work [2].

[1] <http://news.ycombinator.com/item?id=3351407>

[2] <http://google-turkey.appspot.com/thumb/295552a0>

------
liruqi
the link is broken. something wrong with golang blog?

~~~
obtu
Great Firewall?

------
cma


~~~
adamio
Transistor density doesn't guarantee performance increase. Is AppEngine's
ability to scale and maintain <60ms consistent with Moore?

~~~
dextorious
The AppEngine is not about transistor density, it's about share-nothing and
scaling by adding cpus.

