Skip to content

Dart with Rust: The efficient way to pass around big objects while following Rust's memory management and Dart's GC? #47323

Open
@fzyzcjy

Description

@fzyzcjy

Hi thanks for the wonderful langauge and Flutter! This question follows dart-lang/language#1862 , (because I follow @mraleph 's suggestion and decide to use Dart_PostCObject).

The problem setup: I have a Flutter app with main isolate (no more worker isolates). I have some Rust code computing big images and talk to Flutter/Dart via FFI. For example, a typical call is:

  • Flutter calls Rust's create_an_image()
  • Rust's create_an_image creates (for simplicity) a new thread, and let that thread to do heavy work of generating a big image (say, rust_worker_thread_create_an_image). But the create_an_image function returns immediately, thus Flutter will not be blocked, and we never need a worker isolate now.
  • After some time, rust_worker_thread_create_an_image() is finished. It uses Dart_PostCObject to post the image as an externalized typed data to Flutter, and Flutter can display it by receiving it in ReceivePort and give it to Image widget.

Now comes the problem: I want that big image to be manipulated later on again. Let's say, make it rotated by the angle given by the user via a text field in the UI (for simplicity).

Naive method is to copy the Uint8List to a region of memory allocated in Rust (suggested in dart-lang/language#1862), and pass it to Rust. But you see, we introduce one extra memory copy here.

Is it suggested (dart-lang/language#1862 (comment)) that I can use finalizers. But how should I do that with Rust's memory management system? And the mutability system - because when putting into an externalized typed data, it can be changed anywhere, while it cannot if we use pure Rust (at most one mutable borrow).

A naive way is that, if it is alive in externalized typed data (i.e. finalizer is not called yet), I should not use it in Rust. But this is silly, because Dart GC can happen very late after seconds, and before it is GCed, the finalizers will never be called, even if the pointer is already passed to Rust.

Thanks for any suggestions! I am not sure whether this should be asked here or on StackOverflow, so please tell me if I need to move.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions