With lots of data key.to_s and camelize(:lower) can be a bottleneck.
Probably Gon was never intended for such use case, but here we are... We have some pages with lots of data pushed to Gon, like ~1Mb JSON on some pages.
We've discovered that enormous amount of server response time was spent in Gon::Base.render_data. We use :snake_case hash keys in our code and let Gon to camelize them. Surprisingly enough most of time was the time spent in camelize(:lower) calls.
Believe it or not, but by introducing caching for camelized keys the mean response time went from 3700ms to 700ms. This is more than 5x improvement!. Memory consumption has also improved dramatically, because lots of String objects were allocated by key.to_s and camelize(:lower) calls. For our ~1Mb JSON this is like 50 unique key names and about 50K calls to camelize them over and over again.
I'm not sure if this is the right place to introduce keys cache in Gon, or should this be in RequestStore, but I'm happy to discuss other options.
I've also done some synthetic benchmarks for Gon::Base.render_data(camel_case: true, camel_depth: :recursive) with the following results:
5 objects with 5 keys: ~ 2.3x faster with cache
5000 objects with 5 keys: ~ 3.3x faster with cache
With lots of data
key.to_s
andcamelize(:lower)
can be a bottleneck.Probably Gon was never intended for such use case, but here we are... We have some pages with lots of data pushed to Gon, like ~1Mb JSON on some pages.
We've discovered that enormous amount of server response time was spent in
Gon::Base.render_data
. We use:snake_case
hash keys in our code and let Gon to camelize them. Surprisingly enough most of time was the time spent incamelize(:lower)
calls.Believe it or not, but by introducing caching for camelized keys the mean response time went from 3700ms to 700ms. This is more than 5x improvement!. Memory consumption has also improved dramatically, because lots of String objects were allocated by
key.to_s
andcamelize(:lower)
calls. For our ~1Mb JSON this is like 50 unique key names and about 50K calls to camelize them over and over again.I'm not sure if this is the right place to introduce keys cache in Gon, or should this be in
RequestStore
, but I'm happy to discuss other options.I've also done some synthetic benchmarks for
Gon::Base.render_data(camel_case: true, camel_depth: :recursive)
with the following results: 5 objects with 5 keys: ~ 2.3x faster with cache 5000 objects with 5 keys: ~ 3.3x faster with cache