Hacker News new | past | comments | ask | show | jobs | submit login

These "memory models" are too complex for languages intended for dilettante developers. It was a disaster in Java/C#. Not even more than a handful of programmers in existence know in depth how it works, as in, can they understand any given trivial program in their language. At best they only know some vague stuff like that locking prevents any non visibility issues. It goes far deeper than that though (which is also the fault of complex language designs like Java and C#).

The common programmer does not understand that you've just transformed their program - for which they were taught merely that multiple threads needs synchronization - into a new game, which has an entire separate specification, where every shared variable obeys a set of abstruse rules revolving around the happens-before relationship. Locks, mutexes, atomic variables are all one thing. Fences are a completely different thing. At least in the way most people intuit programs to work.

Go tries to appeal to programmers as consumers (that is, when given a choice between cleaner design and pleasing the user who just wants to "get stuff done", they choose the latter), but yet also adds in traditional complexities like this. Yes, there is performance trade off to having shared memory behave intuitively, but that's much better than bugs that 99% of your CHOSEN userbase do not know how to avoid. Also remember Go has lots of weird edge cases, like sharing a slice across threads can lead to memory corruption (in the C / assembly sense, not merely within that array) despite the rest of the language being memory-safe. Multiply that by the "memory model".

Edit: forgot spaces between paragraphs.




> These "memory models" are too complex for languages intended for dilettante developers.

It would be nice if sometime we stopped pretending that beginners are too slow to know/understand things and instead faced the fact that their instructors and mentors are bad at teaching.


If "not even more than a handful of programmers" understand something, then it's objectively wrong to refer to all programmers - approximately all programmers - as "dilletantes".

Also, maybe you are different, but I can only keep so much in my head at a time. If I can keep something simple or abstract it away so I can focus on other details, that doesn't make me a dilletante. It makes me more effective at what I'm actually trying to do.


Not sure why people keep deducing this point I have not made. I said Go markets to dilletante programmers, which is a reason to make it simpler, not more complex. Any language with "the memory model" is complex. I do not fully grasp the memory model, either, as it requires full time investment.


They are not too complex for "languages intended for dilettante developers": they can (and should) use sequential consistency or locks everywhere.


How many programmers do you know put locks around polling varibles for seemingly no reason (as they are not cognizant of the memory model)?


Well, while it may appear gatekeeping, maybe those dilettante developers should be using something else instead, like BASIC?


CPython has a pleasant memory model from what I've heard :)


Aha. The other day you were arguing for education as a silver bullet /g


Were I?

So here is my argument, maybe those developers should bother to actually learn about what they are trying to do in first place.


All expert developers were dilettante at some point. The only way to become an expert in some specific area is to study and practice it. It might make you a better developer even if you don't end up using it in anger often (or at all).


All dilettante developers should only use javascript and dart.


> Go has lots of weird edge cases, like sharing a slice across threads can lead to memory corruption (in the C / assembly sense, not merely within that array)

Source?




Er, your summary does not at all describe what is going on there. Like, all of that code violates the memory model, so whatever it accomplishes is irrelevant.


> Like, all of that code violates the memory model,

and?

> so whatever it accomplishes is irrelevant.

I have no idea what point you are making. _Of course_ there has to be a bug in the code for there to be a buffer overflow vuln. Or are you objecting that they put contrived code to make the race work better (this is the concept of a PoC)? None of the patterns in that code are unlikely in practice.


> I have no idea what point you are making. _Of course_ there has to be a bug in the code for there to be a buffer overflow vuln. Or are you objecting that they put contrived code to make the race work better (this is the concept of a PoC)?

The original claim was that "Go has lots of weird edge cases, like sharing a slice across threads can lead to memory corruption." But that's not the whole picture, you have to violate the memory model, too. And that's not interesting, because if you violate the memory model, literally any consequence is fair game.

