Created
October 1, 2022 15:42
-
-
Save umurgdk/1ea48caf4ca5aa9e62f4f43d5477f4a3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Darwin | |
var logID: Int64 = 0 | |
enum Errors: String, Error { | |
case couldntOpenFile | |
case failedToWrite | |
} | |
struct BufferedWriter { | |
let file: OutputStream | |
let bufferCapacity: Int | |
var buffer: Data | |
init(file: OutputStream, bufferCapacity: Int = 10_024_000) { | |
self.file = file | |
self.bufferCapacity = bufferCapacity | |
self.buffer = Data(capacity: bufferCapacity) | |
} | |
@inline(__always) | |
mutating func write(_ string: String) throws -> Int { | |
let utf8View = string.utf8 | |
let stringLen = utf8View.count | |
if buffer.count + stringLen >= bufferCapacity { | |
try flush() | |
} | |
buffer.append(contentsOf: utf8View) | |
return utf8View.count | |
} | |
@inline(__always) | |
mutating func flush() throws { | |
let bufferSize = buffer.count | |
let writtenBytes = try buffer.withUnsafeBytes { bytes in | |
file.write(bytes, maxLength: bufferSize) | |
} | |
if writtenBytes != bufferSize { | |
throw Errors.failedToWrite | |
} | |
buffer.removeAll(keepingCapacity: true) | |
} | |
} | |
@main | |
struct App{ | |
public static func main() throws { | |
guard let file = OutputStream(toFileAtPath: "output.txt", append: false) else { | |
throw Errors.couldntOpenFile | |
} | |
file.open() | |
var bufferedWriter = BufferedWriter(file: file) | |
print("Starting to write...") | |
let beginning = Date() | |
var totalBytesWritten: Int = 0 | |
let message = "This is a really long log message with the id: \(logID)" | |
while true { | |
let bytesWritten = try bufferedWriter.write(message) | |
totalBytesWritten += bytesWritten | |
logID += 1 | |
if totalBytesWritten >= 512_000_000 { | |
break | |
} | |
} | |
try bufferedWriter.flush() | |
file.close() | |
let operationDuration = Date().timeIntervalSince(beginning) | |
let bytesMeasurement = Measurement<UnitInformationStorage>(value: Double(totalBytesWritten), unit: .bytes) | |
let timeMeasurement = Measurement<UnitDuration>(value: operationDuration, unit: .seconds) | |
let megabytesPerSecond = bytesMeasurement | |
print("Written \(bytesMeasurement.converted(to: .megabytes)) bytes in \(timeMeasurement) seconds") | |
print("Performance: \(bytesMeasurement.converted(to: .megabytes).value / timeMeasurement.value) mb/s") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment