Last active
August 29, 2015 14:04
-
-
Save jpsim/038a0dfd81267d7e2cbe to your computer and use it in GitHub Desktop.
RealmStringsBenchmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You haven't use batch write for LevelDB, it's unfair!