Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Swift] Adds new API to reduce memory copying within swift #8484

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

mustiikhalil
Copy link
Collaborator

Adds new storage container _InternalByteBuffer which will be holding the data that will be created within the swift lib, however reading data will be redirected to ByteBuffer, which should be able to handle all types of data that swift provide without the need to copy the data itself. This is due to holding a reference to the data.

  • Adds _InternalByteBuffer which is responsible for creating FlatBuffers
  • Moves the current implementation of ByteBuffer to be the external face of the library and allows different ways of initialization
  • Removed unowned from the initializer
  • Replaces assumingMemoryBinding with bindMemory which is safer
  • Adds function that provides access to a UnsafeBufferPointer for scalars and NativeStructs within swift
  • Updates docs

@github-actions github-actions bot added c++ codegen Involving generating code from schema documentation Documentation grpc python swift labels Jan 14, 2025
@mustiikhalil mustiikhalil changed the title Adds new API to reduce memory copying within swift [Swift] Adds new API to reduce memory copying within swift Jan 14, 2025
@mustiikhalil mustiikhalil force-pushed the mmk/making-pointers-safe branch from b6473e1 to 7bfcafb Compare January 14, 2025 22:03
@mustiikhalil
Copy link
Collaborator Author

@wtholliday would be nice to have a secondary pair of eyes on the swift implementation, the benchmarks are good when we are creating a buffer. however as mentioned before, reading data from the buffer is a bit slower

@mustiikhalil mustiikhalil force-pushed the mmk/making-pointers-safe branch from 7bfcafb to 3a29d6e Compare January 14, 2025 22:32
@mustiikhalil mustiikhalil self-assigned this Jan 14, 2025
@mustiikhalil mustiikhalil force-pushed the mmk/making-pointers-safe branch 2 times, most recently from 9f3f299 to f171d78 Compare January 15, 2025 19:39
@mustiikhalil
Copy link
Collaborator Author

mustiikhalil commented Jan 16, 2025

Hello,

@abandy, @mr-swifter. We are currently reworking the way Flatbuffers swift reads data from a data object, what we used to do is make a copy of the data that is stored somewhere and then read from our internal storage, but that seemed to be inefficient. So we decided to refactor that and basically store that data within the ByteBuffer, and provide ways for our already written methods to read from that ByteBuffer, this refactor would allowed us to remove the allowReadingUnalignedBuffers if used correctly.

Questions

  • Would this still work with the unaligned data that you provide the ByteBuffer?
  • Can we test it to verify that everything works?
  • Are you always sure that the first four bytes are the offset of the root/prefix?

Clarification

So in the following test, we are creating an array of bytes that we unalign using a byte at the start and then advancing the pointer, however that advance would always advance into 48, 0, 0, 0, which is the first required offset to read the Monster object

    let testUnaligned: () -> Bool = {
      var bytes: [UInt8] = [0x00]
      bytes.append(contentsOf: fbb.sizedByteArray)
      return bytes.withUnsafeMutableBytes { ptr in
        guard var baseAddress = ptr.baseAddress else {
          XCTFail("Base pointer is not defined")
          return false
        }
        baseAddress = baseAddress.advanced(by: 1)
        let unlignedPtr = UnsafeMutableRawPointer(baseAddress)
        var bytes = ByteBuffer(
          assumingMemoryBound: unlignedPtr,
          capacity: ptr.count - 1)
        var monster: Monster = getRoot(byteBuffer: &bytes)
        self.readFlatbufferMonster(monster: &monster)
        return true
      }
    }

So as long as the bytes within a Data, Uint8 array or even a pointer is pointing to an offset, which in theory is the 48, 0, 0, 0 and not 0, 48, 0, 0 we are all good.

Where do we go from here?

  • Revert the changes for allowReadingUnalignedBuffers, which is still a problem if you are reading strings and arrays.
  • Adopting the verifier to verify that the data is an unaligned valid Flatbuffer object before trying to read it

@abandy
Copy link
Contributor

abandy commented Jan 17, 2025

Hi @mustiikhalil,

I commented on the Swift Arrow issue you opened and am pasting the reply here as well. Thanks again!

Nice, good to remove unnecessary copying! I will try to pull your changes down and run the tests by end of next week. Even if these changes cause an issue, Swift Arrow should be fine as it is bound to a version of the flatbuffers, so checking in your changes shouldn't break Swift Arrow right away. Thanks for checking!

@mustiikhalil mustiikhalil force-pushed the mmk/making-pointers-safe branch 2 times, most recently from c17d423 to d636dfc Compare January 17, 2025 07:18
Adds new storage container _InternalByteBuffer which
will be holding the data that will be created within the swift
lib, however reading data will be redirected to ByteBuffer, which
should be able to handle all types of data that swift provide without
the need to copy the data itself. This is due to holding a reference to
the data.

Removed unowned from the initializer

Replaces assumingMemoryBinding with bindMemory which is safer

Adds function that provides access to a UnsafeBufferPointer for
scalars and NativeStructs within swift

Updates docs

Suppress compilation warnings by replacing var with let
@mustiikhalil mustiikhalil force-pushed the mmk/making-pointers-safe branch from d636dfc to bd409d4 Compare January 17, 2025 07:22
Using overflow operators within swift to improve performance

Adds tests for GRPC message creation from a retained _InternalByteBuffer
@mustiikhalil mustiikhalil force-pushed the mmk/making-pointers-safe branch from bd409d4 to b74f2af Compare January 17, 2025 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ codegen Involving generating code from schema documentation Documentation grpc python swift
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants