Skip to content

[Incremental] Harness immutability to make inputDependencySourceMap robust #675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 9, 2021

Conversation

davidungar
Copy link
Contributor

@davidungar davidungar commented May 24, 2021

Make the inputDependencyMap immutable, solely reflecting the OutputFileMap.
Do not include it in the priors.

In a previous PR, @CodaFi uncovered and explained issues with the `inputDependencySourceMap:

   // FIXME: The map between swiftdeps and swift files is absolutely *not*`
   // a bijection. In particular, more than one swiftdeps file can be encountered
   // in the course of deserializing priors *and* reading the output file map
   // *and* re-reading swiftdeps files after frontends complete
   // that correspond to the same swift file. These cause two problems:
   // - overwrites in this data structure that lose data and
   // - cache misses in `getInput(for:)` that cause the incremental build to
   // turn over when e.g. entries in the output file map change. This should be
   // replaced by a multi-map from swift files to dependency sources,
   // and a regular map from dependency sources to swift files -
   // since that direction really is one-to-one.

This PR solves the problem in a simpler way. The key insight is that the output file map contains the information linking a source file to the swiftdeps file for any build. Thus, the output file map should just determine the entries in the inputDependencySourceMap, just as it did before the introduction of incremental imports. Then the map in question does become a true bijection. It can also be made immutable, which greatly eases reasoning about the code.

It will also make it easy to cull removed file nodes from priors in a future PR.

@davidungar
Copy link
Contributor Author

@swift-ci please test

@davidungar davidungar force-pushed the after-replace-bijection branch from 3cae5b2 to 2d81f55 Compare May 25, 2021 17:59
@@ -121,7 +121,8 @@ extension ModuleDependencyGraph.Tracer {
path.compactMap { node in
node.dependencySource.map {
source in
graph.inputDependencySourceMap[source].map { input in
graph.inputDependencySourceMap.input(ifKnownFor: source).map {
input in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this request still relevant now that the map has been turned into its own, domain-specific type?



extension OutputFileMap {
fileprivate static func mock(maxIndex: Int) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Whitespace here is quite weird

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the white space there still weird? I hope I've fixed it.

@CodaFi CodaFi mentioned this pull request May 27, 2021
@davidungar davidungar force-pushed the after-replace-bijection branch 4 times, most recently from 11c4f8c to 9b3e681 Compare June 5, 2021 02:19
@davidungar
Copy link
Contributor Author

@swift-ci please test

@davidungar davidungar force-pushed the after-replace-bijection branch from 7d88e76 to b6cc8ec Compare June 7, 2021 16:38
@davidungar davidungar changed the title [DNM] Testing a new approach to inputDependencyMap [Incremental] Harness immutability to make inputDependencyMap immutable Jun 7, 2021
@davidungar davidungar changed the title [Incremental] Harness immutability to make inputDependencyMap immutable [Incremental] Harness immutability to make inputDependencySourceMap immutable Jun 7, 2021
@davidungar
Copy link
Contributor Author

@CodaFi Would you mind taking a look at this? Because you uncovered and explored the issues before with this map, you'll be a great reviewer to assess the correctness of this change. Thanks!

@davidungar
Copy link
Contributor Author

@swift-ci please test

@davidungar davidungar requested a review from artemcm June 8, 2021 15:27
@davidungar
Copy link
Contributor Author

@CodaFi Any word on when you might have time for this? Thanks!

@davidungar davidungar changed the title [Incremental] Harness immutability to make inputDependencySourceMap immutable [Incremental] Harness immutability to make inputDependencySourceMap robust Jun 8, 2021
Copy link
Contributor

@artemcm artemcm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the surface, this change seems like and improvement to me, and the problems Robert outlined shouldn't be possible with this data-structure being immutable. It seems reasonable to have the outputFileMap be the canonical source of dependencies for each input and it simplifies the logic quite a bit.

I'd still really like @CodaFi to weigh in because I'm less familiar with the scenarios that previously led to conflict and whether we were relying on serialized priors containing dependency sources in a way I'm not familiar with. And whether that could have implications on incremental build performance.

return nil
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: trailing whitespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! I'll fix it.

@@ -671,27 +634,6 @@ extension ModuleDependencyGraph {
throw ReadError.malformedDependsOnRecord
}
self.nodeUses.append( (key, Int(record.fields[0])) )
case .mapNode:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tells me that we are no longer reading in swiftdeps files from serialized priors. I'm lacking context here to understand the implications of this, where were these deserialized files used?

They are one of the examples that made the SourceMap not-truly-bijective, is it the case that they never led to correct behavior? Or if they resulted in another behavior, where were we relying on it that we now choose not to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand the confusion here.

The intention of this change is to no longer serialize and deserialize the inputDependencySourceMap. Serialized mapNodes were only used for that purpose. We still read in ModuleDependencyGraphs from the priors.

Yes, serializing the map and then deserialized it created confusion because the deserialized version might be inconsistent with the info from the OutputFileMap. This PR is premised on the believe that it is the OutputFileMap that should be the source of truth.

Does this explanation satisfy? Have I missed something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that makes sense, thank you. And it also makes sense for the output-file-map to be the canonical source of truth. Probably so much so that I am wondering why we serialized the inputDependencySourceMap in the first place, hence the confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for validating the notion of output-file-map as canonical. Wrt to serializing the inputDependencySourceMap I have to plead mea culpa. It seemed like a good idea at the time because the inputDependencySourceMap was being dynamically build as swiftdeps files were processed. When @CodaFi added the prior deserialization code, IIRC, there was a moment when we had deserialized priors with an empty map. So I (wrongly) fixed it by serializing the inputDependencySourceMap. My mistake, in conjuction with the build system's proclivity to change file names when a C++ file and Swift file had the same basename-without-extension, led to hilarity ensuing. @CodaFi got to the bottom of things there, and identified the problems with that design.

Later, I realized that the output-file-map should just be the truth, and that, consequently, the inputDependencySourceMap could be both immutable and a bijection. I hope I'm right this time!

@davidungar
Copy link
Contributor Author

On the surface, this change seems like and improvement to me, and the problems Robert outlined shouldn't be possible with this data-structure being immutable. It seems reasonable to have the outputFileMap be the canonical source of dependencies for each input and it simplifies the logic quite a bit.

I'd still really like @CodaFi to weigh in because I'm less familiar with the scenarios that previously led to conflict and whether we were relying on serialized priors containing dependency sources in a way I'm not familiar with. And whether that could have implications on incremental build performance.

Thank you for your review. Yes, it would still be ideal for @CodaFi to weigh in. As I haven't received any indication of how long it will be till he can review this PR, I plan to fix the white-space issue and merge.

@davidungar
Copy link
Contributor Author

@swift-ci please test

@davidungar davidungar merged commit f32e8e1 into swiftlang:main Jun 9, 2021
davidungar pushed a commit to davidungar/swift-driver that referenced this pull request Jun 11, 2021
[Incremental] Harness immutability to make `inputDependencySourceMap` robust
# Conflicts:
#	Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraph.swift
@davidungar
Copy link
Contributor Author

rdar://77998890

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants