Skip to content

Commit e230dbc

Browse files
committed
Setting the "pragma journal_size_limit" to zero by default. This should result in the WAL file staying much smaller during continued heavy use of the database.
1 parent 944076b commit e230dbc

File tree

5 files changed

+108
-10
lines changed

5 files changed

+108
-10
lines changed

Testing/Xcode-mobile/YapDatabase.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@
888888
ORGANIZATIONNAME = "Robbie Hanson";
889889
TargetAttributes = {
890890
DCAE51E61673FE2600395076 = {
891-
DevelopmentTeam = 939WR99F3W;
891+
DevelopmentTeam = 4D98PK6HWS;
892892
};
893893
};
894894
};

Testing/Xcode-mobile/YapDatabase/AppDelegate.m

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,33 +73,74 @@ - (void)yapDatabaseModified:(NSNotification *)notification
7373
#pragma mark General Debugging
7474
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7575

76+
- (NSString *)randomLetters:(NSUInteger)length
77+
{
78+
NSString *alphabet = @"abcdefghijklmnopqrstuvwxyz";
79+
NSUInteger alphabetLength = [alphabet length];
80+
81+
NSMutableString *result = [NSMutableString stringWithCapacity:length];
82+
83+
NSUInteger i;
84+
for (i = 0; i < length; i++)
85+
{
86+
uint32_t randomIndex = arc4random_uniform((uint32_t)alphabetLength);
87+
unichar c = [alphabet characterAtIndex:(NSUInteger)randomIndex];
88+
89+
[result appendFormat:@"%C", c];
90+
}
91+
92+
return result;
93+
}
94+
7695
- (void)debug
7796
{
7897
NSLog(@"Starting debug...");
7998

8099
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
100+
NSLog(@"databasePath: %@", databasePath);
81101

82102
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:nil];
83103

84104
database = [[YapDatabase alloc] initWithPath:databasePath];
85-
// database.connectionPoolLifetime = 15;
86105

87-
databaseConnection = [database newConnection];
106+
// Fill up the database with stuff
88107

89108
[[database newConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
90109

91-
[transaction setObject:@"value" forKey:@"key" inCollection:nil];
110+
for (int i = 0; i < 1500; i++)
111+
{
112+
NSString *key = [NSString stringWithFormat:@"%d", i];
113+
114+
[transaction setObject:[self randomLetters:100] forKey:key inCollection:nil];
115+
}
92116
}];
93117

94-
[NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(debugTimer:) userInfo:nil repeats:YES];
95-
}
96-
97-
- (void)debugTimer:(NSTimer *)timer
98-
{
118+
// Delete a bunch of stuff (to make more pages in the WAL)
119+
99120
[[database newConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
100121

101-
[transaction setObject:@"value" forKey:@"key" inCollection:nil];
122+
for (int i = 0; i < 1000; i+=2)
123+
{
124+
NSString *key = [NSString stringWithFormat:@"%d", i];
125+
126+
[transaction removeObjectForKey:key inCollection:nil];
127+
}
102128
}];
129+
130+
NSLog(@"database WAL should be fairly big now...");
131+
132+
// This next change should reset the WAL file size (to something much smaller)
133+
134+
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
135+
dispatch_after(when, dispatch_get_main_queue(), ^{
136+
137+
NSLog(@"This change should reset the WAL file size to something much smaller...");
138+
139+
[[database newConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
140+
141+
[transaction setObject:@"bar" forKey:@"foo" inCollection:nil];
142+
}];
143+
});
103144
}
104145

105146
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

YapDatabase/YapDatabase.m

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,21 @@ - (BOOL)configureDatabase:(BOOL)isNewDatabaseFile
572572
// This isn't critical, so we can continue.
573573
}
574574

