RFC: [hg] backingstore: use IOBuf::TakeOwnershipOp to achieve zero-copy

Summary: Uses `folly::IOBuf`'s `TakeOwnership` instead of `CopyBuffer` to achieve zero-copy of file content we get from Rust.

Reviewed By: chadaustin

Differential Revision: D18264900

fbshipit-source-id: 45baa70cb771a2bff0b31feaa1b85569625218eb
This commit is contained in:
Zeyi (Rice) Fan 2019-12-06 19:03:35 -08:00 committed by Facebook Github Bot
parent 559a0dafeb
commit 1ae1169043
4 changed files with 25 additions and 16 deletions

View File

@ -7,7 +7,6 @@
#include "eden/scm/lib/backingstore/c_api/HgNativeBackingStore.h"
#include <folly/Optional.h>
#include <folly/Range.h>
#include <folly/String.h>
#include <folly/io/IOBuf.h>
@ -17,6 +16,21 @@
namespace facebook {
namespace eden {
namespace {
/**
* Convert a `RustCBytes` into `folly::IOBuf` without copying the underlying
* data.
*/
std::unique_ptr<folly::IOBuf> bytesToIOBuf(RustCBytes* bytes) {
return folly::IOBuf::takeOwnership(
reinterpret_cast<void*>(bytes->ptr),
bytes->len,
[](void* /* buf */, void* userData) {
rust_cbytes_free(reinterpret_cast<RustCBytes*>(userData));
},
reinterpret_cast<void*>(bytes));
}
} // namespace
HgNativeBackingStore::HgNativeBackingStore(folly::StringPiece repository) {
RustCFallible<RustBackingStore> store(
@ -30,7 +44,7 @@ HgNativeBackingStore::HgNativeBackingStore(folly::StringPiece repository) {
store_ = store.unwrap();
}
folly::Optional<folly::IOBuf> HgNativeBackingStore::getBlob(
std::unique_ptr<folly::IOBuf> HgNativeBackingStore::getBlob(
folly::ByteRange name,
folly::ByteRange node) {
RustCFallible<RustCBytes> result(
@ -42,13 +56,10 @@ folly::Optional<folly::IOBuf> HgNativeBackingStore::getBlob(
XLOG(DBG5) << "Error while getting blob name=" << name.data()
<< " node=" << folly::hexlify(node)
<< " from backingstore: " << result.getError();
return folly::none;
return nullptr;
}
auto buffer = result.get();
auto iobuf =
folly::IOBuf{folly::IOBuf::COPY_BUFFER, buffer->ptr, buffer->len};
return iobuf;
return bytesToIOBuf(result.unwrap().release());
}
std::shared_ptr<RustTree> HgNativeBackingStore::getTree(folly::ByteRange node) {

View File

@ -13,8 +13,6 @@
namespace folly {
class IOBuf;
template <typename T>
class Optional;
} // namespace folly
namespace facebook {
@ -24,7 +22,7 @@ class HgNativeBackingStore {
public:
explicit HgNativeBackingStore(folly::StringPiece repository);
folly::Optional<folly::IOBuf> getBlob(
std::unique_ptr<folly::IOBuf> getBlob(
folly::ByteRange name,
folly::ByteRange node);

View File

@ -7,7 +7,7 @@
* This file is generated with cbindgen. Please run `./tools/cbindgen.sh` to
* update this file.
*
* @generated SignedSource<<85582de8715286965cfc5e5472a8dab0>>
* @generated SignedSource<<d4d2d4d612a8215f35cd4ef138904bab>>
*
*/
@ -89,7 +89,7 @@ template<typename T>
struct RustVec;
struct RustCBytes {
const uint8_t *ptr;
uint8_t *ptr;
size_t len;
RustVec<uint8_t> *vec;
folly::ByteRange asByteRange() const {
@ -112,7 +112,7 @@ struct RustTreeEntry {
struct RustTree {
const RustTreeEntry *entries;
/// This makes sure `entries` above is pointing to a valid memory.
RustVec<RustTreeEntry> *_entries;
RustVec<RustTreeEntry> *entries_ptr;
uintptr_t length;
RustCBytes hash;
};

View File

@ -13,15 +13,15 @@ use libc::size_t;
#[repr(C)]
pub struct CBytes {
ptr: *const u8,
ptr: *mut u8,
len: size_t,
vec: *mut Vec<u8>,
}
impl CBytes {
pub fn from_vec(vec: Vec<u8>) -> Self {
let vec = Box::new(vec);
let ptr = vec.as_ptr();
let mut vec = Box::new(vec);
let ptr = vec.as_mut_ptr();
Self {
ptr,