1
votes

Objectify is Google's API/service for storing Java objects in the Google data store. At first, my operations used to be fast (low tens of milliseconds). Now, they have become slow (400-600 ms).

Objectify also turns one operation into multiple operations, e.g. a query looks up the entity ids in an index and then retrieves some entities from memcache and others from the data store. There are annotations on the fields that affect how many operations are created. There are potentially a lot of places where something could go wrong for performance.

How can I get insight into what Objectify actually does both to improve the performance and reduce the billing (by triggering less and more efficient operations)?

I've looked at the Objectify documentation and searched the web extensively. I haven't been able to find a way to diagnose Objectify queries.

1
Havae you tried do the same query using low Datastore API? This way you can identify if the slowest part is the Datastore itself or the Objectify framework - Deviling Master
What operations are you performing? Are you pulling back all entities? If nothing changed then perhaps data size changed? - Robert
I haven't learned the low Datastore API yet. I'm pulling back the whole entity. What I can see has changed are the number of entities in the store. Doesn't an index use a hash, which shouldn't get slower with more indexed entities? - Thomas Fischer

1 Answers

0
votes

Look at the stackdriver analysis of GAE RPC calls to see what's going on under the covers. It'll give you a list of the raw operations.

There really aren't that many non-obvious places where things can go wrong for performance. Hybrid queries (turning a query into a keys-only query followed by a batch get) only apply to @Cache entities. The philosophy is simple - if it's efficient to cache your entities, it's probably efficient to use the cache as much as possible. If you're unsure, eliminate @Cache.

Other than that, Objectify just translates low level Entity objects into POJOs. It's reasonably efficient at this, but you can certainly construct pathological cases. Watch out for long and expensive lifecycle methods (@OnLoad and friends). Nesting lists of lists of lists etc can easily create O(N^3) operations. But these should be obvious when you create them. Especially if you use @Load on Ref<?> objects. Loads aren't free.