[Swift] Improving reallocation time by using memcpy and moving reallocation code...
authormustiikhalil <mustii@mmk.one>
Thu, 11 Jun 2020 15:53:32 +0000 (18:53 +0300)
committerGitHub <noreply@github.com>
Thu, 11 Jun 2020 15:53:32 +0000 (08:53 -0700)
Removes stride

Use capacity - current size to initialize

Fixes memory leak

Updated test code for linux

swift/Sources/FlatBuffers/ByteBuffer.swift
swift/Sources/FlatBuffers/FlatBufferBuilder.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift

index 75ad075..40b9cd7 100644 (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
index cd2523f..2501a39 100644 (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)
index 18ad6a0..d9e118d 100644 (file)
@@ -36,6 +36,7 @@ extension FlatBuffersStructsTests {
         ("testCreatingVectorStructWithForcedDefaults", testCreatingVectorStructWithForcedDefaults),
         ("testReadingStruct", testReadingStruct),
         ("testReadingStructWithEnums", testReadingStructWithEnums),
+        ("testWritingAndMutatingBools", testWritingAndMutatingBools),
     ]
 }