#string #performance #integer #swift5
#строка #Производительность #целое #swift5
Вопрос:
import Foundation
let first = readLine()! // input : 10 20 30
processTime {
first.split(separator: " ").map { Int($0)! }
}
processTime {
first.split(separator: " ").map { Int(String($0))! }
}
func processTime(blockFunction: () -> ()) {
let startTime = CFAbsoluteTimeGetCurrent()
blockFunction()
let processTime = CFAbsoluteTimeGetCurrent() - startTime
print("performance = (processTime)")
}
производительность = 0.0012700557708740234 => Int($ 0)!
производительность = 0.000843048095703125 => Int(строка($ 0))!
Я использовал map для преобразования в Int. Но это заняло меньше времени, когда я преобразовал его в «Int(String ($ 0))!». Интересно, почему.
Ответ №1:
split
Возвращает не строки, а подстроки, поэтому Int($0)
исполнение преобразует подстроки в целые числа и Int(String($0))
преобразует подстроку в строку, а затем в целое число.
Глядя на разборку для этих двух версий, они вызывают разные Int.init?
методы. Но в сборке многое происходит, поэтому немного сложно сказать, единственное ли это отличие или некоторые другие вещи, происходящие в фоновом режиме, также могут оказать некоторое скромное влияние.
Но можно с уверенностью сказать, что преобразование String
в Int
более эффективно, чем работа с подстроками. Как уже было сказано, я бы придерживался более чистого кода и не беспокоился об этой незначительной разнице, если только эта разница, измеряемая в десятитысячные доли секунды, не будет существенной (т. Е. Вы делаете это миллионы раз, что в другом месте кода нет других вещей, которые могли бы иметь больше возможностей для оптимизации материала и т.д.). Как сказал Дональд Кнут:
Мы должны забыть о небольшой эффективности, скажем, в 97% случаев: преждевременная оптимизация — корень всего зла. И все же мы не должны упускать наши возможности в этих критических 3%.
Кстати, при измерении производительности, вместо измерения одного вызова, сделайте это миллионы раз и посмотрите, как они сравниваются. Кроме того, при тестировании производительности вы можете также попробовать рандомизировать порядок, в котором вы выполняете тесты, повторив его несколько раз, чтобы убедиться, что порядок выполнения не влияет на производительность. Наконец, убедитесь, что вы тестируете оптимизированную сборку выпуска, а не отладочную сборку.
Кроме того, в модульных тестах есть measure
метод сравнения производительности, повторяющий тест десять раз:
class ConversionBenchmarkTests: XCTestCase {
let input = "10 20 30"
let count = 100_000
func testInt() throws {
measure {
for _ in 0 ..< count {
let result = input.split(separator: " ").map { Int($0)! }
XCTAssertEqual(result.count, 3)
}
}
}
func testString() throws {
measure {
for _ in 0 ..< count {
let result = input.split(separator: " ").map { Int(String($0))! }
XCTAssertEqual(result.count, 3)
}
}
}
}
String
Исполнение было в два раза быстрее: