Skip to content
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

[SR-2901] Synthesized properties type-checked once per file in the target/module #45495

Closed
swift-ci opened this issue Oct 9, 2016 · 19 comments
Closed
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Oct 9, 2016

Previous ID SR-2901
Radar None
Original Reporter benasher44 (JIRA User)
Type Bug
Status Closed
Resolution Done
Environment

macOS Sierra
Swift 3.0

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee graydon (JIRA)
Priority Medium

md5: f12720121b8f3fdd3662fb338eed86eb

Issue Description:

After some discussion with Mark Lacey, I found that in our project synthesized properties with the following signatures (as logged using the -debug-time-function-bodies debug flag) are type-checked once per file in our project (607 files in the project x 2521 generated setters/getters = ~1.5 million "type-checks"):

get {}
set {}
final get {}
final set {}
@objc get {}
@objc set {}
@objc final get {}
@objc final set {}
(closure)

I got these signatures by getting lines from -debug-time-function-bodies output like this for example:

0.025ms someFile.swift:29:7 @objc get {}

, parsing the log with a script, and compiling the set of all signatures that were logged the same number of times as there are files in the target in question.

This was done using a custom toolchain built off of swift-3.0-branch, but I got similar results using the Swift 3.0 that comes with Xcode 8.0 (App Store version).

I used a custom toolchain here, so that I could increase the number of decimal places logged by -debug-time-function-bodies. By doing that, I could then determine that fixing this bug would save ~40 seconds when building our main target. Otherwise, many of these lines show up as the function taking 0.0ms to type-check, since the time elapsed is less than 0.1ms but adds up over time. I'll put up a PR to add this soon.

Update: Link to PR

@swift-ci
Copy link
Collaborator Author

swift-ci commented Oct 9, 2016

Comment by Ben A (JIRA)

Based on Mark's comments here, there may be some cases in which -debug-time-function-bodies isn't reporting type-checking time. In that case, the 40sec number I reported in the description may be an underestimate. I haven't had time to confirm this yet.

@belkadan
Copy link
Contributor

I think you mean "type-checked" rather than "parsed".

@belkadan
Copy link
Contributor

As part of chasing this down, someone could consider getting accessors to print more nicely in the output of -debug-time-function-bodies. The SourceLoc is the important thing, though.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

What kind of additional information would be useful? The SourceLoc is already logged. I should have mentioned that I omitted it because I didn't think that info would be useful in aggregate (i.e. each line has a different SourceLoc, and knowing that for my project would probably just be noise here). Were you looking for something to the effect of: "these are mostly properties with access level <level>", "are mostly of type <t>", etc.?

Those are all things I can easily collect in my script, since I have the SourceLoc available, while I file another ticket to add extra, needed information for the log.

@belkadan
Copy link
Contributor

Oh, not for us, or for any real analysis, just to make the output a little prettier. "getter for 'foo'" instead of just "get".

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

Ah gotcha. Filed SR-2910

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

Confirmed that this only happens when you pass the -module-name flag to swiftc. I have a lot of time at the end of this week (long flight) to stare at this. If anyone has any tips for where to start looking in terms of how/where swiftc changes when a module name is specified, that'd be helpful!

@belkadan
Copy link
Contributor

That makes absolutely no sense. Every module has a name; it's just that that name is sometimes inferred and sometimes explicit. How did you confirm this?

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

Oh your right. I thought the only difference between the two commands I was running was the -module-name flag, but it now seems like that incorrect. Here's the concrete example:

test_file1.swift:

class B {
    let a: A
    init() {
        a = A(s: "test")
    }
}

test_file2.swift:

struct A {
    let s: String
}

Here are the 2 similar commands and their varying outputs:

1. swift -frontend -debug-time-function-bodies -c test_file2.swift test_file1.swift yields:

1.4ms test_file2.swift:2:9 get {}
0.2ms test_file1.swift:2:9 final get {}
14.1ms test_file1.swift:3:5 init()
0.0ms test_file1.swift:1:7 @objc deinit

2. swiftc -c test_file1.swift test_file2.swift -module-name test -Xfrontend -debug-time-function-bodies yields:

0.4ms test_file1.swift:2:9 final get {}
18.7ms test_file1.swift:3:5 init()
0.0ms test_file1.swift:1:7 @objc deinit
0.1ms test_file2.swift:2:9 get {}
1.5ms test_file2.swift:2:9 get {}

In 2, test_file2.swift:2:9 is type-checked twice, whereas it's only type checked once in 1. I'm still not quite sure why these 2 commands have different output though (note: even though the order of the file list is different for the two commands, re-ordering the list has no effect).

@belkadan
Copy link
Contributor

Order of files sounds much more plausible (and still a problem, of course). Thanks, Ben.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

Sorry to clarify, I meant that file order here has no impact. You can reorder the files in either command and get the same results, in terms of number of times each method is type-checked.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

That still leaves the question: what is different about these two commands that would cause one to type-check properties fewer times?

@swift-ci
Copy link
Collaborator Author

Comment by Graydon Hoare (JIRA)

The first invocation is passing -frontend which means that it's bypassing the driver and running a single frontend job; the second invocation is hitting the driver which is then running two frontend jobs (one for each file) and you're seeing the output of the two runs concatenated.

(To be clear: there looks to be some redundant work in the typechecker, in terms of checking synthesized get/set bodies merely referenced from another file, but that redundant work is not quite as quadratic as it might seem from this example; it's only checking each synthesized body once per frontend run. I am currently investigating ways to limit this.)

@swift-ci
Copy link
Collaborator Author

Comment by Steven Sheldon (JIRA)

I think we were seeing the synthesized bodies checked once per file, on the mailing list Ben mentioned:

[...] I found that we have 2521 properties that are parsed 607 times each. [...] In the main target, there are 607 .swift files

Does Xcode use a frontend job per Swift file?

@belkadan
Copy link
Contributor

Ah, wow, I completely missed that. Yes, a non-whole-module build uses one frontend process per .swift file. (Additionally, calling the frontend directly is unsupported.)

@rudkx has actually already fixed some of this redundant work, and as graydon (JIRA User) said he's looking into more cases of it.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

Ah okay that makes sense. Thanks!

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 2, 2016

Comment by Graydon Hoare (JIRA)

A PR that seems to fix it is here: #5588

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 3, 2016

Comment by Graydon Hoare (JIRA)

Merged 9351843

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 4, 2016

Comment by Ben A (JIRA)

Awesome![]( Excited for the upcoming snapshot)

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

2 participants