Skip to content

Commit 28563cb

Browse files
authored
Merge pull request #103 from cltnschlosser/cs_largeResponseFileRuntime
Driver performance improvements (profile test/Driver/response-file.swift)
2 parents 9f9f9fe + 63bfc1c commit 28563cb

File tree

4 files changed

+42
-33
lines changed

4 files changed

+42
-33
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ on the command line:
8585
```
8686
$ SWIFT_DRIVER_ENABLE_INTEGRATION_TESTS=1 \
8787
SWIFT_DRIVER_LIT_DIR=/path/to/build/Ninja-ReleaseAssert/swift-.../test-... \
88-
swift test --parallel
88+
swift test -c release --parallel
8989
```
9090

9191
#### Preparing a Linux docker for debug

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ public struct Driver {
241241
throw Error.subcommandPassedToDriver
242242
}
243243

244-
var args = try Self.expandResponseFiles(args, fileSystem: fileSystem, diagnosticsEngine: self.diagnosticEngine)[...]
244+
var args = try Self.expandResponseFiles(args, fileSystem: fileSystem, diagnosticsEngine: self.diagnosticEngine)
245245

246246
self.driverKind = try Self.determineDriverKind(args: &args)
247247
self.optionTable = OptionTable()
@@ -508,18 +508,21 @@ extension Driver {
508508
continue
509509
} else if char.isWhitespace && !quoted {
510510
// This is unquoted, unescaped whitespace, start a new token.
511-
tokens.append(token)
512-
token = ""
511+
if !token.isEmpty {
512+
tokens.append(token)
513+
token = ""
514+
}
513515
continue
514516
}
515517

516518
token.append(char)
517519
}
518520
// Add the final token
519-
tokens.append(token)
521+
if !token.isEmpty {
522+
tokens.append(token)
523+
}
520524

521-
// Filter any empty tokens that might be parsed if there's excessive whitespace.
522-
return tokens.filter { !$0.isEmpty }
525+
return tokens
523526
}
524527

