-
Notifications
You must be signed in to change notification settings - Fork 822
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
Optimize bottlenecks #803
Optimize bottlenecks #803
Conversation
@@ -4,18 +4,36 @@ import PathKit | |||
import Yams | |||
|
|||
extension Dictionary where Key: JSONKey { | |||
|
|||
public func json<T: NamedJSONDictionaryConvertible>(atKeyPath keyPath: JSONUtilities.KeyPath, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) throws -> [T] { | |||
public func json<T: NamedJSONDictionaryConvertible>(atKeyPath keyPath: JSONUtilities.KeyPath, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove, parallel: Bool = false) throws -> [T] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parallelizing the json parsing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi if we used zippyjson for the json parsing, even single-threaded it would be a lot (maybe 10x?) faster. but parallelizing is a simple win for this commit
@@ -10,11 +10,14 @@ import ProjectSpec | |||
import PathKit | |||
|
|||
public class CarthageDependencyResolver { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parallelizing dependency resolution
Sources/ProjectSpec/Decoding.swift
Outdated
let jsonDictionary: JSONDictionary = try! dictionary.json(atKeyPath: .key(key)) | ||
let item = try! T(name: key, jsonDictionary: jsonDictionary) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to use exclamation mark on try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. any other concerns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope. but bear in mind i am not a real reviewer 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to another paring function, it would be better to set try
, not try!
public func json<T: NamedJSONConvertible>(atKeyPath keyPath: JSONUtilities.KeyPath, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) throws -> [T] { |
This is also because paring error should be handled on here
XcodeGen/Sources/ProjectSpec/Project.swift
Line 166 in a0e144b
public init(basePath: Path = "", jsonDictionary: JSONDictionary) throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking at this further, i think it would be simpler to use try!
instead of try
. the issue is that these blocks are being run asynchronously, so they don't just bubble up to this function's caller. there are other strategies, like storing a result type in the list and then if any of the results are failures, throw the first failure as the error out of this function. we can do that if people want though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eh, i'll just do it with try
actually
Is this project still maintained? |
Thanks for your work here @michaeleisel. Would you be able to post some timings before and after this PR (after a rebase) for a large project, and also for the performance tests. Thanks! |
class CarthageVersionLoader { | ||
|
||
private let buildPath: Path | ||
private var cachedFiles: [String: CarthageVersionFile] = [:] | ||
private var cachedFilesMutex: Mutex<[String: CarthageVersionFile]> = Mutex([:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note that we'll need to be careful in the future not to add any non-thread-safe state to CarthageVersionLoader. for now it's just cachedFiles
that needs this, but something to keep in mind
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a comment to CarthageVersionLoader
to warn future us.
For carthage dependencies, on my 8 (physical) core machine it reduces the time from 600ms to 200ms for a large project. For the JSON parsing, it goes from 1,500 ms to 300ms. for performance testing, i can take a look. but first, are we good with these at a high level? (i.e., excluding stuff like try vs. try!, which can easily be fixed) |
I can't speak for @yonaskolb, but I'm interested in this. From a cursory glance I'm good with it at a high level. |
ok i'm happy with it now personally as well. here are the perf test results: https://gist.github.com/michaeleisel/3d1a5316d233571ca5e2ec9531351c82 |
are we good to merge? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems our project doesn't benefit much from this (not to say it's not a good change).
The spike at the start is this change. The spikes at the end are from tuist/XcodeProj#529.
Can you add a CHANGELOG entry? I think this is good to be merged.
class CarthageVersionLoader { | ||
|
||
private let buildPath: Path | ||
private var cachedFiles: [String: CarthageVersionFile] = [:] | ||
private var cachedFilesMutex: Mutex<[String: CarthageVersionFile]> = Mutex([:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a comment to CarthageVersionLoader
to warn future us.
More details on our performance bottleneck: Seems it's all in project generation and writing. In particular these two functions are hot spots: XcodeGen/Sources/XcodeGenKit/SourceGenerator.swift Lines 80 to 82 in 01c6959
(or just https://github.com/yonaskolb/XcodeGen/blob/master/Sources/XcodeGenKit/PBXProjGenerator.swift#L222) and |
Yeah, I've only ensured it improves my own use case. I spent some time with that |
@brentleyjones ptal |
These are some bottlenecks that were causing significant performance overhead for me. The changes are rough, but if they look good overall I can clean them up