In the following code, populateData does an unnecessary copy of the vector:
struct A {
vector<int> data;
ACTOR static Future<Void> populateData(A* self, int size) {
vector<int> _data = wait(produce(size));
self->data = std::move(_data);
}
static Future<vector<int>> produce(int size) {
return vector<int>(size, 0);
}
};
Calling wait(function_producing_future(args)) is a common pattern in FDB code, so reducing the number of copies in this scenario could potentially lead to large performance improvements, as https://github.com/apple/foundationdb/pull/2915 did. There are also other scenarios where it is possible to move the result of a future, but the actor compiler generates code that creates unnecessary copies.
The current plan is to create a new class:
template<class T>
struct MovableSAV : public SAV<T> {
...
};
which overrides the finishSendAndDelPromiseRef function to move the SAV contents instead of copy them. The actor compiler can then detect scenarios where itâs safe to use a MovableSAV instead of SAV. Other changes in the actor compiler can generate code that supports perfect forwarding.
This issue has already been discussed some with various people at Snowflake and Apple, but I created this forum post as a place for people to post other ideas to help reduce the number of unnecessary copies.