HN user

martisch

20 karma
Posts0
Comments5
View on HN
No posts found.
Go 1.20 released 3 years ago

That is just the language definition. It is fine for an implementation to actually compare both at the same time as long as within the language you can not observe this happend. If we cant tell the read to be b happenend with a or before a (hello spectre) then for the implementation it should be fine to have done the comparison.

This is more of a constraint if the struct contains a comparison that can panic. The panic must happen in order or not at all depending how the fields are listed.

  type t struct {
        a int64
        b any
  }
Should not panic on b if a values are already different.
Go 1.20 4 years ago

Note that afaik [3]string(s) was not valid before go1.20 so no existing code should use it. The semantic equivalent had to be written as *(*[3]string)(s) which also copies the array pointed to by *[3]string)(s). The new notation is basically a shorthand and easier to discover than using *(*[3]string)(s): https://github.com/golang/go/issues/46505

The reasoning is here: https://github.com/golang/go/issues/40255

Copy of part of it:

1) While 387 support isn’t a huge maintenance burden, it does take time away from performance and feature work and represents a fair amount of latent complexity.

2) 387 support has been a regular source of bugs (#36400, #27516, #22429, #17357, #13923, #12970, #4798, just to name a few).

3) 387 bugs often go undetected for a long time because we don’t have builders that support only 387 (so unsupported instructions can slip in unnoticed).

4) Raising the minimum requirement to SSE2 would allow us to also assume many other useful architectural features, such as proper memory fences and 128 bit registers, which would simplify the compiler and runtime and allow for much more efficient implementations of core functions like memmove on 386.

5) We’re exploring switching to a register-based calling convention in Go 1.16, which promises significant performance improvements, but retaining 387 support will definitely complicate this and slow our progress.

The 5) didnt make it into go1.16 but will be focused on again for go1.17.

I think this part "Step 1) is not needed with the append approach, as we just reserve a memory location but the previous values stay there until we write them in step 2. " is not what the Go gc implementation currently actually does.

Copied from reddit: https://www.reddit.com/r/golang/comments/cn2jdh/benchmark_of...

Currently make (runtime.makeslice or runtime.mallocgc or duffzero as part of stack allocation) always zeroes the backing array of slice regardless if the element is written to directly or append to the slice. Not requiring the memclr/zeroing would need a prove pass that proves that before the loop finishes noone can observe the uninitialized value by e.g. re-slicing. Which in general when e.g. interfaces and plugins are involved wont be possible to prove. In the case of pointers the memclr is also not avoidable since the garbage collector might scan that part of the memory (if its heap allocated) any time even while the loop is running. https://github.com/golang/go/blob/e37a1b1ca6afcbe3b02d2dfd59...

There could be effects observed due to the difference of having small slices allocated on the stack vs on the heap and differing zero techniques. E.g. for size = 100 there is a jump to duffzero that clears the stack space for the backing array of the slice: https://godbolt.org/z/wRuF5z while for size = 100000 the backing array is heap allocated and zeroed as part of the runtime.makeslice call.

There is a optimization fusing make+copy (to avoid the memclr) in the pipeline for go1.14 but this would not trigger here either.https://go-review.googlesource.com/c/go/+/146719