diff --git a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift index 20613c3a..fe0f334e 100644 --- a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift +++ b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift @@ -19,7 +19,7 @@ protocol BenchmarkCommand: Command { var benchmarkName: String { get } - func loadInput(_ input: String) throws -> InputType + func loadInput(_ input: String) throws -> (InputType, Double) var benchmarkFunction: (InputType) throws -> Any { get } @@ -27,9 +27,12 @@ protocol BenchmarkCommand: Command { extension BenchmarkCommand where InputType == Data { - func loadInput(_ input: String) throws -> Data { + func loadInput(_ input: String) throws -> (Data, Double) { let inputURL = URL(fileURLWithPath: input) - return try Data(contentsOf: inputURL, options: .mappedIfSafe) + let inputData = try Data(contentsOf: inputURL, options: .mappedIfSafe) + let attr = try FileManager.default.attributesOfItem(atPath: input) + let inputSize = Double(attr[.size] as! UInt64) + return (inputData, inputSize) } } @@ -44,12 +47,12 @@ extension BenchmarkCommand { for input in self.inputs.value { print("Input: \(input)") - let loadedInput = try self.loadInput(input) + let (loadedInput, inputSize) = try self.loadInput(input) - var totalTime: Double = 0 + var totalSpeed: Double = 0 - var maxTime = Double(Int.min) - var minTime = Double(Int.max) + var maxSpeed = Double(Int.min) + var minSpeed = Double(Int.max) print("Iterations: ", terminator: "") #if !os(Linux) @@ -59,7 +62,8 @@ extension BenchmarkCommand { let startTime = CFAbsoluteTimeGetCurrent() _ = try benchmarkFunction(loadedInput) let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime - print(String(format: "(%.3f) ", timeElapsed), terminator: "") + let speed = inputSize / timeElapsed + print("(\(SpeedFormat(speed).format())), ", terminator: "") #if !os(Linux) fflush(__stdoutp) #endif @@ -68,19 +72,22 @@ extension BenchmarkCommand { let startTime = CFAbsoluteTimeGetCurrent() _ = try benchmarkFunction(loadedInput) let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime - print(String(format: "%.3f ", timeElapsed), terminator: "") + let speed = inputSize / timeElapsed + print(SpeedFormat(speed).format() + ", ", terminator: "") #if !os(Linux) fflush(__stdoutp) #endif - totalTime += timeElapsed - if timeElapsed > maxTime { - maxTime = timeElapsed + totalSpeed += speed + if speed > maxSpeed { + maxSpeed = speed } - if timeElapsed < minTime { - minTime = timeElapsed + if speed < minSpeed { + minSpeed = speed } } - print(String(format: "\nAverage: %.3f \u{B1} %.3f\n", totalTime / 10, (maxTime - minTime) / 2)) + let avgSpeed = totalSpeed / 10 + let devSpeed = (maxSpeed - minSpeed) / 2 + print("\nAverage: \(SpeedFormat(avgSpeed).format()) \u{B1} \(SpeedFormat(devSpeed).format())\n") } } diff --git a/Sources/swcomp/Benchmarks/CreateTar.swift b/Sources/swcomp/Benchmarks/CreateTar.swift index b59ca1be..404ee8a3 100644 --- a/Sources/swcomp/Benchmarks/CreateTar.swift +++ b/Sources/swcomp/Benchmarks/CreateTar.swift @@ -17,8 +17,19 @@ class CreateTar: BenchmarkCommand { let benchmarkName = "TAR Create" let benchmarkFunction: ([TarEntry]) throws -> Any = TarContainer.create - func loadInput(_ input: String) throws -> [TarEntry] { - return try TarEntry.createEntries(input, false) + func loadInput(_ input: String) throws -> ([TarEntry], Double) { + return try (TarEntry.createEntries(input, false), Double(URL(fileURLWithPath: input).directorySize())) + } + +} + +fileprivate extension URL { + + func directorySize() throws -> Int { + let urls = FileManager.default.enumerator(at: self, includingPropertiesForKeys: nil)?.allObjects as! [URL] + return try urls.lazy.reduce(0) { + (try $1.resourceValues(forKeys: [.totalFileAllocatedSizeKey]).totalFileAllocatedSize ?? 0) + $0 + } } } diff --git a/Sources/swcomp/Benchmarks/SpeedFormat.swift b/Sources/swcomp/Benchmarks/SpeedFormat.swift new file mode 100644 index 00000000..67a3a1af --- /dev/null +++ b/Sources/swcomp/Benchmarks/SpeedFormat.swift @@ -0,0 +1,45 @@ +// Copyright (c) 2021 Timofey Solomko +// Licensed under MIT License +// +// See LICENSE for license information + +import Foundation + +enum SpeedFormat { + + case bytes(Double) + case kilo(Double) + case mega(Double) + case giga(Double) + case tera(Double) + + init(_ speed: Double) { + if speed > pow(1000, 4) { + self = .tera(speed) + } else if speed > pow(1000, 3) { + self = .giga(speed) + } else if speed > pow(1000, 2) { + self = .mega(speed) + } else if speed > 1000 { + self = .kilo(speed) + } else { + self = .bytes(speed) + } + } + + func format() -> String { + switch self { + case .bytes(let speed): + return String(format: "%.3f B/s", speed) + case .kilo(let speed): + return String(format: "%.3f kB/s", speed / 1000) + case .mega(let speed): + return String(format: "%.3f MB/s", speed / 1000 / 1000) + case .giga(let speed): + return String(format: "%.3f GB/s", speed / 1000 / 1000 / 1000) + case .tera(let speed): + return String(format: "%.3f TB/s", speed / 1000 / 1000 / 1000 / 1000) + } + } + +}