Performance Issue Help - NSCache CBLModels?

50 views
Skip to first unread message

Ragu Vijaykumar

unread,
May 4, 2014, 7:10:41 AM5/4/14
to mobile-c...@googlegroups.com
I've been hitting a performance issue that I'm not sure how to fix exactly. I have a lot of large read-only documents that I'm mapping out as objects with id<CBLJSONEncoding>. Usually, I use queries and get the row.document, and then make my CBLModels, and then access the models properties, which are heavily nested CBLJSONEncoding classes. The creation of these models is expensive as I've found through my debugging, and they are constantly being destroyed since I'm using getters only for local information.

From what I've seen in the source for Couchbase, it seems that CBLDocument only stores a weak pointer to the CBLModel, and only CBLModels which are changed and set the needsSave flag are prevented from being dealloc'd as they are added to an unsavedMutableSet. 

I was wondering if there might be any bad side-effects if I were to create an NSCache for my read-only CBLModels? 

In particular, I'm still not sure how CBLDocuments are deallocated and whether this would impact my pre-existing CBLModels. I see that the documents are added to a CBLCache, but how are they checked to see if a models that wraps around them have the unsaved properties when the cache wants to clear them? I looked around for calls to document.modelObject, but didn't find much.

Any insights into this would be greatly appreciated.

Cheers,
Ragu

Ragu Vijaykumar

unread,
May 4, 2014, 8:35:38 AM5/4/14
to mobile-c...@googlegroups.com
Actually, I think I see the answer to my second quesiton, which is that the models have strong pointers to the CBLDocuments, so as long as they aren't dealloc'd, the documents won't be evicted from the cache. I hope that thinking is right. Given that, it seems that an NSCache of CBLModels shouldn't cause problems, right?

Jens Alfke

unread,
May 4, 2014, 2:32:38 PM5/4/14
to mobile-c...@googlegroups.com

On May 4, 2014, at 4:10 AM, Ragu Vijaykumar <ra...@scrxpt.com> wrote:

I was wondering if there might be any bad side-effects if I were to create an NSCache for my read-only CBLModels? 

That sounds reasonable. I don’t think there would be any bad side effects, other than increased memory usage of course. CBLDatabase does something similar, keeping an NSMutableSet of models with unsaved changes so they won’t be dealloced before they can be saved.

the models have strong pointers to the CBLDocuments, so as long as they aren't dealloc'd, the documents won't be evicted from the cache.

Right.

—Jens

Ragu Vijaykumar

unread,
May 4, 2014, 6:28:49 PM5/4/14
to mobile-c...@googlegroups.com
Thanks for the input. One follow-up question that I've seen one other ask in the Github issues, but not seen answered. Why are cached property values of CBLModels discarded on save?

One of the performance issues I've been running into is that I periodically save my CBLModels when my user leaves different view controllers. However, this invalidates all the currently accessed values for properties, and when I call the getters on these properties, recreating their values from the document is expensive. Is there a workaround for this?

Cheers,
Ragu

Ragu Vijaykumar

unread,
May 5, 2014, 2:48:06 AM5/5/14
to mobile-c...@googlegroups.com
From what I gather, it seems that this block of code is what invalidates all the current cached values of the getters during a save. 

- (void) didSave {

 

   
if (!_needsSave || (!_changedNames && !_changedAttachments))

       
return;

    _isNew
= NO;

    _properties
= nil; // This line of code invalidates all currently accessed values for model getters.

    _changedNames
= nil;

    _changedAttachments
= nil;

   
self.needsSave = NO;

}

Do you think it would be unreasonable to comment out this one line of code, or will this cause a butterfly effect in the CBLModel code with foreseen consequences?

I was worried that it might screw up something with upstream changes being pushed down to the device, but I noticed that _properties is invalidated in that block of code anyways, and see that is necessary so the code will start using the new data and not stale data.

// Respond to an external change (likely from sync). This is called by my CBLDocument.

 

- (void) CBLDocument: (CBLDocument*)doc didChange:(CBLDatabaseChange*)change {

   
...    

   
// Remove unchanged cached values in _properties:

   
if (_changedNames && _properties) {

       
NSMutableSet* removeKeys = [NSMutableSet setWithArray: [_properties allKeys]];

       
[removeKeys minusSet: _changedNames];

       
[_properties removeObjectsForKeys: removeKeys.allObjects];    // Only remove cached property values that haven't changed

   
} else {

        _properties
= nil;     // In the case of only getter cached values, delete all cached values so they will be reloaded from the document

   
}

...

}


I really appreciate all your help and this library has been a fantastic addition to my app.

Cheers,
Ragu

Jens Alfke

unread,
May 5, 2014, 11:04:11 AM5/5/14
to mobile-c...@googlegroups.com
On May 4, 2014, at 3:28 PM, Ragu Vijaykumar <ra...@scrxpt.com> wrote:

Thanks for the input. One follow-up question that I've seen one other ask in the Github issues, but not seen answered. Why are cached property values of CBLModels discarded on save?

To free up memory, IIRC.

One of the performance issues I've been running into is that I periodically save my CBLModels when my user leaves different view controllers. However, this invalidates all the currently accessed values for properties, and when I call the getters on these properties, recreating their values from the document is expensive. 

What sort of properties are they?

—Jens

Jens Alfke

unread,
May 5, 2014, 11:07:01 AM5/5/14
to mobile-c...@googlegroups.com

On May 4, 2014, at 11:48 PM, Ragu Vijaykumar <ra...@scrxpt.com> wrote:

Do you think it would be unreasonable to comment out this one line of code, or will this cause a butterfly effect in the CBLModel code with foreseen consequences?

I think it should be OK. You can run the model unit tests to make sure (run with command-line arg “Test_API_Model”.)

—Jens

Ragu Vijaykumar

unread,
May 5, 2014, 11:17:57 AM5/5/14
to mobile-c...@googlegroups.com
Sorry, I've never run a unit test on CBL before. Do I just add the "Test_API_Model" to the argument list in the Continuous iOS scheme in CouchbaseLite.xcodeproj, and build? What should I expect to see?

Thanks.

Ragu Vijaykumar

unread,
May 5, 2014, 11:23:14 AM5/5/14
to mobile-c...@googlegroups.com
Never mind, I figured out that I needed to run it with the empty ios model. All 7 tests passed!

Also, I implemented the NSCache for CBLModels and it significantly improved performance of my app! Thanks.
Reply all
Reply to author
Forward
0 new messages