Bug 24523 – writeln doesn't memoize its templates

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2024-04-26T16:24:31Z
Last change time
2024-04-27T01:24:03Z
Assigned to
No Owner
Creator
crazymonkyyy

Comments

Comment #0 by crazymonkyyy — 2024-04-26T16:24:31Z
copy and pasted from the open d discord some messages: ---- as far as I understand, writeln is a variadic template, so for each set of arguments you get a new instance of writeln in object code -- I would expect a trivail optiomization here with how templates auto memoize -- on practice, this generates a lot of garbage code https://godbolt.org/z/9Gx6ja5vo void main() { import std.stdio : writeln; writeln("hello"); writeln(123); writeln(123, 456); } -- it dups the template argument list 3 times -- ... why isnt writeln writen in such a way to auto memoize simplier write calls its one line of code difference -- wat? -- ```d void writeln(S...)(S args) { write(args, '\n'); } ``` given grims code, write(int,int,string) and write(int,string) are both being compiled when it chould be ```d void writeln(T...)(T args){ static foreach(a;args){write(a);} write("\n"); } ``` and only compile write(int) and write(string) --- I can't believe it, but monkyyy is actually correct on this one https://godbolt.org/z/edf46vcqv import std.stdio; void smartWriteln(T...)(T args) { static foreach(a; args) { write(a);} write("\n"); } void a() { writeln(123, 345, 789); smartWriteln(123, 345, 789); } --- etc. writeln should be cleaned up and made to memoize arguments
Comment #1 by schveiguy — 2024-04-27T01:24:03Z
Since write does exactly what is requested (loop over all parameters), it seems like the only "waste" here is a template instantiation of `write` with the particular parameters. Such a call is quite benign. See the code: https://github.com/dlang/phobos/blob/54eb95c139e09f6e7f8da3beed8407817ba184c1/std/stdio.d#L1750 And this also is going to result in extra instantiations of `write` (all the ones with single args). So in some cases, it may actually result in extra instantiations. In addition, splitting into multiple `write` calls is going to perform worse (and potentially cause weird outputs) as it locks and unlocks the underlying `File` for each parameter per call. Closing as wontfix. Now, there is a *runtime* penalty that is not discussed here. The fact that all the parameters need to be pushed again onto the stack, so you can add on the `\n`. If there was a better way to handle that, it might be useful to explore. Perhaps it's not worth fixing, because inlining might already do it.