Live data from Hacker News

Profiling Go Applications with Flamegraphs

brendanjryan.com

11–20 of 28 posts

Re: Profiling Go Applications with Flamegraphs

#11
A nice writeup, thanks. There are a few variations on this workflow that I've found useful in practice; perhaps they'll be helpful to some folks:

- Linux perf can profile unmodified Go programs. This is handy when your application doesn't expose the /debug/pprof endpoint. (http://brendangregg.com/FlameGraphs/cpuflamegraphs.html#perf has detailed instructions)

- Recent versions of https://github.com/google/pprof include a flamegraph viewer in the web UI. This is handy when you want a line-level flamegraph instead of a function-level flamegraph.

Re: Profiling Go Applications with Flamegraphs

#12
post #2

I’m trying to figure out why I find Go so hard to read. Am I mostly alone with this?

There must be individual differences at play. I find Go the easiest to read of any language I know (and I've only been looking into it, reading more than writing, for a few weeks). This is part intrinsic limitations (it's a simple language, and there tends to be one obvious way to do ordinary things), in part culture (a strong leaning towards consistent idioms). Perhaps these aspects of the language are a more natural fit with some of us than others.

As for short variable names -- I think they're a readability boon where they are essentially placeholders into common structures that you can read as a whole unit at a glance (counters in loops, readers/writers/buffers in input/output idioms etc), but detrimental elsewhere.

Re: Profiling Go Applications with Flamegraphs

#13
post #9

Earlier quoted context omitted.

I've mostly interpreted that to use single character names for method receivers and loop variables. I think those are defensible because you know where to find them if you need their definition (in the method definition or in the loop). I don't think that assigning terse names (such as the variable "ra" from the OP) to variables that might be declared anywhere in a function is helpful.

I agree, and the link I posted states as much. I think the problem comes when people take that advice without nuance and think it gives them carte blanche to make everything as obscure as possible. And really, it’s not about whether or not we can understand our own code, but can the future developers who have to maintain it after we leave. I kinda worry that the Go community is creating a lot of unmaintainable code r…

I see an intrinsic pattern to variable naming in Go and not some randomly assigned single letters.

I work on Java code where variables name look like 'reconnectDelayToInitiallyEstablishJMSConnection" Even though very clear name it really exhaust me while reading code like this. Java explicitness things like spreading code over dozens of files and directories for a functionality that could ideally be in 1-2 reasonably sized files. And methods that actually do something instead of calling another methods. So I guess code I deal with is understandable at a method level which finally does something. But overall it is too sprawling to fit everything in mind while looking at a functionality.

Re: Profiling Go Applications with Flamegraphs

#14
post #10

Earlier quoted context omitted.

I've mostly interpreted that to use single character names for method receivers and loop variables. I think those are defensible because you know where to find them if you need their definition (in the method definition or in the loop). I don't think that assigning terse names (such as the variable "ra" from the OP) to variables that might be declared anywhere in a function is helpful.

Though that would still be idiomatic go code. For what it is worth, I do agree with you. Short variable names on a function are a hassle. You have to lookup what they mean, which slows down understanding. n = copy(p, b.buf[b.r:b.w]) Oh better go to the top and see what those are again... https://github.com/golang/go/blob/master/src/bufio/bufio.go#...

I find to understand a piece of code, I need to know what all the involved variables are, which I'll have to do regardless of long or short names.

Once I know what they all are, I find it's easier for me to track them through the function if they have short names.