525528
/// Tokenize each line of the response file, omitting empty lines.
@@ -581,7 +584,7 @@ extension Driver {
581584
/// Determine the driver kind based on the command-line arguments, consuming the arguments
582585
/// conveying this information.
583586
public static func determineDriverKind(
584-
args: inout ArraySlice<String>
587+
args: inout [String]
585588
) throws -> DriverKind {
586589
// Get the basename of the driver executable.
587590
let execRelPath = args.removeFirst()

Sources/SwiftDriver/Execution/JobExecutor.swift

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,11 @@ public final class JobExecutor {
118118
/// The context required during job execution.
119119
struct Context {
120120

121-
/// This contains mapping from an output to the job that produces that output.
122-
let producerMap: [VirtualPath: Job]
121+
/// This contains mapping from an output to the index(in the jobs array) of the job that produces that output.
122+
let producerMap: [VirtualPath: Int]
123+
124+
/// All the jobs being executed.
125+
let jobs: [Job]
123126

124127
/// The resolver for argument template.
125128
let argsResolver: ArgsResolver
@@ -155,7 +158,8 @@ public final class JobExecutor {
155158
argsResolver: ArgsResolver,
156159
env: [String: String],
157160
fileSystem: FileSystem,
158-
producerMap: [VirtualPath: Job],
161+
producerMap: [VirtualPath: Int],
162+
jobs: [Job],
159163
executorDelegate: JobExecutorDelegate,
160164
jobQueue: OperationQueue,
161165
processSet: ProcessSet?,
@@ -164,6 +168,7 @@ public final class JobExecutor {
164168
diagnosticsEngine: DiagnosticsEngine
165169
) {
166170
self.producerMap = producerMap
171+
self.jobs = jobs
167172
self.argsResolver = argsResolver
168173
self.env = env
169174
self.fileSystem = fileSystem
@@ -227,7 +232,7 @@ public final class JobExecutor {
227232
let delegate = JobExecutorBuildDelegate(context)
228233
let engine = LLBuildEngine(delegate: delegate)
229234

230-
let result = try engine.build(key: ExecuteAllJobsRule.RuleKey(jobs: jobs))
235+
let result = try engine.build(key: ExecuteAllJobsRule.RuleKey())
231236

232237
// Throw the stub error the build didn't finish successfully.
233238
if !result.success {
@@ -237,11 +242,11 @@ public final class JobExecutor {
237242

238243
/// Create the context required during the execution.
239244
func createContext(_ jobs: [Job], env: [String: String], fileSystem: FileSystem) -> Context {
240-
var producerMap: [VirtualPath: Job] = [:]
241-
for job in jobs {
245+
var producerMap: [VirtualPath: Int] = [:]
246+
for (index, job) in jobs.enumerated() {
242247
for output in job.outputs {
243248
assert(!producerMap.keys.contains(output.file), "multiple producers for output \(output): \(job) \(producerMap[output.file]!)")
244-
producerMap[output.file] = job
249+
producerMap[output.file] = index
245250
}
246251
}
247252

@@ -254,6 +259,7 @@ public final class JobExecutor {
254259
env: env,
255260
fileSystem: fileSystem,
256261
producerMap: producerMap,
262+
jobs: jobs,
257263
executorDelegate: executorDelegate,
258264
jobQueue: jobQueue,
259265
processSet: processSet,
@@ -275,7 +281,7 @@ struct JobExecutorBuildDelegate: LLBuildEngineDelegate {
275281
func lookupRule(rule: String, key: Key) -> Rule {
276282
switch rule {
277283
case ExecuteAllJobsRule.ruleName:
278-
return ExecuteAllJobsRule(key, fileSystem: context.fileSystem)
284+
return ExecuteAllJobsRule(key, jobs: context.jobs, fileSystem: context.fileSystem)
279285
case ExecuteJobRule.ruleName:
280286
return ExecuteJobRule(key, context: context)
281287
default:
@@ -305,26 +311,26 @@ class ExecuteAllJobsRule: LLBuildRule {
305311
struct RuleKey: LLBuildKey {
306312
typealias BuildValue = DriverBuildValue
307313
typealias BuildRule = ExecuteAllJobsRule
308-
309-
let jobs: [Job]
310314
}
311315

312316
override class var ruleName: String { "\(ExecuteAllJobsRule.self)" }
313317

314318
private let key: RuleKey
319+
private let jobs: [Job]
315320

316321
/// True if any of the inputs had any error.
317322
private var allInputsSucceeded: Bool = true
318323

319-
init(_ key: Key, fileSystem: FileSystem) {
324+
init(_ key: Key, jobs: [Job], fileSystem: FileSystem) {
320325
self.key = RuleKey(key)
326+
self.jobs = jobs
321327
super.init(fileSystem: fileSystem)
322328
}
323329

324330
override func start(_ engine: LLTaskBuildEngine) {
325-
for (idx, job) in key.jobs.enumerated() {
326-
let key = ExecuteJobRule.RuleKey(job: job)
327-
engine.taskNeedsInput(key, inputID: idx)
331+
for index in jobs.indices {
332+
let key = ExecuteJobRule.RuleKey(index: index)
333+
engine.taskNeedsInput(key, inputID: index)
328334
}
329335
}
330336

@@ -351,7 +357,7 @@ class ExecuteJobRule: LLBuildRule {
351357
typealias BuildValue = DriverBuildValue
352358
typealias BuildRule = ExecuteJobRule
353359

354-
let job: Job
360+
let index: Int
355361
}
356362

357363
override class var ruleName: String { "\(ExecuteJobRule.self)" }
@@ -369,9 +375,9 @@ class ExecuteJobRule: LLBuildRule {
369375
}
370376

371377
override func start(_ engine: LLTaskBuildEngine) {
372-
for (idx, input) in key.job.inputs.enumerated() {
373-
if let producingJob = context.producerMap[input.file] {
374-
let key = ExecuteJobRule.RuleKey(job: producingJob)
378+
for (idx, input) in context.jobs[key.index].inputs.enumerated() {
379+
if let producingJobIndex = context.producerMap[input.file] {
380+
let key = ExecuteJobRule.RuleKey(index: producingJobIndex)
375381
engine.taskNeedsInput(key, inputID: idx)
376382
}
377383
}
@@ -404,7 +410,7 @@ class ExecuteJobRule: LLBuildRule {
404410
private func executeJob(_ engine: LLTaskBuildEngine) {
405411
let context = self.context
406412
let resolver = context.argsResolver
407-
let job = key.job
413+
let job = context.jobs[key.index]
408414
let env = context.env.merging(job.extraEnvironment, uniquingKeysWith: { $1 })
409415

410416
let value: DriverBuildValue

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ final class SwiftDriverTests: XCTestCase {
5858
func assertArgs(
5959
_ args: String...,
6060
parseTo driverKind: DriverKind,
61-
leaving remainingArgs: ArraySlice<String>,
61+
leaving remainingArgs: [String],
6262
file: StaticString = #file, line: UInt = #line
6363
) throws {
64-
var slice = args[...]
65-
let result = try Driver.determineDriverKind(args: &slice)
64+
var args = args
65+
let result = try Driver.determineDriverKind(args: &args)
6666

6767
XCTAssertEqual(result, driverKind, file: file, line: line)
68-
XCTAssertEqual(slice, remainingArgs, file: file, line: line)
68+
XCTAssertEqual(args, remainingArgs, file: file, line: line)
6969
}
7070
func assertArgsThrow(
7171
_ args: String...,
7272
file: StaticString = #file, line: UInt = #line
7373
) throws {
74-
var slice = args[...]
75-
XCTAssertThrowsError(try Driver.determineDriverKind(args: &slice))
74+
var args = args
75+
XCTAssertThrowsError(try Driver.determineDriverKind(args: &args))
7676
}
7777

7878
try assertArgs("swift", parseTo: .interactive, leaving: [])

0 commit comments

Comments
 (0)