如何在 Objective C 中实现循环缓冲区以获得高性能
How to implement circular buffer in Objective C for high performance
我们想要每秒多次 Objective C 将双精度数组添加到循环缓冲区。
我们目前正在使用嵌套在另一个 NSMutableArray(二维数组)中的 NSMutableArray。这工作正常,但对我们的需求来说太慢了。
我们想每秒多次添加到循环缓冲区。当我们这样做并进行性能监控时,我们看到对 removeObjectAtIndex:0 的调用成为瓶颈(移动 n-1 个对象或 O(n-1))。这是因为我们的循环缓冲区中有数千个条目。
我们已经考虑过使用 STL 和 std::deque 的可能性。我们还查看了 CHDataStructures。如您所知,STL 位于 C++ 中并且可以集成,但不像 Objective C 解决方案那样直接。 CHDataStructures 已过时且不符合 ARC。
如果可能的话,请用代码示例建议我们应该如何实现一个循环缓冲区(用于我们的双精度数组)以实现高性能。
阅读了您的评论(并进一步考虑)后,我意识到使用常规 NSArray 会更好,因为没有内存管理问题(NSArray 自然保留其对象)。只需预先定义容量,以避免它在运行时必须重新分配内存。调用[self resetBuffer]
将快速释放所有数据并重新开始。
#define BUFFER_SIZE 1000
@implementation ViewController {
NSMutableArray *circularBuffer;
NSUInteger bufferHead;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self resetBuffer];
}
return self;
}
- (void)addArrayToBuffer:(NSMutableArray *)incoming {
if (bufferHead < circularBuffer.count)
[circularBuffer replaceObjectAtIndex:bufferHead withObject:incoming];
else
[circularBuffer addObject:incoming];
bufferHead = (bufferHead + 1) % BUFFER_SIZE;
}
- (NSArray *)bufferContent {
if (circularBuffer.count < BUFFER_SIZE) {
return circularBuffer;
} else {
NSArray *arrHead = [circularBuffer objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, bufferHead)]];
NSArray *arrTail = [circularBuffer objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(bufferHead, BUFFER_SIZE-bufferHead)]];
return [arrTail arrayByAddingObjectsFromArray:arrHead];
}
}
- (void)resetBuffer {
circularBuffer = [NSMutableArray arrayWithCapacity:BUFFER_SIZE];
bufferHead = 0;
}
我们想要每秒多次 Objective C 将双精度数组添加到循环缓冲区。
我们目前正在使用嵌套在另一个 NSMutableArray(二维数组)中的 NSMutableArray。这工作正常,但对我们的需求来说太慢了。
我们想每秒多次添加到循环缓冲区。当我们这样做并进行性能监控时,我们看到对 removeObjectAtIndex:0 的调用成为瓶颈(移动 n-1 个对象或 O(n-1))。这是因为我们的循环缓冲区中有数千个条目。
我们已经考虑过使用 STL 和 std::deque 的可能性。我们还查看了 CHDataStructures。如您所知,STL 位于 C++ 中并且可以集成,但不像 Objective C 解决方案那样直接。 CHDataStructures 已过时且不符合 ARC。
如果可能的话,请用代码示例建议我们应该如何实现一个循环缓冲区(用于我们的双精度数组)以实现高性能。
阅读了您的评论(并进一步考虑)后,我意识到使用常规 NSArray 会更好,因为没有内存管理问题(NSArray 自然保留其对象)。只需预先定义容量,以避免它在运行时必须重新分配内存。调用[self resetBuffer]
将快速释放所有数据并重新开始。
#define BUFFER_SIZE 1000
@implementation ViewController {
NSMutableArray *circularBuffer;
NSUInteger bufferHead;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self resetBuffer];
}
return self;
}
- (void)addArrayToBuffer:(NSMutableArray *)incoming {
if (bufferHead < circularBuffer.count)
[circularBuffer replaceObjectAtIndex:bufferHead withObject:incoming];
else
[circularBuffer addObject:incoming];
bufferHead = (bufferHead + 1) % BUFFER_SIZE;
}
- (NSArray *)bufferContent {
if (circularBuffer.count < BUFFER_SIZE) {
return circularBuffer;
} else {
NSArray *arrHead = [circularBuffer objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, bufferHead)]];
NSArray *arrTail = [circularBuffer objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(bufferHead, BUFFER_SIZE-bufferHead)]];
return [arrTail arrayByAddingObjectsFromArray:arrHead];
}
}
- (void)resetBuffer {
circularBuffer = [NSMutableArray arrayWithCapacity:BUFFER_SIZE];
bufferHead = 0;
}