On Thu, Oct 1, 2015 at 12:51 AM, Taco de Wolff <
tacod...@gmail.com> wrote:
>
> I would outline such optimizations as follows, but correct me if I'm wrong:
> Take for example the `ParseFloat` function. It requires a `string` because
> that is a stronger guarantee than `[]byte`, namely `string` enforces
> non-mutability within the function. Because the atof.go functions are pure
> it is safe to say that they have no state lingering or external
> dependencies. Therefore, unless concurrently used perhaps!, it is safe to
> call such functions without a copy. The compiler would recognize that the
> bytes to string conversion is just a cast and not a copy. This would mean it
> is preferable to write functions accepting strings (for that is a stronger
> guarantee) and there is no need to write duplicated code.
The interesting case is, of course, parallel use. When can we safely
treat a []byte as a string? Only when we know that the contents of
the []byte do not change. If we change the memory model to say that a
program with a race condition is undefined, which is approximately how
we treat race conditions anyhow, then given f(string(b)) where b is a
[]byte the compiler can assume that the contents of b will not change
if there are no possible happens-before relationships in f--that is,
if f does not have any synchronization points before or after which b
might change.
This will be true if f does not call any sync functions, does not have
any channel operations, does not start any goroutines, etc., and if
the same is true for all functions call by f. This can be determined
statically if f is a function or non-interface method call, and if
everything it calls are functions or non-interface methods. I think
we can determine this for the special case of strconv.ParseFloat and
friends.
A similar static analysis can apply for f([]byte(s)). That case is
different--we know that s will not change, so we need to look for any
case where f might try to change the slice contents.
How general this would be, I don't know. It doesn't help for the
important case of writer.Write([]byte(s)), when writer is an
io.Writer. Still, it seems worth investigating.
Ian