We've been using Spray for a while now and have a few services running but I've been running some profiling as we'd like to see if we can maximise performance. I've long been concerned that our pattern is to build objects, then store them in our cache as a JSON string, then return these from the cache by unmarshalling the JSON string to case classes then preparing the response and rendering JSON as the HTTP response body. It felt, intuitively, that excessive marshalling/unmarshalling is probably a bad thing although the performance testing I've been running with YourKit/Gatling suggests that our code spends most of its time with the Parboiled parserunner. Though our pipeline can be quite complex if we don't have the object in our cache:
user makes request
service checks cache
service makes upstream call for JSON data
service unmarshalls JSON data and maps this to native case classes
service marshalls native case classes to JSON string
service renders native case classes to JSON string in HTTP response
Or if we do have the object:
user makes request
service checks cache
service unmarshalls JSON string from cache to native case classes
service renders native case classes to JSON string in HTTP response
So even a request to the cache gets a string and turns it into objects then back into a string...could this be short-cut?
Obviously different apps will vary but our API dialect is JSON so I'm wondering if there was any optimisation we could do. I did consider building the JSON and inserting it into the cache outside of an HTTP request cycle and then just return the string from the cache direct as the body of an HTTP request. The only wrinkle is that we unmarshall the JSON string to do things like add single items to collections etc. It makes sense—logically—to unmarshall three strings to three objects, add them to a collection then marshall this collection to JSON. Makes sense logically, in terms of code, but not necessarily in terms of performance.
It's a bit of an open question really. We'd like to boost our req/sec but should this be done simply by adding more resources to scale out rather than tweak code?
Also, is there a compelling reason to migrate to Akka from Spray for this purpose?
Thanks,
Beth