Skip to content

#1759 cases 30% slowdown when generating diagnostics #1847

Closed
@ahoppen

Description

@ahoppen

When changing swift-parser-cli performance-test to also fold operators and generate diagnostics (like the SourceKit stress tester does), then #1759 causes a 30% slowdown.

Steps to Reproduce

  1. Apply the following diff to SwiftSyntax
diff --git a/Sources/swift-parser-cli/Commands/PerformanceTest.swift b/Sources/swift-parser-cli/Commands/PerformanceTest.swift
index 5b3c0afa..844fdaaa 100644
--- a/Sources/swift-parser-cli/Commands/PerformanceTest.swift
+++ b/Sources/swift-parser-cli/Commands/PerformanceTest.swift
@@ -14,6 +14,9 @@ import _InstructionCounter
 import ArgumentParser
 import Foundation
 import SwiftParser
+import SwiftOperators
+import SwiftSyntax
+import SwiftParserDiagnostics
 
 struct PerformanceTest: ParsableCommand {
   static var configuration = CommandConfiguration(
@@ -42,7 +45,11 @@ struct PerformanceTest: ParsableCommand {
     for _ in 0..<self.iterations {
       for file in files {
         file.withUnsafeBytes { buf in
-          _ = Parser.parse(source: buf.bindMemory(to: UInt8.self))
+          var tree = Parser.parse(source: buf.bindMemory(to: UInt8.self))
+          if let foldedTree = OperatorTable.standardOperators.foldAll(tree, errorHandler: { _ in }).as(SourceFileSyntax.self) {
+            tree = foldedTree
+          }
+          _ = ParseDiagnosticsGenerator.diagnostics(for: tree)
         }
       }
     }
  1. Save the following file to /tmp/i/input.swift
//  Copyright (c) 2015 Rob Rix. All rights reserved.

#if swift(>=4.2)
#if compiler(>=5)

// Use Swift.Result
extension Result {
	// ResultProtocol
	public

extension Result {
	/// The compatibility alias for the Swift 5's `Result` in the standard library.
	///
	/// See https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md
	/// and https://forums.swift.org/t/accepted-with-modifications-se-0235-add-result-to-the-standard-library/18603
	/// for the details.
	public typealias Success = Value
	/// The compatibility alias for the Swift 5's `Result` in the standard library.
	///
	/// See https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md
	/// and https://forums.swift.org/t/accepted-with-modifications-se-0235-add-result-to-the-standard-library/18603
	/// for the details.
	public typealias Failure = Error
}

extension Result {
	// MARK: Constructors

	/// Constructs a result from an `Optional`, failing with `Error` if `nil`.
	public init(_ value: Value?, failWith: @

extension Result: CustomStringConvertible {
	public var description: String {
		switch self {
		case 

extension Result: CustomDebugStringConvertible {
	public var debugDescription: String {
		return description
	}
}

extension Result: ResultProtocol {
	/// Constructs a success wrapping a `value`.
	public init(value: Value) {
		self = 

extension Result where Result.Failure == AnyError {
	/// Constructs a result from an expression that uses `throw`, failing with `AnyError` if throws.
	public init(_ f: 

// MARK: - Equatable

#if swift(>=4.2)
#if !compiler(>=5)
	extension Result

#if swift(>=4.2)
	// Conformance to `Equatable` will be automatically synthesized.
#else
	extension Result where Result.Success: Equatable

// MARK: - Derive result from failable closure

@available(*, deprecated, renamed: "Result.init(attempt:)")
public func 

@available(*, deprecated, renamed: "Result.init(_:)")
public func 

// MARK: - ErrorConvertible conformance
	
extension NSError: ErrorConvertible {
	public static func error(from error: Swift.

// MARK: - migration support

@available(*, unavailable, message: "Use the overload which returns `Result<T, AnyError>` instead")
public func 

@available(*, unavailable, message: "Use the overload which returns `Result<T, AnyError>` instead")
public func 

#if os(macOS) || os(iOS) || os(tvOS) 

// MARK: -

import Foundation
  1. Run swift-parser-cli performance-test --directory /tmp/i --iterations 1000

On my local machine I’m seeing an instruction count of ~27.000.000 before #1759 and ~36.000.000 after that PR. That’s a >30% slowdown.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions