-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/cgo, runtime: optimize C.GoString #23830
Comments
I'm not sure I understand the concern about a fault from a vectorized read past the end of the string. Seems like that could happen in Go just as easily as in C. |
@ianlancetaylor, because bytes.IndexByte starts with a slice (which contains a length), the assembly for that knows it's safe to do wide loads of many bytes up to that length only (or capacity, at least). C.GoString only takes a That's how I read it, at least. |
Oh, yeah, OK. For C strings we need to do it slightly differently. Since vector instructions are always aligned, we are fine using vectors as long as we haven't found a zero yet, but we can't read ahead. We could write special purpose code for this, but I doubt it's worth it. We could call a function in runtime/cgo that calls |
A quick GitHub search says yes, it is used a lot. Whether it is in performance-critical paths, or whether the cost is worth it, I don't know. I'll move to Unplanned, unless/until someone comes forward and says they need it or someone is inspired to dig deeper and implement themselves. |
I think using indexbyte with fake slice is safe, if all access is limited to 1 page, so doing something like:
|
@TocarIP That requires fairly strong assumptions about the optimizations present in the rest of the Go compiler and runtime. In general we have no guarantee there isn't some other thread writing to the address just after the string, and the Go memory model does not define behavior in the presence of data races, let alone data races that cross language boundaries. We could, of course, check the rest of the runtime code to ensure that such races are benign, but it seems very difficult to write a test that would reliably detect violations due to future changes. |
I'm not sure I understand what extra assumptions this introduces. IndexByte (at least asm version on amd64) already does out-of-bounds read, as long as they don't cross page for normal go strings. |
I think Ilya's strategy should be fine. IndexByte does not depend on data values past the first \0. |
Change https://golang.org/cl/97523 mentions this issue: |
Reverted in https://go-review.googlesource.com/c/go/+/97995 /cc @TocarIP |
Change https://golang.org/cl/98015 mentions this issue: |
C.GoString ends up being translated into a call to runtime.gostring, which calls findnull, which does a byte-at-a-time search for the terminating NUL.
A quick hack to use bytes.IndexByte to find the NUL shows speed-ups of almost 40%. We cant use this directly, though, because of the danger of a vectorized read past the end of the string faulting.
Perhaps we could call strlen on the C side (which is presumably well-optimized) and pass the length in to the runtime? Or write a safe (length-oblivious, aligned-load-only) IndexByte for use here?
cc @ianlancetaylor @randall77
The text was updated successfully, but these errors were encountered: