Optimize C string to Kotlin String conversion
andersio opened this issue · 3 comments
I did some synthetic benchmarking in this area recently, and discovered that toKStringFromUtf8()
is quite underwhelming, especially in debug builds. Imagine in debug builds, 100 rows of 2KB worth of strings take a whopping 18ms — more than a frame at 60fps.
The results were filed in this issue: https://youtrack.jetbrains.com/issue/KT-44357.
Since toKStringFromUtf8()
is a hot path for getting strings out of SQLite, it might be valuable for SQLiter to drop toKStringFromUtf8()
for the alternatives listed, until improvements were made to the stdlib. Most importantly, these alternatives have a way less drastic debug-release performance gap, so developer experience is improved too.
TL;DR of the options:
-
Given the known size via
sqlite3_column_bytes()
,memcpy()
the C string to aByteArray
, and then useByteArray.decodeToString()
. -
Convert the C string first to
NSString
, and then to KString viatoString()
oras String
.This is the fastest option, though it is exclusive to Darwin targets.
Take a look. I didn't run your benchmarks, but I'm not super surprised with the outcome. I think we're likely to find this kind of thing in places.
The pre-cinterop version of this library probably had better performance as it was pretty much calling c++ to directly create a utf16 from utf8, and returning that as a Kotlin string. Anyway...
columnGetString
and columnName
both call into bytesToString
, which is an expect/actual.
expect inline fun bytesToString(bv:CPointer<ByteVar>):String
Currently the only actual targets are apple-related and windows. For apple targets, this is the implementation:
actual inline fun bytesToString(bv:CPointer<ByteVar>):String = NSString.create(bv).toString()
I didn't try so hard on windows, however.
actual inline fun bytesToString(bv:CPointer<ByteVar>):String = bv.toKStringFromUtf8()
We can try the other option you presented if somebody wants to give that a run on windows. I'm also going to take a look at toKStringFromUtf8
itself as I've spent some time in the native compiler in the past.
Pushing a PR. Take a look if you get a chance.
BTW, looked at the code for toKStringFromUtf8
and the comment right on top of it is pretty great.
// TODO: optimize
Added back in Jan. Just entering use now with Sqldelight 1.5+.