Row filtering in the ORM

For a while now we’ve had an unwanted behavior in our Solution Engine product. The larger the on-device database got, the longer the app took to load. To the point that some devices in the field were taking nearly 5 minutes to boot (up from roughly 1 minute under normal circumstances). This morning we decided to go figure out what was causing it.

First, we pulled a database file from a device that is slow to boot. It turns out that the database was largely empty except to about 50k rows in a log table where we record general boot/run information on the device for diagnostics.

At startup the logging service pulls the last hour of log information and outputs it to the console, which has proven to be very helpful in diagnosing bad behaviors and crashes. Looking at the code that gets that last hour of data, we saw the following:

Now let’s look at this call in the context of having 50k rows in the table. What it effectively says is “Retrieve every row from the SFTraceEntry Table, hydrate a SFTraceEntry class for each row, then walk through that entire list checking the TimeStamp field. If the TimeStamp is less that an hour old, then copy that item to a new list and when you’re done, return the filtered list.” Ouch. This falls into the category of “using a tool wrong”. The ORM supports FilterConditions that, depending on the backing store, will attempt to decipher into a SQL statement, index walk or something more efficient than “return all rows”. In this case, the change was as simple as this: