digitalmars.D.announce - D Language Foundation October 2024 Quarterly Meeting Summary
- Mike Parker (298/298) Jan 15 The D Language Foundation's quarterly meeting for October 2024
The D Language Foundation's quarterly meeting for October 2024 took place on Friday the 4th at 15:00 UTC. It lasted about 45 minutes. Our quarterly meetings are where representatives from businesses big and small can bring us their most pressing D issues, status reports on their use of D, and so on. The following people attended the meeting: * Walter Bright (DLF) * Ali Çehreli (DLF/MBRDNA) * Dennis Korpel (DLF/SARC) * Martin Kinkelin (DLF/Symmetry) * Mathias Lang (DLF/Symmetry) * Átila Neves (DLF/Symmetry) * Razvan Nitu (DLF) * Mike Parker (DLF) * Carsten Rasmussen (Decard) * Bastiaan Veelo (SARC) Carsten said they were doing a lot at work, but nothing special. They were trying to make the network more distributed and were working on consensus rules. He said it might sound boring, but it was exciting. They were also trying to build a new way to do what we might call "smart contracts", except it wasn't really smart contracts. It was an execution tree with functions. Bastiaan said work was progressing. The day before the meeting he'd resolved a bug that had been bugging them for two years. Things were getting misplaced in the Windows GUI when using D with MDI. It was due to an old Windows SDK. He said that Dennis had been helping them find bottlenecks in compile times. Bastiaan was changing the transpiler because of that. In one program they saw a reduction from 28 minutes down to 14 minutes. Otherwise, they had no complaints about D. Dennis said they were using DMD at SARC. They couldn't use LDC because of a 32-bit stack bug. Debug builds for certain projects were 20 seconds, and then the release builds would be 30 minutes. They'd found that 25 minutes of that was spent optimizing five very large functions. That was because the DMD back-end optimizer had some quadratic algorithms that could take a really long time if you had, e.g., a complex `for` loop. He'd been looking for ways to mitigate that and was wondering if there could be a threshold at which the back end could determine a function was too complex and decide not to optimize. Or maybe an attribute to prevent it. LDC had the ` optStrategy` attribute. He wanted to know in particular if Walter was down for something like that since he knew a lot about the back end. Walter said there were some cases in which the optimizer could get into an infinite loop. They never told you about this in optimization books, but some of the optimizations would undo each other, then redo, then undo, then redo, and so on. The only way he'd found to combat it was to set a limit on passes through the compiler so that it would give up and continue on. He suggested the easiest way to deal with it, since they'd identified the functions, was to break them into smaller functions. He asked Dennis how big they were. Dennis said that some of them were translated from the original Pascal source. Pascal had some features that were translated into meta programming in D. For example, a large struct with a variant record would get translated into a 3,000-line D function because of template expansions, inlining, and such. Walter said that Dennis could look at the optimizer and try to fiddle with the limit on optimization passes. But it was a difficult problem when the compiler was stuck in a loop of doing and undoing something. If a function was small enough, it wouldn't slow things down. A 3,000-line function was probably too much to handle, so breaking it up might be the best option. Ali agreed with that approach. He suggested the compiler should print a message that announced it was giving up and that recommended the user split up the function. Walter said that could be done. Walter said that right now it was counting the number of passes, but we could put a wall clock in there to tell it to give up on optimization after a certain amount of time. Carsten liked the idea of a UDA telling the compiler not to optimize a function. That would be very flexible. Bastiaan noted that the user would need to know where to put it. Carsten agreed. Walter suggested the compiler could print a message when a function took too long to optimize. Walter said another thing to do was to pass `-b` or `--c` to the compiler and look at the output. You might see it flipping between two states. Dennis posted the following minimal reproduction in the chat: ```d void main() { for (int i = 0; i < 1; i++) { int j; static foreach (k; 0 .. 2000) j++; } } ``` He said you could vary the upper range from `2000` to something else and see the quadratic explosion of slowdown. He saw it was going through those 2,000 things 2,000 times. He thought it was because of the way it was structured as a big comma expression. Walter asked him to post an issue and he linked to an existing one (which is [now on GitHub](https://github.com/dlang/dmd/issues/19759), thanks to Robert Schadek). Bastiaan asked what the `--c` switch was. Walter said it printed out what the optimizer was doing. Everyone said they'd never heard of it. Walter said he'd documented some of the internal switches in the past and had received some negative feedback for it, so he'd stopped. Ali said they were still using D at work and were happy with it. They were on an older compiler version, but that didn't matter. He told us that Mike Shah had invited him and Steve Schveighoffer out to Yale to talk to some students there. Razvan said he'd made a PR for an issue Manu Evans had posted regarding warnings for unused imports inside the compiler. It was easy for the simple cases, but there were some hard questions. What should be done with imports inside the body of a template? What about symbols from imports used in template constraints? Things were messy when you put the templates inside static conditionals. He'd made the PR and then couldn't even compile the runtime with it, since the build for it treated warnings as errors. He knew Walter was against adding warnings to the compiler. He wasn't sure if it was worth trying to improve the implementation, but it had been a good experience because it showed that putting this into the compiler was doable. Implementing it instead via DMD-as-a-library was not doable because of the library's current interface. He asked if anyone had any thoughts on this. Walter said that every time he wanted to use `printf`, he found that someone had removed the import for it. Every time he wanted to dump the AST trees, someone had removed the import for it. This was always irritating. He constantly put them back in and they were constantly removed. He was not a fan of the idea of removing unused imports. If someone did care about that, they could do it in their own code, but not in DMD. He kept those imports there for debugging. Razvan said that was fine, but the issue was about having it in the compiler for those who wanted it. Walter said that meant another switch, and the more switches we had, the more problems we had. Bastiaan suggested that imports used only for debugging should be `debug import foo`. Walter said that was a good idea. Dennis said we didn't have a switch to remove unused imports now, but people were removing unused imports anyway. So something that indicated an import was unused, whether it removed them, put out a message, or added a `debug` prefix, would be useful to have. Walter said you might have conditionally compiled code in there that needed particular imports. Mathias thought it would be a good thing to implement and it would be good to make DMD-as-a-library work, but he wouldn't want it in the current development cycle. When you were in development, moving things around would get in your way. And what about versioned imports? For example, one that was only used inside `version(Windows)`. Walter suggested it might be better suited for a style checker. Razvan said that, based on his experience, he saw no way to solve this for all cases. But having the switch would give you the possibility to use it. And if you knew you had imports in static conditionals and versions and such, then you could choose not to use it. Walter pondered it briefly, then said he would be okay with adding a switch. Carsten asked if it could be done by DScanner. Razvan said you'd need semantic analysis to do it. The way that symbol resolution and semantic analysis were currently implemented in DMD made it very hard, probably impossible, to create an interface that allowed you to implement it outside of the compiler. Walter said he'd accept the switch and also accept that it wouldn't be perfect. In addition to the cases Razvan had mentioned, it was also possible to generate an import with a mixin. So we could just have the switch, accept that it served an advisory role, and just not worry about it. Razvan said we could implement it only for normal functions first just to get it in. We could add solutions for more complicated cases down the road if we discovered any. Dennis said an old issue had recently [popped up in the forums](https://forum.dlang.org/post/dlaomdfxdzhxtpbsoixl forum.dlang.org). It was about [instantiating a template through a constructor call](https://github.com/dlang/dmd/issues/18343). He'd put together [a prototype implementation](https://github.com/dlang/dmd/pull/16910) to see if it was feasible to do it without throwing or completely rewriting the template system. It seemed doable. He wondered if this was worth pursuing, or if it were dead on arrival or had been rejected in the past. Walter said his initial thought was, "Why?" Dennis said it was to reduce the number of trampoline functions in Phobos, like `tuple` forwarding to `Tuple`. So we could, e.g., get rid of `auto tuple(T...)(T args) => Tuple!T(args)` and just use `Tuple(1, 2, 3)`. He noted that C++ had this. Átila said it had been very popular in the C++ world. Walter said if C++ had it, maybe it wouldn't be a big deal for us to do it. And he couldn't believe he was saying that. Átila said that a consequence of this was that you could write `vector v = {1, 2, 3}` and it would infer `int`, so you didn't have the template parameters anywhere. Walter said if Dennis could make it work without significant disruption, then he thought it would be okay. He asked if it needed a DIP. Átila said it probably didn't. Walter said he'd at least like to see a description of it that fully described what it was so we could put it in the spec. Dennis said there was [an old DIP for it](https://wiki.dlang.org/DIP40) on the Wiki. I said that in that case Dennis should just take that DIP and shape it up. He could put it directly into the DIP Development forum for feedback. Then after a bit, I'd assign a new number to it and we could move it on through. Dennis said he wasn't sure how comprehensive of a feature it should be. DIP 40 had a whole set of rules to combine struct templates and constructor template arguments into one so you could have template constructors. Átila said it would be up to Dennis, but he advised against it. Dennis said he had a simple implementation now that didn't do extra stuff like partial evaluation or anything advanced. It worked for the `Tuple` case. The DIP described a more expressive variant that allowed for more complicated versions. Was the simple version expressive enough? Walter said he thought it was. If there was no use for those other complicated cases now, we should stick with the simple one. I suggested we could do the simple one first and add more complex cases later if needed. Átila agreed. Razvan brought up an incident that had happened recently. Some PRs had been merged that were aimed at organizing some of DMD's source modules into packages. He said this had broken some of Walter's PRs, and Walter didn't understand why it was being done. It had also caused issues for Razvan's student who was working on DMD-as-a-library. The student had to update to the latest to fix the breakage and would then have to go back and rebase everything if the upstream PRs were to be reverted. Razvan asked if we could decide on something here and say that it wouldn't change for the next 10 years. People had been arguing about packaging for a while. Walter said that packaging didn't really help because everything was importing everything else. He felt packaging was better restricted to cases where module imports weren't going sideways, or deeper into the package heirarchy. For example, he tried to have the root package not call anything in the common package, and nothing in the back-end package calling anything in the front end. That kind of thing forced you to think more about encapsulation than just shoving things willy-nilly into subdirectories. Martin asked if the student had to track master closely or if he could stick with stable. With LDC, he was able to go with stable bumps every two or three months so he didn't have to track master all the time. Razvan said that at the start they'd been making a lot of PRs to DMD because they were modifying the interface. Because of that, they'd needed to track master. They hadn't needed to submit DMD PRs for a while, but still wanted to create a better interface, so still needed to track master. Walter said there was an effort to divide DMD into modules that were not mutually dependent. That had been going on for a while and had made good progress. Packaging things would be better done once that was completed. For example, he had spent a lot of effort on making the parser independent of everything else, so the parser and the lexer could go into separate packages now. He didn't think he'd gotten that far with the rest of the stuff. Dennis said that the packaging PRs hadn't just been shuffling stuff. Some of it was about reduced visibility. Some `public` things had been changed to `package`, so the packages were already somewhat separated. Mathias agreed and noted that in some cases, from what he could see in the PRs, some symbols had been moved to where they were used and their imports removed. That sort of thing was still useful. Walter said before we packagized things, we needed to do the groundwork to make sure we had actual packages and not window dressing. Razvan thought that discussions about visibility weren't really relevant to DMD's code base. He thought `private` was important when there was an interface through which you wanted to prevent access to certain things, but sometimes in DMD it was annoying when things were private. You might really need it in another module, so you'd just make it public. He didn't see that kind of refactoring as a big gain. He thought one thing packaging really helped with was when you had 150 modules in a single directory. For someone just getting started on modifying the compiler, it was hard to know where things were. Otherwise, he didn't really care about it. He didn't see any big advantages either way. All he wanted was for us to decide on one approach and stick with it. Walter asked how many packages the PRs had created. Dennis said there were three: one related to scanning object files, one for the visitors, and one for C++ mangling. Walter suggested we stop there for now. Dennis thought that was where it stopped anyway. Those were the most obvious and natural. Everything else was pretty entwined. Martin said he was only interested in a single package: a glue layer package to clearly delineate which part of the front end was shared by all the compilers and which was DMD-specific so he could get rid of it. Walter said that was a fair point. Dennis and Razvan agreed. To close this out, Razvan wanted to verify that we weren't reverting the packaging PRs. Walter confirmed. Our October Monthly meeting took place the following Friday, October 11th. Our next quarterly was on Friday, January 3rd, 2025. If you are running or working for a business using D, large or small, and would like to join our quarterly meetings periodically or regularly to share your problems or experiences, please let me know.
Jan 15