Skip to content

Instantly share code, notes, and snippets.

@benbahrenburg
Last active January 26, 2024 19:49
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save benbahrenburg/8372cb79a63d699b9e66a18e0e24409c to your computer and use it in GitHub Desktop.
Save benbahrenburg/8372cb79a63d699b9e66a18e0e24409c to your computer and use it in GitHub Desktop.
Swift Playground for testing memory associated with converting UIImage to Data
import UIKit
import ImageIO
import MobileCoreServices
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func report_memory() -> UInt64 {
var taskInfo = mach_task_basic_info()
var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
let kerr: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
}
}
return kerr == KERN_SUCCESS ? taskInfo.resident_size : 0
}
func UIImageToDataJPEG2(image: UIImage, compressionRatio: CGFloat) -> Data? {
return autoreleasepool(invoking: { () -> Data? in
return UIImageJPEGRepresentation(image, compressionRatio)
})
}
func UIImageToDataIO(image: UIImage, compressionRatio: CGFloat, orientation: Int = 1) -> Data? {
return autoreleasepool(invoking: { () -> Data in
let data = NSMutableData()
let options: NSDictionary = [
kCGImagePropertyOrientation: orientation,
kCGImagePropertyHasAlpha: true,
kCGImageDestinationLossyCompressionQuality: compressionRatio
]
let imageDestinationRef = CGImageDestinationCreateWithData(data as CFMutableData, kUTTypeJPEG, 1, nil)!
CGImageDestinationAddImage(imageDestinationRef, image.cgImage!, options)
CGImageDestinationFinalize(imageDestinationRef)
return data as Data
})
}
func Test_JPEGRepresentation_AutoRelease(iterations: Int, compressionRatio: CGFloat,image: UIImage) {
//Gather the initial information
let startReading = report_memory()
print("Memory at start: \(startReading / 1024 / 1024) mb")
//Loop through the number of test iterations specified
for index in 1...iterations {
if let data = UIImageToDataJPEG2(image: image, compressionRatio: compressionRatio) {
//Sample the length of the first result to make sure we are comparing the same size
if index == 1 {
//Report out results
let dataSize = Int(data.count / 1024 / 1024)
print("Data Length: \(dataSize) mb")
}
}
}
let endReading = report_memory()
print("Memory at finish: \(Int(endReading / 1024 / 1024)) mb")
let delta = (Int(Int(endReading) - Int(startReading)) / 1024 / 1024)
print("Memory delta: \(delta) mb")
}
func Test_JPEGRepresentation_Standard(iterations: Int, compressionRatio: CGFloat, image: UIImage) {
//Gather the initial information
let startReading = report_memory()
print("Memory at start: \(startReading / 1024 / 1024) mb")
//Loop through the number of test iterations specified
for index in 1...iterations {
if let data = UIImageJPEGRepresentation(image, compressionRatio) {
//Sample the length of the first result to make sure we are comparing the same size
if index == 1 {
//Report out results
let dataSize = Int(data.count / 1024 / 1024)
print("Data Length: \(dataSize) mb")
}
}
}
let endReading = report_memory()
print("Memory at finish: \(Int(endReading / 1024 / 1024)) mb")
let delta = (Int(Int(endReading) - Int(startReading)) / 1024 / 1024)
print("Memory delta: \(delta) mb")
}
func Test_ImageIO(iterations: Int, compressionRatio: CGFloat, image: UIImage) -> Void {
//Gather the initial information
let startReading = report_memory()
print("Memory at start: \(startReading / 1024 / 1024) mb")
//Loop through the number of test iterations specified
for index in 1...iterations {
if let data = UIImageToDataIO(image: image, compressionRatio: compressionRatio) {
//Sample the length of the first result to make sure we are comparing the same size
if index == 1 {
//Report out results
let dataSize = Int(data.count / 1024 / 1024)
print("Data Length: \(dataSize) mb")
}
}
}
let endReading = report_memory()
print("Memory at finish: \(Int(endReading / 1024 / 1024)) mb")
let delta = (Int(Int(endReading) - Int(startReading)) / 1024 / 1024)
print("Memory delta: \(delta) mb")
}
//Setup the parameters for testing
let JPEG_Standard_run: Bool = true
let JPEG_AutoRelease_run: Bool = false
let ImageIO_run: Bool = false
let testIterations: Int = 14
let compressionRatio: CGFloat = 0.9
let image = UIImage(named: "YOUR-IMAGE-GOES-HERE.jpg")!
let memAtStart = report_memory() / 1024 / 1024
print("++++++++++++++++++++++++++++++++++++++++++++++++++++++")
print("Image to Data tests")
print("Test Criteria - iterations: \(testIterations) compressionRatio: \(compressionRatio)")
print("Memory at start: \(memAtStart) mb")
print("++++++++++++++++++++++++++++++++++++++++++++++++++++++")
print("")
print("")
if JPEG_Standard_run {
print("Testing JPEGRepresentation")
print("-----------------------------------------------------")
Test_JPEGRepresentation_Standard(iterations: testIterations, compressionRatio: compressionRatio, image: image)
print("-----------------------------------------------------")
print("")
}
if JPEG_AutoRelease_run {
print("Testing JPEGRepresentation wrapped in autoreleasepool")
print("-----------------------------------------------------")
Test_JPEGRepresentation_AutoRelease(iterations: testIterations, compressionRatio: compressionRatio, image: image)
print("-----------------------------------------------------")
print("")
}
if ImageIO_run {
print("Testing ImageIO")
print("-----------------------------------------------------")
Test_ImageIO(iterations: testIterations, compressionRatio: compressionRatio, image: image)
print("-----------------------------------------------------")
print("")
}
print("")
print("-----------------------------------------------------")
print("-----------------------------------------------------")
print("")
let memAtFinish = report_memory() / 1024 / 1024
print("Finished Image tests with \(testIterations) iterations - Memory at finish: \(memAtFinish)")
let memUsed = Int(memAtFinish) - Int(memAtStart)
print("Memory used while testing: \(memUsed)")
print("")
print("-----------------------------------------------------")
print("-----------------------------------------------------")
print("")
let delayFor: Double = 10
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayFor) {
let laterSample = report_memory() / 1024 / 1024
print("Memory Sample After \(delayFor) seconds: Usage \(Int(laterSample))")
print("Memory Sample After \(delayFor) seconds: Delta since tests stopped \(Int(memAtFinish) - Int(laterSample))")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment