Created
October 1, 2022 16:52
-
-
Save umurgdk/f93b75c6478847a38ee008f2d3dd5fc6 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: UnsafeMutableBufferPointer<UInt8> | |
var bufferSize = 0 | |
init(file: OutputStream, bufferCapacity: Int = 10_024_000) { | |
self.file = file | |
self.bufferCapacity = bufferCapacity | |
self.buffer = .allocate(capacity: bufferCapacity) | |
self.buffer.initialize(repeating: 0) | |
} | |
@inline(__always) | |
mutating func write(_ string: String) throws -> Int { | |
let utf8View = string.utf8 | |
let stringLen = utf8View.count | |
if bufferSize + stringLen >= bufferCapacity { | |
try flush() | |
} | |
let writeAddress = buffer.baseAddress!.advanced(by: bufferSize) | |
utf8View.withContiguousStorageIfAvailable { bytes in | |
writeAddress.assign(from: bytes.baseAddress!, count: stringLen) | |
} | |
bufferSize += stringLen | |
return utf8View.count | |
} | |
@inline(__always) | |
mutating func flush() throws { | |
let writtenBytes = file.write(buffer.baseAddress!, maxLength: bufferSize) | |
if writtenBytes != bufferSize { | |
throw Errors.failedToWrite | |
} | |
bufferSize = 0 | |
} | |
} | |
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") | |
} | |
try main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment