Skip to content

Instantly share code, notes, and snippets.

@umurgdk
Created October 1, 2022 15:42
Show Gist options
  • Save umurgdk/1ea48caf4ca5aa9e62f4f43d5477f4a3 to your computer and use it in GitHub Desktop.
Save umurgdk/1ea48caf4ca5aa9e62f4f43d5477f4a3 to your computer and use it in GitHub Desktop.
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