0

I'm finally familiar enough with Unsafe…Pointer types in Swift to try to address how the following code was marked as unsafe by XCode.

let pixelBuffer = UnsafeMutablePointer<UInt32>(&pixels)
let bytes = UnsafeRawPointer(pixelBuffer).assumingMemoryBound(to: UInt8.self)
destination.assign(from: bytes, count: pixels.count * 4)

This generated the warning "Initialization of 'UnsafeMutablePointer' results in a dangling pointer". It also runs without error and in approximately 0.00056 seconds. I've found two potential solutions, but both run slower

For the sake of clarity:

var pixels: [UInt32] = …
let destination: UnsafeMutablePointer<UInt8> = …
let destinationCount = pixels.count * 4

I've come up with two alternatives, both of which are considerably slower. This executes in 0.00364 seconds. As I understand the documentation, Data(buffer:) performs a copy, meaning this copies twice:

pixels.withUnsafeMutableBufferPointer { pixelBuffer in
    let data = Data(buffer: pixelBuffer)
    data.copyBytes(to: destination, count: destinationCount)
}

This executes in 0.02529 seconds.

pixels.withUnsafeBytes { pixelBytes in
    let pointer = UnsafeMutableRawBufferPointer(start: destination, count: destinationCount)
    pointer.copyBytes(from: pixelBytes)
}

I would have suspected that due to less copying, the second solution would be faster but clearly it's not. Overall this is all negligible but I really want to understand what's going on here, and why a two-copy solution executes in 1/7 the time.

For benchmarking I'm taking the interval between to Date() objects from directly before and after the block is executed.

  • 1
    "For benchmarking I'm taking the interval between to Date() objects from directly before and after the block is executed." That's not how you properly benchmark. Please benchmark with Instruments – Sweeper Jul 03 '20 at 11:05
  • Or at least use the `CFAbsoluteTimeGetCurrent` or `XCTestCase`'s `measure` method. But you should prefer [`os_signpost`](https://developer.apple.com/documentation/os/3019241-os_signpost) & Instruments. BTW there's `Data` initializer which doesn't copy. – zrzka Jul 03 '20 at 13:12

0 Answers0