christophhagen / BinaryCodable

A binary encoder for Swift Codable types
MIT License
92 stars 7 forks source link

Slow encoding with new binary format in v3 #20

Closed galijot closed 6 months ago

galijot commented 6 months ago

I tried updating from v2.0.2 to v3.0.1 to benefit the new format and performance that comes with it. However, per me testing, new format seems to be a downgrade for my specific use-case.

I'd like to share what I found; maybe my use-case is very specific and shouldn't be optimized for it. For the time being, I think I'll stick to v2 of this awesome library!

My Codable type is a final class with about 10 properties, most being primitive types along with two small and simple structs - and one huge Float array. The array normally holds a few million elements.

During encoding, I'm converting the Float array to Data type, which makes encoding much faster:

let data: Data = floatArray.withUnsafeBufferPointer { Data(buffer: $0) }

Decoding also gets much faster this way:

let data: Data = try container.decode(Data.self, forKey: .floatArray)
floatArray = data.withUnsafeBytes { Array($0.bindMemory(to: Float.self)) }

Using v2, encoding took on average ~40ms and decoding took ~4ms. Using v3, encoding jumped on average to 1.5sec, though decoding was slightly faster, with average of ~3ms.

christophhagen commented 6 months ago

Hi, thanks for raising this issue!

I created a test case for your described usage, and I think I could fix the bug. At least on my system, encoding an array of 1 million floats (in the way you described) used to take 0,65s, which is now down to 0,003s (a speed improvement of over 200x!).

If you want you can test the fix, you can check out PR #21 against your code. I'll merge this fix soon into master and create a bugfix release.

christophhagen commented 6 months ago

BTW, be careful when directly using the memory representation of values. If you exchange data between systems of different endianness, then there may be issues decoding the data correctly. If you only ever use the data on one system (e.g. for local storage) you should be fine.

galijot commented 6 months ago

Thank you for being so prompt on this!

I've updated to v3.0.3 and can confirm that in my case, when comparing encoding and decoding durations to v2.0.2, on average, encoding is faster by approximately 70% and decoding is faster by about 40%!

Also, thank you for the advice on using memory representation of values. Luckily I only use the data on one system so I'm good.