Skip to content

Instantly share code, notes, and snippets.

@jpsim
Last active August 29, 2015 14:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jpsim/038a0dfd81267d7e2cbe to your computer and use it in GitHub Desktop.
Save jpsim/038a0dfd81267d7e2cbe to your computer and use it in GitHub Desktop.
RealmStringsBenchmarks
#import <Objective-LevelDB/LevelDB.h>
#include <mach/mach_time.h>
#include <stdint.h>
NSString *randomString(NSUInteger length) {
NSMutableString *string = [NSMutableString stringWithCapacity:length];
for (int i = 0; i < length; i++) {
[string appendFormat:@"%C", (unichar)('a' + arc4random_uniform(25))];
}
return string;
}
void benchmarkLevelDB(void) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.ldb"];
[[NSFileManager defaultManager] removeItemAtPath:dbPath error:nil];
NSUInteger numberOfObjects = 30000; // 30,000
NSMutableArray *randomStrings = [NSMutableArray arrayWithCapacity:numberOfObjects * 9];
NSInteger stringLength = 10;
for (NSInteger i = 0; i < numberOfObjects * 9; i++) {
[randomStrings addObject:randomString(stringLength)];
}
const uint64_t startTime = mach_absolute_time();
// Create 30k LevelDB objects
// Precomputes random strings
// Benchmark: 73.6s on iPhone 5 (73.76, 73.63, 74.01, 73.26)
LevelDB *ldb = [LevelDB databaseInLibraryWithName:@"test.ldb"];
for (NSInteger i = 0; i < numberOfObjects; i++) {
NSArray *subArray = [randomStrings subarrayWithRange:NSMakeRange(i * 9, 9)];
for (NSInteger j = 0; j < 9; j++) {
NSString *ldbKey = [NSString stringWithFormat:@"%ld.%ld", (long)i, (long)j];
[ldb setObject:subArray[j] forKey:ldbKey];
}
}
const uint64_t endTime = mach_absolute_time();
const uint64_t elapsedMTU = endTime - startTime;
// Get information for converting from MTU to nanoseconds
mach_timebase_info_data_t info;
mach_timebase_info(&info);
// Get elapsed time in nanoseconds
const double elapsedNS = (double)elapsedMTU * (double)info.numer / (double)info.denom;
NSLog(@"adding %lu objects to LevelDB took %.2f seconds", (unsigned long)numberOfObjects, elapsedNS / 1000000000.0f);
}
Just a quick performance comparison between LevelDB and Realm. Benchmark inserted 30k objects with 9 string properties each, with random strings.
Realm was **3.7 seconds** on average.
LevelDB was **73.6 seconds** on average.
#include <mach/mach_time.h>
#include <stdint.h>
#import <Realm/Realm.h>
@interface ANISampleRealmModel : RLMObject
@property (nonatomic, copy) NSString *testString1;
@property (nonatomic, copy) NSString *testString2;
@property (nonatomic, copy) NSString *testString3;
@property (nonatomic, copy) NSString *testString4;
@property (nonatomic, copy) NSString *testString5;
@property (nonatomic, copy) NSString *testString6;
@property (nonatomic, copy) NSString *testString7;
@property (nonatomic, copy) NSString *testString8;
@property (nonatomic, copy) NSString *testString9;
@property (nonatomic, assign) NSInteger testInteger;
@end
@implementation ANISampleRealmModel
@end
NSString *randomString(NSUInteger length) {
NSMutableString *string = [NSMutableString stringWithCapacity:length];
for (int i = 0; i < length; i++) {
[string appendFormat:@"%C", (unichar)('a' + arc4random_uniform(25))];
}
return string;
}
NSArray *generateRandomRealmObjects(NSInteger count) { // in this case: 30,000
NSMutableArray *objects = [NSMutableArray arrayWithCapacity:count];
NSInteger stringLength = 10;
for (NSInteger i = 0; i < count; i++) {
ANISampleRealmModel *model = [[ANISampleRealmModel alloc] init];
model.testString1 = randomString(stringLength);
model.testString2 = randomString(stringLength);
model.testString3 = randomString(stringLength);
model.testString4 = randomString(stringLength);
model.testString5 = randomString(stringLength);
model.testString6 = randomString(stringLength);
model.testString7 = randomString(stringLength);
model.testString8 = randomString(stringLength);
model.testString9 = randomString(stringLength);
[objects addObject:model];
}
return objects.copy;
}
void benchmarkRealm(void) {
[[NSFileManager defaultManager] removeItemAtPath:[[RLMRealm defaultRealm] path] error:nil];
NSUInteger approachType = 0; // 0 == slow, 1 == fast
NSUInteger numberOfObjects = 30000; // 30,000
NSMutableArray *randomStrings = [NSMutableArray arrayWithCapacity:numberOfObjects * 9];
NSInteger stringLength = 10;
for (NSInteger i = 0; i < numberOfObjects * 9; i++) {
[randomStrings addObject:randomString(stringLength)];
}
const uint64_t startTime = mach_absolute_time();
RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
if (approachType == 0) {
// Approach where Realm objects are added one by one to an NSMutableArray
// and then that NSMutableArray is iterated over one by one to add each Realm object
// to the realm
// Benchmark: 20 seconds on iPhone 5 (19.67, 20.01, 19.71, 19.87, 20.99, 20.41)
NSArray *realmObjects = generateRandomRealmObjects(numberOfObjects);
[realmObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[realm addObject:obj];
}];
} else {
// Approach where random strings are pre-computed and
// Realm objects are created and added directly to the realm, never copied
// Benchmark: 3.7 seconds on iPhone 5 (3.35, 3.71, 3.93, 3.65, 3.77, 3.74)
for (NSInteger i = 0; i < numberOfObjects; i++) {
NSArray *subArray = [randomStrings subarrayWithRange:NSMakeRange(i * 9, 9)];
ANISampleRealmModel *model = [[ANISampleRealmModel alloc] init];
model.testString1 = subArray[0];
model.testString2 = subArray[1];
model.testString3 = subArray[2];
model.testString4 = subArray[3];
model.testString5 = subArray[4];
model.testString6 = subArray[5];
model.testString7 = subArray[6];
model.testString8 = subArray[7];
model.testString9 = subArray[8];
[realm addObject:model];
}
}
[realm commitWriteTransaction];
const uint64_t endTime = mach_absolute_time();
const uint64_t elapsedMTU = endTime - startTime;
// Get information for converting from MTU to nanoseconds
mach_timebase_info_data_t info;
mach_timebase_info(&info);
// Get elapsed time in nanoseconds
const double elapsedNS = (double)elapsedMTU * (double)info.numer / (double)info.denom;
NSLog(@"adding %lu objects to the realm took %.2f seconds", (unsigned long)numberOfObjects, elapsedNS / 1000000000.0f);
}
@levey
Copy link

levey commented Jan 16, 2015

You haven't use batch write for LevelDB, it's unfair!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment