Last two days I was asking GTP to optimise code to speed up things.
And it does do a good job in general. But one thing really blew my mind.
I had a method that converts byte size of a file into a readable format like 15.9MB, 1.53GB, …
That methode looked like this.
if bytes = 0 then return "0 Bytes"
var k as integer = 1000
var sizes() as string
sizes = array("Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
var i as double = floor( log(bytes) / log(k) )
return format(bytes / pow(k , i),"#.00") + " " + sizes(i)
So I ask GTP:
“Optimise for speed the following xojo code: if bytes = 0 then return “0 Bytes”
var k as integer = 1000
var sizes() as string
sizes = array(“Bytes”, “KB”, “MB”, “GB”, “TB”, “PB”, “EB”, “ZB”, “YB”)
var i as double = floor( log(bytes) / log(k) )
return format(bytes / pow(k , i),”#.00") + " " + sizes(i)
And the answer was this:
The code you provided is used to format a given number of bytes into a human-readable string that includes units (e.g. “KB”, “MB”, etc.). Here are a few potential optimizations you can make to improve its speed:
- Use integer math instead of floating-point math: The
logandpowfunctions in your code use floating-point math, which can be slower than integer math. Since thesizesarray is only 9 elements long, you can precompute the powers of 1000 and store them in a separate array. Then you can use integer division and modulus to compute the appropriate index into thesizesarray:
if bytes = 0 then return "0 Bytes"
var k as integer = 1000
var sizes() as string = array("Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
var powers() as integer = array(1, k, k*k, k*k*k, k*k*k*k, k*k*k*k*k, k*k*k*k*k*k, k*k*k*k*k*k*k, k*k*k*k*k*k*k*k)
dim i as integer = 0
while bytes >= powers(i+1) and i < 8
i = i + 1
wend
return str(bytes \ powers(i)) + "." + right("0" + str(bytes mod powers(i) \ powers(i-1)), 2) + " " + sizes(i)
- Avoid unnecessary function calls: The
formatfunction in your code is used to format the number of bytes with two decimal places. However, you can achieve the same result using integer division and modulus. This avoids the overhead of a function call:
if bytes = 0 then return "0 Bytes"
var k as integer = 1000
var sizes() as string = array("Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
var powers() as integer = array(1, k, k*k, k*k*k, k*k*k*k, k*k*k*k*k, k*k*k*k*k*k, k*k*k*k*k*k*k, k*k*k*k*k*k*k*k)
dim i as integer = 0
while bytes >= powers(i+1) and i < 8
i = i + 1
wend
return str(bytes \ powers(i)) + "." + right("0" + str(bytes mod powers(i) \ powers(i-1)), 2) + " " + sizes(i)
By implementing these optimizations, you can significantly improve the performance of your code while still producing the same output.
So I tried this with 1000 files.
And the solution provided by GTP was about 280% faster! Incredible. And to be honest, I would never ever came up with the code myself. Pretty nifty.