Maybe your point is (a) it's easy to violate the memory model, and/or (b) bugs that violate the memory model have surprising consequences? I don't agree with (a); the situation can always be improved, but it's easy to spot and fix data races, and Go provides plenty of tooling for that purpose. And I guess I agree with (b) in the basic sense, but that's just a truism, for the reasons stated above.


> because if you violate the memory model, literally any consequence is fair game.

Any consequence is _not_ fair game. "Memory Models" only involve stuff like tossing out sequential consistency [1]. They never say or imply something like "if you have a data race, anything can happen [including executing code on the stack]". Go slices exposing implementation details in a way that makes the language memory-unsafe is a completely different issue. If Go was sequentially consistent (so it had no "Memory Model" to violate), it would still not make the language memory-safe, because it would still write the array pointer and be pre-empted before writing the length.

> And that's not interesting

It matters because all programs have bugs (apparently), and so we'd like them to fail in a less harmful way than executing shellcode submitted by a client.

> it's easy to spot and fix data races, and Go provides plenty of tooling for that purpose.

Never used the data race detector but it probably can only identify low hanging fruit, and is not a substitute for the developer education problem.

Okay I think I see your confusion: You can actually avoid slices causing buffer overflows because the language requires you to have a happens-before relationship for all data shared across threads in the first place. That is, even if you share a boolean or across threads, you would be sure to establish a happens-before relationship if you are in the know. However, this does not rebuke my original argument, which assumes that most devs are not in the know. They do not know about slices being unsafe, nor do they know about happens-before. So they are not educated to prevent this mistake. Also, avoiding data races is hard.

1. https://en.wikipedia.org/wiki/Sequential_consistency


> They never say or imply something like "if you have a data race, anything can happen [including executing code on the stack]"

They absolutely do.

https://software.intel.com/content/www/us/en/develop/blogs/b...

Violating the memory model gets you undefined behavior.

> However, this does not rebuke my original argument, which assumes that most devs are not in the know. They do not know about slices being unsafe, nor do they know about happens-before

I just don't agree. Go programmers know that nothing is safe for concurrent access unless explicitly noted otherwise. They don't have any confusion about slices requiring synchronization.

Concurrent programming isn't trivial but neither is it impossible. And data races are critical bugs that can be subtle, but are straightforward to identify, and straightforward to fix.


Okay, well your (wrong) semantic argument that "GMM violation = UB" is irrelevant, so I'll stop arguing against it other than hinting that there is not one single mention of the word "undefined" in the GMM spec. Back on topic: Go is not memory-safe. Your belief that "GMM violation = UB", where UB = memory corruption literally and by definition implies that Go is not memory-safe. Java (which is where the term "memory model" comes from) is memory-safe, C# is memory-safe. Go is not.

Dilettante programmers certainly do not know the following:

1. Go slices, strings, and interface values are unsafely non-atomic. It's documented on some obscure page (even the spec does not document it AFAIK, which is also broken).

2. What a data race is

Even if they know #1, they will still write code like: modifying a slice within a structure and setting a thread-shared pointer to point to that structure.

Again, most programmers are taught "things need locks, for reasons". At best, they will pointlessly lock things, then another programmer will come "debunk" them and remove the lock because "the thing being locked is atomic". Note how none of this involves any thought of the memory model. That's because they do not know it exists.

As for people who know #2, yes that is enough to avoid memory corruption without needing to know #1, however, they are not sufficiently informed how much data races matter (as executing shellcode is not an expected outcome of writes to your data being non observable).


> GMM violation = UB

This is definitionally correct (shrug)

> Dilettante programmers certainly do not know [that] Go slices, strings, and interface values are unsafely non-atomic.

Yes. They do. As soon as a Go programmer learns that there is such a thing as concurrency and "thread safety" they learn that nothing in Go is "thread safe" by default.

> Go is not memory-safe.

"Memory-safe" is not a precisely defined concept. Go is memory safe by some definitions, not by others.


Thinking on: "[data races] are straightforward to identify"

It's a the same as the problem of knowing what data is used in what thread, which is hard and unsolvable by automation, so I doubt it's an easy problem.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: