opt copying from NSData to MMBuffer

This commit is contained in:
guoling
2020-01-02 19:04:12 +08:00
parent ebdac3eee9
commit 620933d9ea
9 changed files with 175 additions and 14 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
CB95641623AB2E9100ACCD39 /* MMKV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB9563F223AB2E9100ACCD39 /* MMKV.cpp */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
CB95641723AB2E9100ACCD39 /* MiniPBCoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB9563F523AB2E9100ACCD39 /* MiniPBCoder.cpp */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
CB95641823AB2E9100ACCD39 /* ThreadLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB9563F723AB2E9100ACCD39 /* ThreadLock.cpp */; };
CB95641923AB2E9100ACCD39 /* MMBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB9563F823AB2E9100ACCD39 /* MMBuffer.cpp */; };
CB95641923AB2E9100ACCD39 /* MMBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB9563F823AB2E9100ACCD39 /* MMBuffer.cpp */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
CB95641A23AB2E9100ACCD39 /* CodedInputData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB9563F923AB2E9100ACCD39 /* CodedInputData.cpp */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
CB95641B23AB2E9100ACCD39 /* openssl_cfb128.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB95640123AB2E9100ACCD39 /* openssl_cfb128.cpp */; };
CB95641C23AB2E9100ACCD39 /* openssl_aes_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB95640323AB2E9100ACCD39 /* openssl_aes_core.cpp */; };
+37
View File
@@ -23,6 +23,12 @@
#include <cstring>
#include <utility>
#ifdef MMKV_IOS_OR_MAC
# if __has_feature(objc_arc)
# error This file must be compiled with MRC. Use -fno-objc-arc flag.
# endif
#endif
namespace mmkv {
MMBuffer::MMBuffer(size_t length) : ptr(nullptr), size(length), isNoCopy(MMBufferCopy) {
@@ -38,10 +44,26 @@ MMBuffer::MMBuffer(void *source, size_t length, MMBufferCopyFlag noCopy) : ptr(s
}
}
#ifdef MMKV_IOS_OR_MAC
MMBuffer::MMBuffer(NSData *data, MMBufferCopyFlag noCopy)
: ptr((void *) data.bytes), size(data.length), isNoCopy(noCopy) {
if (isNoCopy == MMBufferCopy) {
m_data = [data retain];
} else {
m_data = data;
}
}
#endif
MMBuffer::MMBuffer(MMBuffer &&other) noexcept : ptr(other.ptr), size(other.size), isNoCopy(other.isNoCopy) {
other.ptr = nullptr;
other.size = 0;
other.isNoCopy = MMBufferCopy;
#ifdef MMKV_IOS_OR_MAC
m_data = other.m_data;
other.m_data = nil;
#endif
}
MMBuffer &MMBuffer::operator=(MMBuffer &&other) noexcept {
@@ -49,10 +71,25 @@ MMBuffer &MMBuffer::operator=(MMBuffer &&other) noexcept {
std::swap(size, other.size);
std::swap(isNoCopy, other.isNoCopy);
#ifdef MMKV_IOS_OR_MAC
std::swap(m_data, other.m_data);
#endif
return *this;
}
MMBuffer::~MMBuffer() {
#ifdef MMKV_IOS_OR_MAC
if (m_data) {
if (isNoCopy == MMBufferCopy) {
[m_data release];
}
m_data = nil;
ptr = nullptr;
return;
}
#endif
if (isNoCopy == MMBufferCopy && ptr) {
free(ptr);
}
+8
View File
@@ -21,6 +21,8 @@
#ifndef MMKV_MMBUFFER_H
#define MMKV_MMBUFFER_H
#include "MMKVPredef.h"
#include <cstdint>
#include <cstdlib>
@@ -36,6 +38,9 @@ private:
void *ptr;
size_t size;
MMBufferCopyFlag isNoCopy;
#ifdef MMKV_IOS_OR_MAC
NSData *m_data = nil;
#endif
public:
void *getPtr() const { return ptr; }
@@ -44,6 +49,9 @@ public:
explicit MMBuffer(size_t length = 0);
MMBuffer(void *source, size_t length, MMBufferCopyFlag noCopy = MMBufferCopy);
#ifdef MMKV_IOS_OR_MAC
explicit MMBuffer(NSData *data, MMBufferCopyFlag noCopy = MMBufferCopy);
#endif
MMBuffer(MMBuffer &&other) noexcept;
MMBuffer &operator=(MMBuffer &&other) noexcept;
+2 -2
View File
@@ -697,7 +697,7 @@ const MMBuffer &MMKV::getDataForKey(MMKVKey_t key) {
if (itr != m_dic.end()) {
return itr->second;
}
static MMBuffer nan(0);
static MMBuffer nan((size_t) 0);
return nan;
}
@@ -733,7 +733,7 @@ bool MMKV::removeDataForKey(MMKVKey_t key) {
m_dic.erase(itr);
m_hasFullWriteback = false;
static MMBuffer nan(0);
static MMBuffer nan((size_t) 0);
return appendDataWithKey(nan, key);
}
+7 -5
View File
@@ -70,9 +70,9 @@ void MMKV::setIsInBackground(bool isInBackground) {
// @finally in C++ stype
template <typename F>
struct FinalAction {
FinalAction(F f) : m_func{f} {}
~FinalAction() { m_func(); }
struct AtExit {
AtExit(F f) : m_func{f} {}
~AtExit() { m_func(); }
private:
F m_func;
@@ -90,7 +90,7 @@ bool MMKV::protectFromBackgroundWriting(size_t size, WriteBlock block) {
//block(m_output);
return false;
} else {
FinalAction cleanup([=] { munlock((void *) ptr, lockDownSize); });
AtExit cleanup([=] { munlock((void *) ptr, lockDownSize); });
try {
block(m_output);
} catch (std::exception &exception) {
@@ -121,7 +121,9 @@ bool MMKV::set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key) {
} else {
/*if ([object conformsToProtocol:@protocol(NSCoding)])*/ {
auto tmp = [NSKeyedArchiver archivedDataWithRootObject:obj];
data = MMBuffer((void *) tmp.bytes, tmp.length);
if (tmp.length > 0) {
data = MMBuffer(tmp);
}
}
}
+2 -2
View File
@@ -83,7 +83,7 @@ void MiniPBCoder::writeRootObject() {
m_outputData->writeRawVarint32(encodeItem->valueSize);
if (encodeItem->valueSize > 0 && encodeItem->value.tmpObjectValue != nullptr) {
auto obj = (__bridge NSData *) encodeItem->value.tmpObjectValue;
MMBuffer buffer((void *) obj.bytes, obj.length, MMBufferNoCopy);
MMBuffer buffer(obj, MMBufferNoCopy);
m_outputData->writeRawData(buffer);
}
break;
@@ -92,7 +92,7 @@ void MiniPBCoder::writeRootObject() {
m_outputData->writeRawVarint32(encodeItem->valueSize);
if (encodeItem->valueSize > 0 && encodeItem->value.objectValue != nullptr) {
auto obj = (__bridge NSData *) encodeItem->value.objectValue;
MMBuffer buffer((void *) obj.bytes, obj.length, MMBufferNoCopy);
MMBuffer buffer(obj, MMBufferNoCopy);
m_outputData->writeRawData(buffer);
}
break;
+1 -1
View File
@@ -83,7 +83,7 @@ public:
return pbcoder.getEncodeData(obj);
} catch (const std::exception &exception) {
MMKVError("%s", exception.what());
return MMBuffer(0);
return MMBuffer((size_t) 0);
}
}
+1 -1
View File
@@ -511,7 +511,7 @@ static BOOL g_hasCalledInitializeMMKV = NO;
} else {
string = mmapID;
}
MMKVInfo("mmapKey: %@", string);
MMKVDebug("mmapKey: %@", string);
return string;
}
+116 -2
View File
@@ -22,6 +22,35 @@
#import "MMKVDemo-Swift.h"
#import <MMKV/MMKV.h>
@interface TestNSArchive : NSObject <NSCoding>
@property(nonatomic, strong) NSString *m_username;
@property(nonatomic, assign) int32_t m_age;
@property(nonatomic, assign) float m_score;
@end
@implementation TestNSArchive
- (id)initWithCoder:(NSCoder *)decoder {
self = [super init];
if (!self) {
return nil;
}
self.m_username = [decoder decodeObjectForKey:@"m_username"];
self.m_age = [decoder decodeInt32ForKey:@"m_age"];
self.m_score = [decoder decodeFloatForKey:@"m_score"];
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.m_username forKey:@"m_username"];
[encoder encodeInteger:self.m_age forKey:@"m_age"];
[encoder encodeFloat:self.m_score forKey:@"m_score"];
}
@end
@interface ViewController () <MMKVHandler>
@end
@@ -29,6 +58,8 @@
NSMutableArray *m_arrStrings;
NSMutableArray *m_arrStrKeys;
NSMutableArray *m_arrIntKeys;
NSMutableArray *m_arrObjKeys;
NSMutableArray *m_arrNSCodingObjs;
int m_loops;
}
@@ -69,6 +100,8 @@
m_arrStrings = [NSMutableArray arrayWithCapacity:m_loops];
m_arrStrKeys = [NSMutableArray arrayWithCapacity:m_loops];
m_arrIntKeys = [NSMutableArray arrayWithCapacity:m_loops];
m_arrObjKeys = [NSMutableArray arrayWithCapacity:m_loops];
m_arrNSCodingObjs = [NSMutableArray arrayWithCapacity:m_loops];
for (size_t index = 0; index < m_loops; index++) {
NSString *str = [NSString stringWithFormat:@"%s-%d", __FILE__, rand()];
[m_arrStrings addObject:str];
@@ -78,6 +111,15 @@
NSString *intKey = [NSString stringWithFormat:@"int-%zu", index];
[m_arrIntKeys addObject:intKey];
/*
NSString *objKey = [NSString stringWithFormat:@"obj-%zu", index];
[m_arrObjKeys addObject:objKey];
TestNSArchive *obj = [[TestNSArchive alloc] init];
obj.m_username = str;
obj.m_age = rand();
obj.m_age = rand() * rand() * 0.5;
[m_arrNSCodingObjs addObject:obj];*/
}
}
@@ -347,6 +389,9 @@
for (size_t index = 0; index < self->m_loops; index++) {
NSString *str = [NSString stringWithFormat:@"%s-%d", __FILE__, rand()];
[self->m_arrStrings addObject:str];
//TestNSArchive *obj = self->m_arrNSCodingObjs[index];
//obj.m_username = str;
}
[self mmkvBaselineTest:self->m_loops];
@@ -365,6 +410,8 @@
[self mmkvBatchReadInt:loops];
[self mmkvBatchWriteString:loops];
[self mmkvBatchReadString:loops];
//[self mmkvBatchWriteObject:loops];
//[self mmkvBatchReadObject:loops];
//[self mmkvBatchDeleteString:loops];
//[[MMKV defaultMMKV] trim];
@@ -447,6 +494,37 @@
}
}
- (void)mmkvBatchWriteObject:(int)loops {
@autoreleasepool {
NSDate *startDate = [NSDate date];
MMKV *mmkv = [MMKV defaultMMKV];
for (int index = 0; index < loops; index++) {
TestNSArchive *obj = m_arrNSCodingObjs[index];
NSString *objKey = m_arrObjKeys[index];
[mmkv setObject:obj forKey:objKey];
}
NSDate *endDate = [NSDate date];
int cost = [endDate timeIntervalSinceDate:startDate] * 1000;
NSLog(@"mmkv write object %d times, cost:%d ms", loops, cost);
}
}
- (void)mmkvBatchReadObject:(int)loops {
@autoreleasepool {
NSDate *startDate = [NSDate date];
MMKV *mmkv = [MMKV defaultMMKV];
for (int index = 0; index < loops; index++) {
NSString *objKey = m_arrObjKeys[index];
[mmkv getObjectOfClass:TestNSArchive.class forKey:objKey];
}
NSDate *endDate = [NSDate date];
int cost = [endDate timeIntervalSinceDate:startDate] * 1000;
NSLog(@"mmkv read object %d times, cost:%d ms", loops, cost);
}
}
#pragma mark - NSUserDefault baseline test
- (void)userDefaultBaselineTest:(int)loops {
@@ -454,6 +532,8 @@
[self userDefaultBatchReadInt:loops];
[self userDefaultBatchWriteString:loops];
[self userDefaultBatchReadString:loops];
//[self userDefaultBatchWriteObject:loops];
//[self userDefaultBatchReadObject:loops];
}
- (void)userDefaultBatchWriteInt:(int)loops {
@@ -465,8 +545,8 @@
NSInteger tmp = rand();
NSString *intKey = m_arrIntKeys[index];
[userdefault setInteger:tmp forKey:intKey];
[userdefault synchronize];
}
[userdefault synchronize];
NSDate *endDate = [NSDate date];
int cost = [endDate timeIntervalSinceDate:startDate] * 1000;
NSLog(@"NSUserDefaults write int %d times, cost:%d ms", loops, cost);
@@ -497,8 +577,8 @@
NSString *str = m_arrStrings[index];
NSString *strKey = m_arrStrKeys[index];
[userdefault setObject:str forKey:strKey];
[userdefault synchronize];
}
[userdefault synchronize];
NSDate *endDate = [NSDate date];
int cost = [endDate timeIntervalSinceDate:startDate] * 1000;
NSLog(@"NSUserDefaults write string %d times, cost:%d ms", loops, cost);
@@ -520,6 +600,40 @@
}
}
- (void)userDefaultBatchWriteObject:(int)loops {
@autoreleasepool {
NSDate *startDate = [NSDate date];
NSUserDefaults *userdefault = [NSUserDefaults standardUserDefaults];
for (int index = 0; index < loops; index++) {
TestNSArchive *obj = m_arrNSCodingObjs[index];
NSString *objKey = m_arrObjKeys[index];
auto tmp = [NSKeyedArchiver archivedDataWithRootObject:obj];
[userdefault setObject:tmp forKey:objKey];
}
[userdefault synchronize];
NSDate *endDate = [NSDate date];
int cost = [endDate timeIntervalSinceDate:startDate] * 1000;
NSLog(@"NSUserDefaults write object %d times, cost:%d ms", loops, cost);
}
}
- (void)userDefaultBatchReadObject:(int)loops {
@autoreleasepool {
NSDate *startDate = [NSDate date];
NSUserDefaults *userdefault = [NSUserDefaults standardUserDefaults];
for (int index = 0; index < loops; index++) {
NSString *objKey = m_arrObjKeys[index];
NSData *tmp = [userdefault objectForKey:objKey];
[NSKeyedUnarchiver unarchiveObjectWithData:tmp];
}
NSDate *endDate = [NSDate date];
int cost = [endDate timeIntervalSinceDate:startDate] * 1000;
NSLog(@"NSUserDefaults read object %d times, cost:%d ms", loops, cost);
}
}
#pragma mark - brutle test
- (void)brutleTest {