Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 190 additions & 6 deletions Benchmarks/Benchmarks/URL/BenchmarkURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ let benchmarks = {
Benchmark.defaultConfiguration.scalingFactor = .kilo
Benchmark.defaultConfiguration.metrics = [.cpuTotal, .throughput]

let validURLString = "scheme://username:password@app.example.com:80/pathwithoutspaces/morepath?queryname=queryvalue#fragmentwithoutspaces"
let validURLString = "http://example.com/path/index.html?query=value&some#fragment"
let invalidURLString = "scheme://username:password@example.com:invalidport/path?query#fragment"
let encodableURLString = "scheme://user name:pass word@😂😂😂.example.com:80/path with spaces/more path?query name=query value#fragment with spaces"
let encodableASCIIString = "http://example.com/users/John Doe/home?date=01\\01\\2001"
let encodableUnicodeString = "http://😂😂😂.com/users/i❤️swift/home%2Fpath?date=01∕01∕2001"

// MARK: - String Parsing

Expand Down Expand Up @@ -57,15 +58,27 @@ let benchmarks = {
}

#if os(macOS) || compiler(>=6)
Benchmark("URL.ParseAndEncode") { benchmark in
Benchmark("URL.ParseAndEncodeASCII") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(string: encodableURLString))
blackHole(URL(string: encodableASCIIString))
}
}

Benchmark("URLComponents.ParseAndEncode") { benchmark in
Benchmark("URLComponents.ParseAndEncodeASCII") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URLComponents(string: encodableURLString))
blackHole(URLComponents(string: encodableASCIIString))
}
}

Benchmark("URL.ParseAndEncodeUnicode") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(string: encodableUnicodeString))
}
}

Benchmark("URLComponents.ParseAndEncodeUnicode") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URLComponents(string: encodableUnicodeString))
}
}
#endif
Expand Down Expand Up @@ -279,4 +292,175 @@ let benchmarks = {
}
}
}

// MARK: - Non-File URL Path Manipulation

let url = URL(string: "https://www.swift.org/api/v1/install/")!

Benchmark("URL.isFileURL") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(url.isFileURL)
}
}

Benchmark("URL.AppendingPathComponent") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(url.appending(path: "releases.json"))
}
}

Benchmark("URL.DeletingLastPathComponent") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(url.deletingLastPathComponent())
}
}

Benchmark("URL.PathComponents") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(url.pathComponents)
}
}

let swiftly = URL(string: ".././swiftly.json", relativeTo: url)!

Benchmark("URL.Standardized") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(swiftly.standardized)
}
}

Benchmark("URL.AbsoluteURL") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(swiftly.absoluteURL)
}
}

// MARK: - File URL

Benchmark("URL.ParseFilePath") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(filePath: "/Users/Foo/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/"))
}
}

let fileURL = URL(filePath: "/Users/Foo/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/")

Benchmark("FileURL.isFileURL") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.isFileURL)
}
}

Benchmark("FileURL.GetPath") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.path)
}
}

Benchmark("FileURL.AppendingPathComponent") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.appending(path: "modules.timestamp"))
}
}

Benchmark("FileURL.DeletingLastPathComponent") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.deletingLastPathComponent())
}
}

Benchmark("FileURL.LastPathComponent") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.lastPathComponent)
}
}

Benchmark("FileURL.PathComponents") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.pathComponents)
}
}

Benchmark("FileURL.AppendingPathExtension") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.appendingPathExtension("tar.gz"))
}
}

Benchmark("FileURL.DeletingPathExtension") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.deletingPathExtension())
}
}

Benchmark("FileURL.PathExtension") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURL.pathExtension)
}
}

let fileURLWithDots = URL(filePath: "/Users/Foo/./Downloads/../Library//Developer/./Xcode/DerivedData/..")

Benchmark("FileURL.Standardized") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(fileURLWithDots.standardized)
}
}

Benchmark("URL.ParseAndEncodeFilePath") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(filePath: "/Users/John Doe/Application Support/Xcode/"))
}
}

let encodableFileURL = URL(filePath: "/Users/John Doe/Application Support/Xcode/")

Benchmark("FileURL.GetDecodedPath") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(encodableFileURL.path)
}
}

// MARK: - Data Round Trip

var data = Data("data:".utf8)
for i in 0..<1000 {
data.append(UInt8(i % 128))
}

Benchmark("URL.DataRepresentation") { benchmark in
for _ in benchmark.scaledIterations {
let url = URL(dataRepresentation: data, relativeTo: nil)!
blackHole(url)
blackHole(url.dataRepresentation)
}
}

// MARK: - Long Strings

let longDataString = {
var string = "data:text/plain;base64,"
for i in 0..<2048 {
string += "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9w"
}
return string
}()

Benchmark("URL.ParseBigString") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(string: longDataString))
}
}

Benchmark("URL.ParseBigFilePath") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(filePath: "/Lorem/ipsum/dolor/sit/amet,/consectetur/adipiscing/elit./Aliquam/aliquam/a/libero/sit/amet/eleifend./Nulla/sapien/mi,/eleifend/quis/accumsan/id,/sollicitudin/in/nulla./Fusce/non/sodales/dolor./Morbi/luctus/consequat/felis/vitae/elementum./Nam/id/ex/in/sapien/congue/varius/nec/quis/eros./Proin/ut/turpis/eu/nisl/efficitur/tempus./Donec/mattis/congue/arcu/vel/convallis./Integer/sit/amet/nunc/sagittis,/gravida/ligula/eu,/varius/quam./Phasellus/sodales/ut/libero/id/ultrices./Mauris/tristique/risus/quis/massa/porta,/vel/ornare/libero/pharetra./Phasellus/id/suscipit/magna./Etiam/porta/nunc/ut/dolor/sollicitudin/commodo./Praesent/consequat/elit/a/ipsum/sodales/rhoncus./Fusce/malesuada/sed/diam/eget/rhoncus./Mauris/et/interdum/nulla./Sed/egestas/egestas/turpis/nec/imperdiet."))
}
}

Benchmark("URL.ParseAndEncodeBigFilePath") { benchmark in
for _ in benchmark.scaledIterations {
blackHole(URL(filePath: "/Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam aliquam a libero sit amet eleifend. Nulla sapien mi, eleifend quis accumsan id, sollicitudin in nulla. Fusce non sodales dolor. Morbi luctus consequat felis vitae elementum. Nam id ex in sapien congue varius nec quis eros. Proin ut turpis eu nisl efficitur tempus. Donec mattis congue arcu vel convallis. Integer sit amet nunc sagittis, gravida ligula eu, varius quam. Phasellus sodales ut libero id ultrices. Mauris tristique risus quis massa porta, vel ornare libero pharetra. Phasellus id suscipit magna. Etiam porta nunc ut dolor sollicitudin commodo. Praesent consequat elit a ipsum sodales rhoncus. Fusce malesuada sed diam eget rhoncus. Mauris et interdum nulla. Sed egestas egestas turpis nec imperdiet."))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -526,3 +526,19 @@ extension _FileManagerImpl {
#endif
}
}

extension URL {
/// Returns `nil` if `getcwd` fails instead of an empty path `URL`.
static func currentDirectoryOrNil() -> URL? {
#if os(Windows)
URL(filePath: FileManager.default.currentDirectoryPath, directoryHint: .isDirectory)
#else
withUnsafeTemporaryAllocation(of: CChar.self, capacity: FileManager.MAX_PATH_SIZE) { buffer in
guard getcwd(buffer.baseAddress!, FileManager.MAX_PATH_SIZE) != nil else {
return nil
}
return URL(fileURLWithFileSystemRepresentation: buffer.baseAddress!, isDirectory: true, relativeTo: nil)
}
#endif
}
}
Loading
Loading