Print Page | Close Window

Memory issue iOS

Printed From: IdeaBlade
Category: Breeze
Forum Name: Community Forum
Forum Discription: Build rich JavaScript apps using techniques you already know
Printed Date: 30-Sep-2020 at 10:24am

Topic: Memory issue iOS
Posted By: Orizz
Subject: Memory issue iOS
Date Posted: 15-Oct-2012 at 2:43pm
Hi there,

Been trying out Breeze today and overall its exactly what I'm looking for since upshot left the room...

I'm downloading around 5000 entities to my client and storing them in localstorage in an array for offline use, 5000 will always be the maximum it could ever be. In all the browsers it works fine and runs fluidly, but in iOS Safari (iPhone + iPad), the browser crashes after around 2500 of these entities are loaded into memory.

Since it works in desktop browsers fine it obviously a memory issue with iOS, its been documented online already, maybe there is a way to have these items stripped down a bit and not as fully functioning entities? I would like the ability to batch save, work offline and handle changes but maybe this is a little too much to hope for at the moment?

If anyone has any thoughts let me know


Posted By: jtraband
Date Posted: 15-Oct-2012 at 4:52pm
Ok, I think there are a few different routes you could go down

1) make each of the entities "smaller"
This would mean 'shrinking' the surface of your entities on the server. Probably not terribly feasible for a lot of apps.  But we are also looking at mechanisms for controlling serialization and allowing the developer to expose only a subset of the server model to the client.  
2) have some of the most voluminous queries return projections instead of full entities.
Projections are queries using the "" method.  For example
var query = EntityQuery("Orders")
.where("Customer.CompanyName", "startsWith", "C")        
.select("Customer.CompanyName, Customer.Region, OrderDate, OrderDetails");

The advantage of projections is that any projected property that is not an entity or an entity collection is not wrapped by breeze in an "observable" wrapper (knockout, backbone etc.).  These wrappers can take up memory especially if you have a lot of them; this combined with the idea that you are only bringing down a subset of each entity can make your app's memory footprint much smaller.  In the query above "Customer.CompanyName", "Customer.Region" and "OrderDate" will all be brought to the client as "simple" scalar values instead of entities, whereas "OrderDetails" will be brought in as an array of  breeze 'OrderDetail' entities each wrapped in its own "observable" wrapper.

3) Avoid query.expand operations
- these are great for caching data, but do tend to have large payloads.

4) Break the query up into several smaller queries. 
Ok, I'm just guessing here because I do not know where the IOS memory limits that you are hitting are but it is conceivable that the issue is not total memory use, but rather a memory spike that occurs when deserializing the entities after a large query.  In this case, creating several smaller queries and executing them in series might work.

Hope this helps!


Posted By: Orizz
Date Posted: 16-Oct-2012 at 4:20am
Thanks for your reply, I took your advice and projected the 2 variables I needed and now store these in an array. Is there a way once a search has been performed and an array item selected I can give the item back (temporarily) its entity status so I can perform operations, once this is achieved it can become a standard array item ready for searching again.

I noticed the items all have a $id, so is it something to do with this?

Many thanks for your time

Posted By: jtraband
Date Posted: 16-Oct-2012 at 9:46am
Not really, the problem is that a breeze "entity" is defined by its collection of properties, and with your 'projected' entity many of these properties will not be populated.  This will cause problems if you were to try, for example, to modify and save it. 

What you can do fairly easily if you have projected the field or fields that make up an entities key value, is to construct a new query for the entity using the key value or values and "requery" just those entities that you want to work with at a point in time.  These entities will be brought into the cache and may be modified and then saved.  If you want to keep the cache size down, you can then detach them and query for the next set of entities that you want to work with.

Does this make sense?

Posted By: Marcel
Date Posted: 20-Oct-2012 at 2:25am
The real question if ofcourse : why would you need 5000 entities on the client in the first place.
I honestly can't imagine an application where you would need 5000 entities.
Even in a normal desktop application 2-tier or 3-tier i hardly ever needed so many, or if i did (for clientside datamining for example) i made sure the user had to make some kind of pre-selection to limit the data in the first place.

Posted By: Orizz
Date Posted: 20-Oct-2012 at 7:02am
It's a guest list system administered through an iPad. Normally around 2000 guests, but making sure I can deal with more. If the wifi/data connection drops I need to be able to still search the backend store for guests and admit them, and then sync changes back when the connection restores. 

I've got around the issue by turning off the default Knockout side of things and only applying the observable functionality after a search is performed. The Breeze side of things is quick and easy even supporting 10,000 entities offline in the browsers localStorage.

jtraband - Thanks for your help

Print Page | Close Window