> On Nov 12, 2017, at 8:30 AM, Brian Gesiak via swift-dev <swift-dev@swift.org> 
> wrote:
> 
> Hello all!
> 
> I'm looking for a body of work to do on the Swift compiler for an upcoming 
> programmer retreat I'm attending in January [1]. I've read a lot of blog 
> posts with tips for diagnosing slow Swift compile times [2], and I was 
> wondering if I could contribute to tooling in this area.

Hey, this is great! Sorry I didn't get back to you earlier. Happy to talk this 
over.

> (Just to make it clear: I'm talking about improving and expanding the set of 
> tools developers have to figure out why their projects take a long time to 
> compile. I'm *not* talking about working on speeding Swift compile times -- 
> although the tools may indirectly help with that.)

This seems plausible to me; though like others, I'm a bit hesitant too. There 
are often _many_ things going on in a given compilation, and one needs to be 
careful surfacing any particular signal as a putative "singular cause" of a 
slow compilation, since the user may see that signal and respond by making 
significant adjustments to their code, only to find the overall time isn't 
helped much. But I totally get the motive.

> Using these options, developers can find function bodies and expressions that 
> took longer to compile than others.

Sadly, there's not always a 1:1 mapping between source entities and time like 
that. Certainly _some_ cases can be so egregious (say, typechecking time on an 
expression that's triggering an exponential-time inference) that they dominate 
compile time, and can be identified-and-fixed in isolation; but often the total 
amount of work attributable to a given source entity is spread around the 
compilation, occurs in multiple phases, emerges out of interaction between 
entities, overlaps with others, etc.

That's not to say that one couldn't build machinery to do a better job 
attributing costs to source entities than what we have now; just that it'll be 
a bit of work to get there from here. Maybe fun work! I'd be happy to discuss 
more :)

> However, it should be noted that, of these options, only the first is a 
> user-facing "supported" option. The others are `swift -frontend` options, and 
> as such the Swift team has been clear that this means the options may be 
> changed or removed at any point in the future [3].

Yeah, there are a few good reasons for being careful which options get 
surfaced; but I generally agree with you that _some_ at least partly-supported 
ones would be nice. IMO it's easiest and most flexible to aim to _export_ 
information out of the compiler in a machine-readable form, so you can 
post-process with other tools. I've mostly been using json and csv in recent 
efforts (eg. see -stats-output-dir or -trace-stats-events). But I don't have an 
especially strong feeling about the degree-of-support / stability of such 
features; I'm going to have to leave that part of your question to others.

> What's more, several contributors have noted the behavior of the options 
> themselves could also be improved. Here's what I gathered from reading 
> several JIRA bugs, commit messages, and mailing list discussions:
> 
> - SR-2910 <https://bugs.swift.org/browse/SR-2910> points out that 
> `-debug-time-function-bodies` prints just `get {}` and `set {}` for struct 
> getters and setters, and that this could be improved by printing the variable 
> name as well.
> - The commit that added `-warn-long-function-message=` notes in its commit 
> message 
> <https://github.com/apple/swift/commit/18c75928639acf0ccf0e1fb6729eea75bc09cbd5>
>  that the option only measures some aspects of type-checking, that it doesn't 
> provide any information on how checking a function for the first time will 
> take longer, doesn't report on other phases of compilation, and doesn't catch 
> anything being type-checked multiple times.

Yes, this latter comment is the part I'm most concerned about. I think if 
you're going to go this way -- providing a diagnostic mode that assigns costs 
to source-entities rather than compiler subsystems -- the difficult/interesting 
parts will be (a) making sure you capture enough of the costs of compilation to 
approximate "total time" meaningfully and (b) making sure you attribute 
"causes" meaningfully. The latter is really quite tricky since a lot of the 
compiler's work is lazy / demand-driven: the first time some (lazy and 
memoized) work is demanded, it's tempting to attribute the cost of the work to 
the entity first requesting it. But if a dozen other entities also demand that 
work gets done (reusing it, whichever requests it first) then the attribution 
will be ... unhelpful to the user trying to change their code to avoid the cost.

> I'd like to solicit ideas for future work here:
> 
> - At the very least, I could fix SR-2910 
> <https://bugs.swift.org/browse/SR-2910>.
> - I'd also like to address some of the issues mentioned in this commit 
> message 
> <https://github.com/apple/swift/commit/18c75928639acf0ccf0e1fb6729eea75bc09cbd5>,
>  but I would like to confirm they're still something the Swift team would 
> like work to be done on. Jordan, are these still relevant?
> - I'm wondering if anyone else has some work in-flight here, or if they have 
> ideas. If you've been longing for a "killer feature", please reply here and 
> let me know!

I'll let the others who feel strongly about the "official support" aspect speak 
to that; myself I'd suggest looking at one or another of two approaches:

  1. See if you can leverage the existing counters and stats-gathering / 
reporting machinery in the compiler; for example the -trace-stats-events 
infrastructure lets you bundle together work done on behalf of a given source 
range and any changes to compiler counters during that work, as a single 
virtual "stats-event" in processing, and trace those events to a .csv file. 
Maybe something related to that would be helpful for the task you're interested 
in?

  2. Consider going up a level from declarations or functions to _files_, and 
see if there's a useful way to visualize hot-spots in the inter-file dependency 
graph that the driver interprets, during incremental compilation. The units of 
work at this level are likely to be large (especially if they involve cascading 
dependencies, that invalidate "downstream" files) and often cutting or changing 
an edge in that graph can be a simpler matter of moving a declaration, or 
changing its visibility: reasonably easy changes that don't cost the user much 
to experiment with.

Hope that helps! Happy to discuss any of this further.

-Graydon

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to