dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.87k stars 781 forks source link

Optimization for string interpolation - simple scenarios: unfolding constants and lowering to concatenation #16247

Open abonie opened 10 months ago

abonie commented 10 months ago

Seems like there is a lot we could do to improve perf of string interpolation. One good example is https://github.com/fsharp/fslang-suggestions/issues/1108, but also some low hanging fruits to start with could be unfolding compile time constants, e.g.:

[<Literal>]
let x = "hello"

[<Literal>]
let y = "world"

let z = $"{x} {y}!"

in the above, the last line could be lowered to let z = "hello world!"

Another one could be lowering to System.String.Concat when it applies, e.g. let f (x: string) (y: string) = $"{x},{y}." could be rewritten as let f (x: string) (y: string) = System.String.Concat(x, ",", y, "."), because we know that all expression holes are filled with objects of type string and there are at most 4 pieces to concatenate.

abonie commented 10 months ago

For the second one, here is difference in allocations from calling the first version of the function vs. the second one 1k times in a loop. Using concat: image vs. string interpolation: image

charlesroddie commented 9 months ago

I would simplify this to: implement string interpolation as String.Concat in all scenarios. With no helper method around {x} unless one is known to be required. Dealing with constants and other special cases can be treated as a subsequent optimization step.

charlesroddie commented 7 months ago

@abonie I see that the PR only works when the inner expressions are strings only. That is not the majority case. Will the PR make it easier to make all expressions concats (i.e. is it a step towards using a collector for all interpolation https://github.com/fsharp/fslang-suggestions/issues/1108) or will it make this harder by adding an exception that needs to be maintained in the future?

abonie commented 7 months ago

the PR only works when the inner expressions are strings only. That is not the majority case.

That is true. This issue is specifically about lowering to System.String.Concat and it doesn't really make sense for other cases (when inner exprs are not strings).

Will the PR make it easier to make all expressions concats (i.e. is it a step towards using a collector for all interpolation https://github.com/fsharp/fslang-suggestions/issues/1108) or will it make this harder by adding an exception that needs to be maintained in the future?

I think neither - as far as I can tell, this is largely orthogonal to interpolated string handlers, doesn't make it particularly easier or more difficult to implement them and also won't be superseded by them, since for cases where this optimization applies, it should still be faster than using a collector.

Reopened the issue, because it also mentions unfolding constants, which the PR does not cover. However, will have to estimate how much of a difference that would make vs work needed. Would be nice to tackle interpolated string handlers soon.