Something java style like

    numBytesWritten = copy(destinationBuffer, reader.buffer[reader.readPosition:reader.writePosition]
is much harder for me to follow.

Re: Profiling Go Applications with Flamegraphs

#15
post #13
post #9

Earlier quoted context omitted.

I agree, and the link I posted states as much. I think the problem comes when people take that advice without nuance and think it gives them carte blanche to make everything as obscure as possible. And really, it’s not about whether or not we can understand our own code, but can the future developers who have to maintain it after we leave. I kinda worry that the Go community is creating a lot of unmaintainable code r…

I see an intrinsic pattern to variable naming in Go and not some randomly assigned single letters. I work on Java code where variables name look like 'reconnectDelayToInitiallyEstablishJMSConnection" Even though very clear name it really exhaust me while reading code like this. Java explicitness things like spreading code over dozens of files and directories for a functionality that could ideally be in 1-2 reasonably…

I would just argue for a happy median. Enough to convey intent, without being verbose. Your java example is clearly exhausingly verbose (I’ve seen similar in C#), where it seems in Go it would probably be written:

rd := 1000

How is anyone supposed to understand at a glance what this value is for? Why not just:

reconnectionDelay := 1000

Intent is clear.

And now, I have strayed way too far off topic (I’ve done some flamegraph style debugging in .Net, super useful!), and should probably apologize to the OP.

Re: Profiling Go Applications with Flamegraphs

#17
post #15
post #13

Earlier quoted context omitted.

I see an intrinsic pattern to variable naming in Go and not some randomly assigned single letters. I work on Java code where variables name look like 'reconnectDelayToInitiallyEstablishJMSConnection" Even though very clear name it really exhaust me while reading code like this. Java explicitness things like spreading code over dozens of files and directories for a functionality that could ideally be in 1-2 reasonably…

I would just argue for a happy median. Enough to convey intent, without being verbose. Your java example is clearly exhausingly verbose (I’ve seen similar in C#), where it seems in Go it would probably be written: rd := 1000 How is anyone supposed to understand at a glance what this value is for? Why not just: reconnectionDelay := 1000 Intent is clear. And now, I have strayed way too far off topic (I’ve done some fla…

(to continue straying for a moment..) perhaps though it best depends on the variable specifics: like how often it appears, how far apart multiple uses are, etc.

Some natural limits might be: (1) single letters for extremely local terms whose structural meaning is more salient than denotation (canonical example: loop counter); (2) fully spelled-out terms for globally-significant terms (not necessarily in global scope) whose denotation is crucial (canonical example: an app configuration value).

Even two short camel-cased words often seem unnecessarily verbose for a loop counter to me. Whereas an important global config variable might justify the full THIS_IS_WHAT_I_AM_FOR treatment.

Re: Profiling Go Applications with Flamegraphs

#18
post #9

Earlier quoted context omitted.

I've mostly interpreted that to use single character names for method receivers and loop variables. I think those are defensible because you know where to find them if you need their definition (in the method definition or in the loop). I don't think that assigning terse names (such as the variable "ra" from the OP) to variables that might be declared anywhere in a function is helpful.

I agree, and the link I posted states as much. I think the problem comes when people take that advice without nuance and think it gives them carte blanche to make everything as obscure as possible. And really, it’s not about whether or not we can understand our own code, but can the future developers who have to maintain it after we leave. I kinda worry that the Go community is creating a lot of unmaintainable code r…

Java went through a phase of not having inner classes, autoboxing, enums, generics, and looping over iterables. The code from that era was burned to the ground for being unreadable shit.

This is survivable, if they're motivated to fix the glaring omissions in Go.

Re: Profiling Go Applications with Flamegraphs

#19
Does anyone else have this problem with go indentation:

    func (sc *SimpleClient) Timing(s string, d time.Duration, sampleRate float64,
        tags map[string]string) error {
        return sc.send([...]
The wrapped parameter list is indented to the same level as the function body. Is this how it's supposed to be done?

Re: Profiling Go Applications with Flamegraphs

#20
post #19

Does anyone else have this problem with go indentation: func (sc *SimpleClient) Timing(s string, d time.Duration, sampleRate float64, tags map[string]string) error { return sc.send([...] The wrapped parameter list is indented to the same level as the function body. Is this how it's supposed to be done?

Surprisingly, it is. (Though personally in Go I wouldn't wrap the parameter list at all (and I think maybe most also doesn't?). Then you just let your editor soft-wrap to match current window width; the continued line indent can be configured per personal taste.)
Post reply on HN