[Swift] Improving reallocation time by using memcpy and moving reallocation code to storage (#5960)

Removes stride

Use capacity - current size to initialize

Fixes memory leak

Updated test code for linux
This commit is contained in:
mustiikhalil
2020-06-11 18:53:32 +03:00
committed by GitHub
parent 4e45f7c9e8
commit 7cb4762a61
3 changed files with 27 additions and 25 deletions

View File

@@ -27,6 +27,24 @@ public struct ByteBuffer {
func initalize(for size: Int) {
memory.initializeMemory(as: UInt8.self, repeating: 0, count: size)
}
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
/// - Parameter size: Size of the current object
@usableFromInline internal func reallocate(_ size: UInt32, writerSize: Int, alignment: Int) {
let currentWritingIndex = capacity - writerSize
while capacity <= writerSize + Int(size) {
capacity = capacity << 1
}
/// solution take from Apple-NIO
capacity = capacity.convertToPowerofTwo
let newData = UnsafeMutableRawPointer.allocate(byteCount: capacity, alignment: alignment)
memset(newData, 0, capacity - writerSize)
memcpy(newData.advanced(by: capacity - writerSize), memory.advanced(by: currentWritingIndex), writerSize)
memory.deallocate()
memory = newData
}
}
@usableFromInline var _storage: Storage
@@ -208,31 +226,13 @@ public struct ByteBuffer {
/// - Parameter size: size of object
@discardableResult
@usableFromInline mutating func ensureSpace(size: UInt32) -> UInt32 {
if Int(size) + _writerSize > _storage.capacity { reallocate(size) }
if Int(size) + _writerSize > _storage.capacity {
_storage.reallocate(size, writerSize: _writerSize, alignment: alignment)
}
assert(size < FlatBufferMaxSize, "Buffer can't grow beyond 2 Gigabytes")
return size
}
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
/// - Parameter size: Size of the current object
@usableFromInline mutating internal func reallocate(_ size: UInt32) {
let currentWritingIndex = writerIndex
while _storage.capacity <= _writerSize + Int(size) {
_storage.capacity = _storage.capacity << 1
}
/// solution take from Apple-NIO
_storage.capacity = _storage.capacity.convertToPowerofTwo
let newData = UnsafeMutableRawPointer.allocate(byteCount: _storage.capacity, alignment: alignment)
newData.initializeMemory(as: UInt8.self, repeating: 0, count: _storage.capacity)
newData
.advanced(by: writerIndex)
.copyMemory(from: _storage.memory.advanced(by: currentWritingIndex), byteCount: _writerSize)
_storage.memory.deallocate()
_storage.memory = newData
}
/// Clears the current size of the buffer
mutating public func clearSize() {
_writerSize = 0

View File

@@ -135,7 +135,6 @@ public struct FlatBufferBuilder {
return _bb.size
}
/// Endtable will let the builder know that the object that's written to it is completed
///
/// This would be called after all the elements are serialized, it will add the vtable into the buffer.
@@ -156,8 +155,10 @@ public struct FlatBufferBuilder {
_bb.write(value: VOffset(tableObjectSize), index: _bb.writerIndex + sizeofVoffset, direct: true)
_bb.write(value: VOffset(_max), index: _bb.writerIndex, direct: true)
for index in stride(from: 0, to: _vtableStorage.writtenIndex, by: _vtableStorage.size) {
let loaded = _vtableStorage.load(at: index)
var itr = 0
while itr < _vtableStorage.writtenIndex {
let loaded = _vtableStorage.load(at: itr)
itr += _vtableStorage.size
guard loaded.offset != 0 else { continue }
let _index = (_bb.writerIndex + Int(loaded.position))
_bb.write(value: VOffset(vTableOffset - loaded.offset), index: _index, direct: true)