Quick question regarding "inTransaction"

22 views
Skip to first unread message

Alexander Selling

unread,
Oct 28, 2014, 6:10:09 AM10/28/14
to mobile-c...@googlegroups.com

            CBLDatabase *database = [[CBLManager sharedInstance] databaseNamed:@"test" error:nil];


            CBLView *v1 = [database viewNamed:viewName];


            [v1 setMapBlock:MAPBLOCK({emit (nil, doc[kDocumentID]);}) version:@"1.0"];


            CBLQuery *q1 = [v1 createQuery];


            CBLQueryEnumerator *enumerator = [q1 run:nil];


            NSMutableArray *documentIDs = [NSMutableArray array];


           


            CBLQueryRow *row = nil;


            while ((row = [enumerator nextRow]) != nil)


            {


                id documentID = [row value];


                [documentIDs addObject:documentID];


            }


           


            double beforeSingleFetch = [NSDate timeIntervalSinceReferenceDate];


            NSMutableArray *singleFetch = [NSMutableArray array];


            for (NSString *documentID in documentIDs)


            {


                CBLDocument *singleFetchDocument = [database documentWithID:documentID];


                [singleFetch addObject:singleFetchDocument];


            }


            double afterSingleFetch = [NSDate timeIntervalSinceReferenceDate];


            double singleFetchDuration = afterSingleFetch - beforeSingleFetch;


           


            double beforeBulkFetch = [NSDate timeIntervalSinceReferenceDate];


            NSMutableArray *bulkFetch = [NSMutableArray array];


            [database inTransaction:^BOOL{


               


                for (NSString *documentID in documentIDs)


                {


                    CBLDocument *bulkFetchDocument = [database documentWithID:documentID];


                    [bulkFetch addObject:bulkFetchDocument];


                }


                return YES;


            }];

            double afterBulkFetch = [NSDate timeIntervalSinceReferenceDate];


            double bulkFetchDuration = afterBulkFetch - beforeBulkFetch;


           


            NSAssert(singleFetchDuration > bulkFetchDuration, @"A bulk fetch should be faster!");


I understand that the test is super naive, there's caching involved that would render the test useless. However, does cbl do bulk fetches? Is that what a transaction is for in this case?

Jens Alfke

unread,
Oct 28, 2014, 1:37:47 PM10/28/14
to mobile-c...@googlegroups.com

On Oct 28, 2014, at 3:10 AM, Alexander Selling <alexande...@gmail.com> wrote:

I understand that the test is super naive, there's caching involved that would render the test useless. However, does cbl do bulk fetches? Is that what a transaction is for in this case?

No — transactions only affect writes, not reads. The major effect of -inTransaction: is to start a SQLite transaction before calling the block, and end the transaction after the block. This groups all the writes into a single transaction, whereas by default SQLite treats every INSERT/UPDATE/DELETE as its own transaction.

The performance benefit is because committing a transaction to disk is expensive. To meet its durability guarantees, SQLite has to flush all of its writes to the kernel and then force the filesystem to flush all those writes to the physical storage medium, not returning until the writes are complete. For reasons involving arcane details of the way disk controllers work, this can take anywhere up to hundreds of milliseconds. Not a cost you want to incur many times in a row if you're saving a lot of documents!

(When we switch to ForestDB the details will differ, but ForestDB also has transactions. Although from what I can tell, it has a lot less overhead when committing a transaction. Not sure why.)

But back to what you actually asked about :) Transactions have no effect on read performance.

—Jens
Reply all
Reply to author
Forward
0 new messages