575+
// Set journal_size_imit.
576+
//
577+
// We only need to do set this pragma for THIS connection,
578+
// because it is the only connection that performs checkpoints.
579+
580+
NSString *stmt =
581+
[NSString stringWithFormat:@"PRAGMA journal_size_limit = %ld;", (long)options.pragmaJournalSizeLimit];
582+
583+
status = sqlite3_exec(db, [stmt UTF8String], NULL, NULL, NULL);
584+
if (status != SQLITE_OK)
585+
{
586+
YDBLogError(@"Error setting PRAGMA journal_size_limit: %d %s", status, sqlite3_errmsg(db));
587+
// This isn't critical, so we can continue.
588+
}
589+
575590
// Disable autocheckpointing.
576591
//
577592
// YapDatabase has its own optimized checkpointing algorithm built-in.
@@ -2345,6 +2360,8 @@ - (void)noteCommittedChanges:(NSDictionary *)changeset fromConnection:(YapDataba
23452360
**/
23462361
- (void)asyncCheckpoint:(uint64_t)maxCheckpointableSnapshot
23472362
{
2363+
static BOOL const PRINT_WAL_SIZE = NO;
2364+
23482365
__weak YapDatabase *weakSelf = self;
23492366

23502367
dispatch_async(checkpointQueue, ^{ @autoreleasepool {
@@ -2354,6 +2371,18 @@ - (void)asyncCheckpoint:(uint64_t)maxCheckpointableSnapshot
23542371

23552372
YDBLogVerbose(@"Checkpointing up to snapshot %llu", maxCheckpointableSnapshot);
23562373

2374+
if (YDB_LOG_VERBOSE && PRINT_WAL_SIZE)
2375+
{
2376+
NSString *walFilePath = [strongSelf.databasePath stringByAppendingString:@"-wal"];
2377+
2378+
NSDictionary *walAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:walFilePath error:NULL];
2379+
unsigned long long walFileSize = [walAttr fileSize];
2380+
2381+
YDBLogVerbose(@"Pre-checkpoint file size: %@",
2382+
[NSByteCountFormatter stringFromByteCount:(long long)walFileSize
2383+
countStyle:NSByteCountFormatterCountStyleFile]);
2384+
}
2385+
23572386
// We're ready to checkpoint more frames.
23582387
//
23592388
// So we're going to execute a passive checkpoint.
@@ -2417,6 +2446,18 @@ - (void)asyncCheckpoint:(uint64_t)maxCheckpointableSnapshot
24172446
}
24182447
});
24192448
}
2449+
2450+
if (YDB_LOG_VERBOSE && PRINT_WAL_SIZE)
2451+
{
2452+
NSString *walFilePath = [strongSelf.databasePath stringByAppendingString:@"-wal"];
2453+
2454+
NSDictionary *walAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:walFilePath error:NULL];
2455+
unsigned long long walFileSize = [walAttr fileSize];
2456+
2457+
YDBLogVerbose(@"Post-checkpoint file size: %@",
2458+
[NSByteCountFormatter stringFromByteCount:(long long)walFileSize
2459+
countStyle:NSByteCountFormatterCountStyleFile]);
2460+
}
24202461
}});
24212462
}
24222463

YapDatabase/YapDatabaseOptions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ typedef NSString* (^YapDatabaseOptionsPassphraseBlock)(void);
6363
**/
6464
@property (nonatomic, assign, readwrite) YapDatabasePragmaSynchronous pragmaSynchronous;
6565

66+
/**
67+
* Allows you to configure the sqlite "PRAGMA journal_size_limit" option.
68+
*
69+
* For more information, see the sqlite docs:
70+
* http://www.sqlite.org/pragma.html#pragma_journal_size_limit
71+
*
72+
* Note that YapDatabase uses sqlite in WAL mode.
73+
*
74+
* The default value is zero,
75+
* meaning that every checkpoint will reduce the WAL file to its minimum size (if possible).
76+
**/
77+
@property (nonatomic, assign, readwrite) NSInteger pragmaJournalSizeLimit;
78+
6679
#ifdef SQLITE_HAS_CODEC
6780
/**
6881
* Set a block here that returns the passphrase for the SQLCipher

YapDatabase/YapDatabaseOptions.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ @implementation YapDatabaseOptions
1616

1717
@synthesize corruptAction = corruptAction;
1818
@synthesize pragmaSynchronous = pragmaSynchronous;
19+
@synthesize pragmaJournalSizeLimit = pragmaJournalSizeLimit;
1920

2021
- (id)init
2122
{
2223
if ((self = [super init]))
2324
{
2425
corruptAction = YapDatabaseCorruptAction_Rename;
2526
pragmaSynchronous = YapDatabasePragmaSynchronous_Full;
27+
pragmaJournalSizeLimit = 0;
2628
}
2729
return self;
2830
}
@@ -32,6 +34,7 @@ - (id)copyWithZone:(NSZone *)zone
3234
YapDatabaseOptions *copy = [[[self class] alloc] init];
3335
copy->corruptAction = corruptAction;
3436
copy->pragmaSynchronous = pragmaSynchronous;
37+
copy->pragmaJournalSizeLimit = pragmaJournalSizeLimit;
3538
#ifdef SQLITE_HAS_CODEC
3639
copy.passphraseBlock = _passphraseBlock;
3740
#endif

0 commit comments

Comments
 (0)