Reputation: 21237
I'm wondering if someone can help me to understand what I believe is related to caching while parsing a JSON object.
I'm trying to benchmark various deserializing libraries (Gson, Kotlin-serialization, Immutables, etc.). I have a string that is read in from a file in json format. I want use each library to parse this string repeatedly and then determine the average time that the library takes to parse the file.
My results are confusing. For example, using kotlin-serialization, the first time the string is parsed, it takes 140ms. I parsed it 5 more times in the same run of the app, and it took 3, 4, 4, 2, and 5 ms, respectively. Clearly, the subsequent executions are benefiting from some sort of caching or memory advantage. This same pattern occurs across any of the libraries that I have tested.
class MainActivity : AppCompatActivity() {
private val stringBuilder = StringBuilder()
private lateinit var jsonString: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
jsonString = assets.open("jsonresponse.json").bufferedReader().use { it.readText() }
stringBuilder.append("\nAverage Deserialization Times:\n")
button_deserialize.setOnClickListener {
benchmarkKotlin()
stringBuilder.append("\n---------------------\n\n")
results.text = stringBuilder.toString()
}
}
fun benchmarkKotlin() {
val target = arrayOfNulls<MyDataClass>(NUM_ITERATIONS)
val t1 = System.currentTimeMillis()
for (i in 0 until NUM_ITERATIONS) {
try {
target[i] = Json.nonstrict.parse(
MyDataClass.serializer(),
jsonString
)
} catch (ignored: MissingFieldException){}
}
val t2 = System.currentTimeMillis()
val avg = (t2 - t1) / NUM_ITERATIONS
stringBuilder.append("Kotlin: $avg ms\n")
}
}
So my question is how can I modify this so that every iteration of the loop is comparable to the first one? Can I turn off caching? Instantiate objects differently?
Thanks.
Upvotes: 1
Views: 511
Reputation: 6277
This may directly not answer your question.
Try using Android's TimingLogger for measuring time and to make your benchmarking easier
A utility class to help log timings splits throughout a method call. Typical usage is:
TimingLogger timings = new TimingLogger(TAG, "methodA"); // ... do some work A ... timings.addSplit("work A"); // ... do some work B ... timings.addSplit("work B"); // ... do some work C ... timings.addSplit("work C"); timings.dumpToLog();
The dumpToLog call would add the following to the log:
D/TAG ( 3459): methodA: begin D/TAG ( 3459): methodA: 9 ms, work A D/TAG ( 3459): methodA: 1 ms, work B D/TAG ( 3459): methodA: 6 ms, work C D/TAG ( 3459): methodA: end, 16 ms
Upvotes: 1