When the request is asked which tokens are have in an intersection, the previous solution was searching for first Index (linearly) and then filtered everything that was coming after that index using `intersect function`
The updated solution will search for the first token index using`binary search`
# Speedup
While this is only one function was updated, the next options were considered:
- [**lin+filter**] old solution
- [**lin+prefix**] old solution with `prefix:wihle` instead of filtering
- [**bin+filter**] binary search with filter
- [**bin+prefix**] binary search with `prefix:wihle` instead of filtering
The speedup highly depends on the file sizes. The bigger/longer files the bigger win is
# Benchmark
## Kickstarter
|lin+filter|lin+prefix|bin+filter|bin+prefix|speedup|
|-|-|-|-|-|
|0.494|0.243|0.390|\***0.117\***| ~4x |
## Swift
|lin+filter|lin+prefix|bin+filter|bin+prefix|speedup|
|-|-|-|-|-|
|1.739|0.740|1.273|\***0.103**\*| ~16x |
## WordPress
|lin+filter|lin+prefix|bin+filter|bin+prefix|speedup|
|-|-|-|-|-|
|1.270|0.526|0.918|0.148| ~8x |
# Testing code
This code was tested with these parts of code (in Release build)
```
fileprivate var counter = 0
fileprivate var times: [String: Double] = [:]
fileprivate let timesQueue = DispatchQueue.init(label: "benchmarks")
fileprivate func timeLog<T>(_ name: String, block: () -> T) -> T {
let start = DispatchTime.now()
let result = block()
let end = DispatchTime.now()
timesQueue.async {
let oldValue = times[name, default:0.0]
let diff = TimeInterval(end.uptimeNanoseconds - start.uptimeNanoseconds) / 1_000_000_000
let newValue = oldValue + diff
times[name] = newValue
counter += 1
if counter % 1000 * times.count == 0 {
print("!!!!: \(times)")
}
}
return result
}
internal func tokens(inByteRange byteRange: NSRange) -> [SyntaxToken] {
let new = timeLog("new") { tokensFast(inByteRange: byteRange) }
let new2 = timeLog("old") { tokensOld(inByteRange: byteRange) }
return arc4random() % 2 == 1 ? new : new2
}
```
* Require Swift 5.0 to build
* Update CI
* Stop testing with Swift 4.x & Xcode 10.0/10.1
* Use official Swift docker image instead of norionomura's
* Use Xcode 10.3 as latest stable version
* Update READMEs
* Fixup xcodeproj
* Fixup CI Swift container image tag
* Fixup changelog
This PR adds a new `unused_declaration` analyzer rule to lint for unused declarations.
By default, detects unused `fileprivate`, `private` and `internal` declarations.
Configure the rule with `include_public_and_open: true` to also detect unused `public` and `open` declarations.
Completely remove the `unused_private_declaration` rule.
This is built on the work enabling collecting rule infrastructure in https://github.com/realm/SwiftLint/pull/2714.
* Split cache into one file per configuration
* Only write cache files with changes
* Avoid converting from Data -> String -> Data when saving cache files
* Move empty check to for where
* Split cache changelog entry
* Reword changelog entry to better reflect impact
* #2441 - Pass custom rules identifiers to the enableRules function to consider custom rules of a parent of a nested configuration
* #2441 - Add custom rules merge
* #2441 - Fix line length violation
* #2441 - Add nested configutaion mocks with custom rules
* #2441 - Add nested configurations tests for custom rules
* #2441 - Disable function body length check
* #2441 - Update changelog
* Move changelog to appropriate position
* Split up and refactor Configuration.init to avoid being too long
* Add tests to LinuxMain.swift
* Remove redundant protocol conformances
Hashable implies Equatable
* Fix typo in changelog entry and add another fixed issue URL
* #2353 - Move violating modifiers search to a private function
* #2353 - Add offset and length to the ModifierDescription
* #2353 - Make modifier_oder rule correctable
* #2353 - Add modifier_oder rule correction tests
* #2353 - Upadte the changelog
* #2353 - Add missing Foundation import
* #2353 - Fix linux tests
* Small edits to ModifierOrderRule and changelog entry
* Add VerticalWhitespaceOpening/ClosingBraces rules with description
* Implement validate, correct & add rules to lists
* Fix minor issues & update docs
* Fix copy & paste issue
* Improve autocorrection + Cleanup triggering examples
* Update changelog with new rule entries
* Add more validation examples
* [CHANGELOG.md] Mark new rules as opt-in
* Point to exact location of violation + update tests
* Make rules severity configurable
* Fix issues after rebasing
* Fix issue with CHANGELOG.md
* Add more violating examples, improve pattern to catch more cases
* Move changelog entries to new version
* Fix issues after rebase
* Move Changelog entry to current master
* Fix failing tests
* Fixes after refactoring
* Fix changelog entry position
* Make range unicode-safe (as suggested by @jpsim)
* Share duplicate Dictionary extension code
This can be used for avoid "Test::Unit::AssertionFailedError" error in `libxpc.dylib` on calling `sourcekitd_send_request_sync` in sandbox environment.
This bumps the minimum version required to build SwiftLint to 4.2. The primary motivating factor to drop support for Swift 4.0-4.1.x is that SwiftLint now uses CryptoSwift, which requires 4.2.
* Add changelog entry
* Remove --allow-warnings flag from CocoaPods commands
* Update CryptoSwift to 0.13.0
* Migrate to Swift 4.2
* Remove CircleCI tests for Swift < 4.2
* Update English and Chinese README
Korean README doesn't yet have a version table like this.
* Update gems
* Add changelog entry for fixed compiler warnings
* Update CocoaPods to 1.6.0.beta.2
To work around https://github.com/CocoaPods/CocoaPods/issues/7708
Performance has gotten pretty bad for complex SwiftLint configurations like the one used for Lyft's iOS code base involving lots of files in the directories being linted, large configuration files and many nested configuration files.
Two main areas were particularly ripe for improvement were:
1. Collecting which files to lint
2. Lint cache lookups
### Collecting which files to lint
Improve this by:
* using an NSOrderedSet to remove excluded paths instead of `Array.filter`
* parallelizing calls to `filesToLint` for all paths to lint and exclude
* using `FileManager.subpaths(atPath:)` instead of `enumerator(atPath:)`
|Change|Before|After|Speed up|
|-|-|-|-|
|NSOrderedSet|2.438s|0.917s|2.659x|
|Parallel Flat Map|2.438s|2.248s|1.085x|
|Subpaths|0.939s|0.867s|1.083x|
|**Total**|**2.438s**|**0.720s**|**3.386x**|
### Lint cache lookups
By using an MD5 hash of the Configuration description from CryptoSwift as the cache key instead of instead the full description, we can drastically speed up cache lookups for projects with complex SwiftLint configurations. I think the dictionary lookup for very large string keys doesn't perform very well.
---
* Speed up Configuration.lintablePaths
* Improve cache lookup performance by up to 10x
By using an MD5 hash of the Configuration description from CryptoSwift
as the cache key instead of instead the full description.
* Add changelog entries
* Swift 4.0 & Linux compatibility
* os(Darwin) isn't a thing
* Allow warnings in pod lib lint
SwiftLint supports building with Swift 4.0 to 4.2.
There is no version of CryptoSwift to support both Swift 4.0 and
Swift 4.2.
So allow warnings for now. We'll make one more Swift 4.0 compatible
release, then we'll bump the build requirements to Swift 4.2 and
remove the `--allow-warnings` flag.