Live data from Hacker News

Making a Go program faster with a one-character change

hmarr.com

81–90 of 249 posts

Re: Making a Go program faster with a one-character change

#81
post #21

As an old C/C++ programmer, I'm always surprised by how often software developers are surprised by the performance costs of inopportune value semantics (C and C++ even more so, punishes you severely for using value semantics when you shouldn't). I increasingly see the wisdom of languages with implicit reference semantics. It's not that value semantics can't be better (they most assuredly can be), or that reference se…

As a current Go programmer, hunting down escaping pointers via escape analysis is a common part of the routine now.

Re: Making a Go program faster with a one-character change

#82
post #30

Earlier quoted context omitted.

> perhaps the problem is implicit allocations rather than value semantics? I think that’s true. Expensive copies should never have been implicit. There was a story some time ago about a single keypress in the address bar of Chrome causing thousands of memory allocations. The culprit: lots of std::string arguments up and down the call stack. Rust gets this right, with the hindsight of C++’s example: “a = b” is a move…

> except for plain data types where copying is literally memcpy what do you mean by this? If I say `let x = 5; let y = x;` in rust, that's a "plain data type copy" of a stack value, but memcpy is usually used to copy heap memory. What connection between copying of primitive simple stack values and memcpy are you suggesting here?

> What connection between copying of primitive simple stack values and memcpy are you suggesting here?

They're just using 'memcpy' as a shorthand for saying the bitpattern is blitted. Semantically, that's like a memcpy. The point is, there are no expensive allocations, nor do any embedded pointer fields need adjusted, etc.

Re: Making a Go program faster with a one-character change

#83
post #21

As an old C/C++ programmer, I'm always surprised by how often software developers are surprised by the performance costs of inopportune value semantics (C and C++ even more so, punishes you severely for using value semantics when you shouldn't). I increasingly see the wisdom of languages with implicit reference semantics. It's not that value semantics can't be better (they most assuredly can be), or that reference se…

Having used C++ relatively little, and a long time ago (and never used Go), I don't think I ever realized that value semantics could be used to implicitly clone heap objects

Yeesh

Re: Making a Go program faster with a one-character change

#84
post #33

Earlier quoted context omitted.

I also have a background in C/C++, etc and I've only ever found myself missing value semantics when I use languages with implicit reference semantics. I guess I always figured the solution was "value semantics with better education / tooling". Education: people should understand value semantics. Tooling: imagine an IDE that highlights allocation points automatically (or perhaps the problem is implicit allocations rat…

> I've only ever found myself missing value semantics when I use languages with implicit reference semantics. Oh, I miss it every time. ;-) I will say though that some newer languages seem to have a confused idea about how to offer mixed semantics. A bunch of them tie semantics to types. The ideal interface can vary by usage context. It's hard enough getting the semantics right as the callee (as opposed to caller), l…

I think this is half right. For anything 64 bits or smaller, value semantics are pretty much always going to be better. That said, being able to choose between value and reference semantics for larger objects per object is a pretty useful feature.

Re: Making a Go program faster with a one-character change

#85

Earlier quoted context omitted.

I'm a dumb dumb. Can you define "implicit reference semantics" and "value semantics"? You use the phrases several times in your post, but I don't really understand what you mean. If it helps, I'm not a C++ programmer, but I am familiar with higher level languages like Go, Python, Ruby, PHP and Javascript.

It's the difference between assigning/passing around "copies of the data" vs. assigning/passing around "the memory address for that data" under the hood. PHP, for example, has explicit references. If you have an `$arr1=array(1,2,3)` and an `$arr2 = $arr1`, that second array is a full copy of the first array, and updating $arr1 does nothing to $arr2. Similarly, `function update_array($arr) { $arr[0] = 'cake'; }` calle…

PHP has implicit references too, objects are passed by reference by default (primitives by value, like your note)

Re: Making a Go program faster with a one-character change

#86
post #21

As an old C/C++ programmer, I'm always surprised by how often software developers are surprised by the performance costs of inopportune value semantics (C and C++ even more so, punishes you severely for using value semantics when you shouldn't). I increasingly see the wisdom of languages with implicit reference semantics. It's not that value semantics can't be better (they most assuredly can be), or that reference se…

[deleted]

Re: Making a Go program faster with a one-character change

#87
post #62

Earlier quoted context omitted.

I'm a dumb dumb. Can you define "implicit reference semantics" and "value semantics"? You use the phrases several times in your post, but I don't really understand what you mean. If it helps, I'm not a C++ programmer, but I am familiar with higher level languages like Go, Python, Ruby, PHP and Javascript.

If you're familiar with Python and Go, you'll likely be able to quickly spot the differences in how they handle parameter passing. Python uses references and Go uses value.

Go maps and channels have reference semantics. Slices are passed and returned by value, but backing arrays are often shared (not copied) in an error-prone way, so it’s safest to pretend they have move semantics and treat only one copy as valid.

IMHO they should have used pointers everywhere they didn’t want value semantics with deep copies.

Re: Making a Go program faster with a one-character change

#88

Earlier quoted context omitted.

I'm a dumb dumb. Can you define "implicit reference semantics" and "value semantics"? You use the phrases several times in your post, but I don't really understand what you mean. If it helps, I'm not a C++ programmer, but I am familiar with higher level languages like Go, Python, Ruby, PHP and Javascript.

It's the difference between assigning/passing around "copies of the data" vs. assigning/passing around "the memory address for that data" under the hood. PHP, for example, has explicit references. If you have an `$arr1=array(1,2,3)` and an `$arr2 = $arr1`, that second array is a full copy of the first array, and updating $arr1 does nothing to $arr2. Similarly, `function update_array($arr) { $arr[0] = 'cake'; }` calle…

That's not technically correct with regards to PHP. Your statement that any changes to $arr1 or $arr2 only impact the one in question, however, is accurate. If no changes are made they still refer to the same data in memory. It's copy-on-write semantics.

$arr1 = [1,2,3]; // $arr1 is a pointer to a zval array [1,2,3] and refcount:1

$arr2 = $arr1; // $arr1 and $arr2 are pointers to the same zval array but incremented refcount to 2.

$arr2[] = 4; // at this point, $arr2 creates a new zval array, copies over the data from the first, sets the recount to 1, and appends int(4). The [1,2,3] array has its refcount decremented to 1 as it's still referenced by $arr1.

[1] http://hengrui-li.blogspot.com/2011/08/php-copy-on-write-how...

Re: Making a Go program faster with a one-character change

#89
post #21

As an old C/C++ programmer, I'm always surprised by how often software developers are surprised by the performance costs of inopportune value semantics (C and C++ even more so, punishes you severely for using value semantics when you shouldn't). I increasingly see the wisdom of languages with implicit reference semantics. It's not that value semantics can't be better (they most assuredly can be), or that reference se…

I think the main issue in C++ isn't value semantics, it's deep copy semantics. E.g. in a functional language ADTs are immutable and don't have identity. They can be freely copied, or not, passed by reference or by value, but they are never deep copied. Comparison may be deep, but not passing them.

That is to say, I think I mostly am agreeing with you. In Java, objects are always passed by reference, never by value, and never implicitly copied. But Java doesn't have any value types other than primitives. When I added ADTs to Virgil, I wanted to get the best of both worlds; objects are pass by reference, like Java, and ADTs are immutable, identity-less, so they are deep compared but never deep copied. (ADTs in Virgil can also sometimes be flattened, so they don't necessarily result in heap allocation).

Re: Making a Go program faster with a one-character change

#90
post #21

As an old C/C++ programmer, I'm always surprised by how often software developers are surprised by the performance costs of inopportune value semantics (C and C++ even more so, punishes you severely for using value semantics when you shouldn't). I increasingly see the wisdom of languages with implicit reference semantics. It's not that value semantics can't be better (they most assuredly can be), or that reference se…

> I increasingly see the wisdom of languages with implicit reference semantics.

I spend most of my time in a JVM language of one flavor or another, and when I was learning Go, the first thing that stuck out at me was, "why would I ever want the compiler to invisibly copy a data structure for me?"

I suppose the primary reason is to prevent the callee from modifying the caller's data out from under them; unless you pass a reference value, you know the callee cannot modify your data.

But, as someone who leans heavily into "everything should be as immutable as possible," the second thing that stuck out at me was "wait, a struct can't have const fields?"

When I write code, it's common to have references to immutable classes thrown around with wild abandon, heedless of ownership, threads, or good taste, because the data just can't change. But that's a paradigm that Go simply doesn't support.

Post reply on HN