[Core] put small objects in memory store (#8972)

* remove the put in memory store

* put small objects directly in memory store

* cast data type

* fix another place that uses Put to spill to plasma store

* fix multiple tests related to memory limits

* partially fix test_metrics

* remove not functioning codes

* fix core_worker_test

* refactor put to plasma codes

* add a flag for the new feature

* add flag to more places

* do a warmup round for the plasma store

* lint

* lint again

* fix warmup store

* Update _raylet.pyx

Co-authored-by: Eric Liang <ekhliang@gmail.com>
This commit is contained in:
Zhuohan Li
2020-07-09 15:39:40 -07:00
committed by GitHub
parent 34b85659d4
commit 8a76f4cbb5
18 changed files with 132 additions and 51 deletions
+3
View File
@@ -315,3 +315,6 @@ RAY_CONFIG(int64_t, gcs_service_address_check_interval_milliseconds, 1000)
RAY_CONFIG(bool, gcs_actor_service_enabled,
getenv("RAY_GCS_ACTOR_SERVICE_ENABLED") != nullptr &&
getenv("RAY_GCS_ACTOR_SERVICE_ENABLED") == std::string("true"))
/// Whether start the Plasma Store as a Raylet thread.
RAY_CONFIG(bool, put_small_object_in_memory_store, false)
+41 -14
View File
@@ -360,9 +360,9 @@ CoreWorker::CoreWorker(const CoreWorkerOptions &options, const WorkerID &worker_
boost::bind(&CoreWorker::TriggerGlobalGC, this),
boost::bind(&CoreWorker::CurrentCallSite, this)));
memory_store_.reset(new CoreWorkerMemoryStore(
[this](const RayObject &obj, const ObjectID &obj_id) {
RAY_LOG(DEBUG) << "Promoting object to plasma " << obj_id;
RAY_CHECK_OK(Put(obj, /*contained_object_ids=*/{}, obj_id, /*pin_object=*/true));
[this](const RayObject &object, const ObjectID &object_id) {
PutObjectIntoPlasma(object, object_id);
return Status::OK();
},
options_.ref_counting_enabled ? reference_counter_ : nullptr, local_raylet_client_,
options_.check_signals));
@@ -708,6 +708,33 @@ CoreWorker::GetAllReferenceCounts() const {
return counts;
}
void CoreWorker::PutObjectIntoPlasma(const RayObject &object, const ObjectID &object_id) {
bool object_exists;
RAY_CHECK_OK(plasma_store_provider_->Put(object, object_id, &object_exists));
if (!object_exists) {
// Tell the raylet to pin the object **after** it is created.
RAY_LOG(DEBUG) << "Pinning put object " << object_id;
RAY_CHECK_OK(local_raylet_client_->PinObjectIDs(
rpc_address_, {object_id},
[this, object_id](const Status &status, const rpc::PinObjectIDsReply &reply) {
// Only release the object once the raylet has responded to avoid the race
// condition that the object could be evicted before the raylet pins it.
if (!plasma_store_provider_->Release(object_id).ok()) {
RAY_LOG(ERROR) << "Failed to release ObjectID (" << object_id
<< "), might cause a leak in plasma.";
}
}));
}
RAY_CHECK(memory_store_->Put(RayObject(rpc::ErrorType::OBJECT_IN_PLASMA), object_id));
}
void CoreWorker::PromoteObjectToPlasma(const ObjectID &object_id) {
auto value = memory_store_->GetOrPromoteToPlasma(object_id);
if (value) {
PutObjectIntoPlasma(*value, object_id);
}
}
const rpc::Address &CoreWorker::GetRpcAddress() const { return rpc_address_; }
rpc::Address CoreWorker::GetOwnerAddress(const ObjectID &object_id) const {
@@ -722,15 +749,8 @@ rpc::Address CoreWorker::GetOwnerAddress(const ObjectID &object_id) const {
return owner_address;
}
void CoreWorker::PromoteToPlasmaAndGetOwnershipInfo(const ObjectID &object_id,
rpc::Address *owner_address) {
auto value = memory_store_->GetOrPromoteToPlasma(object_id);
if (value) {
RAY_LOG(DEBUG) << "Storing object promoted to plasma " << object_id;
RAY_CHECK_OK(
Put(*value, /*contained_object_ids=*/{}, object_id, /*pin_object=*/true));
}
void CoreWorker::GetOwnershipInfo(const ObjectID &object_id,
rpc::Address *owner_address) {
auto has_owner = reference_counter_->GetOwner(object_id, owner_address);
RAY_CHECK(has_owner)
<< "Object IDs generated randomly (ObjectID.from_random()) or out-of-band "
@@ -773,7 +793,11 @@ Status CoreWorker::Put(const RayObject &object,
const std::vector<ObjectID> &contained_object_ids,
const ObjectID &object_id, bool pin_object) {
bool object_exists;
if (options_.is_local_mode) {
if (options_.is_local_mode ||
(RayConfig::instance().put_small_object_in_memory_store() &&
static_cast<int64_t>(object.GetSize()) <
RayConfig::instance().max_direct_call_object_size())) {
RAY_LOG(DEBUG) << "Put " << object_id << " in memory store";
RAY_CHECK(memory_store_->Put(object, object_id));
return Status::OK();
}
@@ -805,7 +829,10 @@ Status CoreWorker::Create(const std::shared_ptr<Buffer> &metadata, const size_t
ObjectID *object_id, std::shared_ptr<Buffer> *data) {
*object_id = ObjectID::ForPut(worker_context_.GetCurrentTaskID(),
worker_context_.GetNextPutIndex());
if (options_.is_local_mode) {
if (options_.is_local_mode ||
(RayConfig::instance().put_small_object_in_memory_store() &&
static_cast<int64_t>(data_size) <
RayConfig::instance().max_direct_call_object_size())) {
*data = std::make_shared<LocalMemoryBuffer>(data_size);
} else {
RAY_RETURN_NOT_OK(
+19 -6
View File
@@ -338,6 +338,22 @@ class CoreWorker : public rpc::CoreWorkerServiceHandler {
/// (local, submitted_task) reference counts. For debugging purposes.
std::unordered_map<ObjectID, std::pair<size_t, size_t>> GetAllReferenceCounts() const;
/// Put an object into plasma. It's a version of Put that directly put the
/// object into plasma and also pin the object.
///
/// \param[in] The ray object.
/// \param[in] object_id The object ID to serialize.
/// appended to the serialized object ID.
void PutObjectIntoPlasma(const RayObject &object, const ObjectID &object_id);
/// Promote an object to plasma. If the
/// object already exists locally, it will be put into the plasma store. If
/// it doesn't yet exist, it will be spilled to plasma once available.
///
/// \param[in] object_id The object ID to serialize.
/// appended to the serialized object ID.
void PromoteObjectToPlasma(const ObjectID &object_id);
/// Get the RPC address of this worker.
///
/// \param[out] The RPC address of this worker.
@@ -351,11 +367,9 @@ class CoreWorker : public rpc::CoreWorkerServiceHandler {
/// \param[out] The RPC address of the worker that owns this object.
rpc::Address GetOwnerAddress(const ObjectID &object_id) const;
/// Promote an object to plasma and get its owner information. This should be
/// Get the owner information of an object. This should be
/// called when serializing an object ID, and the returned information should
/// be stored with the serialized object ID. For plasma promotion, if the
/// object already exists locally, it will be put into the plasma store. If
/// it doesn't yet exist, it will be spilled to plasma once available.
/// be stored with the serialized object ID.
///
/// This can only be called on object IDs that we created via task
/// submission, ray.put, or object IDs that we deserialized. It cannot be
@@ -368,8 +382,7 @@ class CoreWorker : public rpc::CoreWorkerServiceHandler {
/// appended to the serialized object ID.
/// \param[out] owner_address The address of the object's owner. This should
/// be appended to the serialized object ID.
void PromoteToPlasmaAndGetOwnershipInfo(const ObjectID &object_id,
rpc::Address *owner_address);
void GetOwnershipInfo(const ObjectID &object_id, rpc::Address *owner_address);
/// Add a reference to an ObjectID that was deserialized by the language
/// frontend. This will also start the process to resolve the future.
@@ -40,6 +40,7 @@ CoreWorkerPlasmaStoreProvider::CoreWorkerPlasmaStoreProvider(
}
buffer_tracker_ = std::make_shared<BufferTracker>();
RAY_CHECK_OK(store_client_.Connect(store_socket));
RAY_CHECK_OK(WarmupStore());
}
CoreWorkerPlasmaStoreProvider::~CoreWorkerPlasmaStoreProvider() {
@@ -419,4 +420,14 @@ void CoreWorkerPlasmaStoreProvider::WarnIfAttemptedTooManyTimes(
}
}
Status CoreWorkerPlasmaStoreProvider::WarmupStore() {
ObjectID object_id = ObjectID::FromRandom();
std::shared_ptr<Buffer> data;
RAY_RETURN_NOT_OK(Create(nullptr, 8, object_id, &data));
RAY_RETURN_NOT_OK(Seal(object_id));
RAY_RETURN_NOT_OK(Release(object_id));
RAY_RETURN_NOT_OK(Delete({object_id}, false, false));
return Status::OK();
}
} // namespace ray
@@ -138,6 +138,12 @@ class CoreWorkerPlasmaStoreProvider {
static void WarnIfAttemptedTooManyTimes(int num_attempts,
const absl::flat_hash_set<ObjectID> &remaining);
/// Put something in the plasma store so that subsequent plasma store accesses
/// will be faster. Currently the first access is always slow, and we don't
/// want the user to experience this.
/// \return status
Status WarmupStore();
const std::shared_ptr<raylet::RayletClient> raylet_client_;
plasma::PlasmaClient store_client_;
/// Used to look up a plasma object's owner.
+6 -3
View File
@@ -774,14 +774,15 @@ TEST_F(SingleNodeTest, TestObjectInterface) {
auto &core_worker = CoreWorkerProcess::GetCoreWorker();
uint8_t array1[] = {1, 2, 3, 4, 5, 6, 7, 8};
uint8_t array2[] = {10, 11, 12, 13, 14, 15};
const size_t array2_size = 200 * 1024;
uint8_t *array2 = new uint8_t[array2_size];
std::vector<RayObject> buffers;
buffers.emplace_back(std::make_shared<LocalMemoryBuffer>(array1, sizeof(array1)),
std::make_shared<LocalMemoryBuffer>(array1, sizeof(array1) / 2),
std::vector<ObjectID>());
buffers.emplace_back(std::make_shared<LocalMemoryBuffer>(array2, sizeof(array2)),
std::make_shared<LocalMemoryBuffer>(array2, sizeof(array2) / 2),
buffers.emplace_back(std::make_shared<LocalMemoryBuffer>(array2, array2_size),
std::make_shared<LocalMemoryBuffer>(array2, array2_size / 2),
std::vector<ObjectID>());
std::vector<ObjectID> ids(buffers.size());
@@ -822,6 +823,8 @@ TEST_F(SingleNodeTest, TestObjectInterface) {
// to process the command.
usleep(200 * 1000);
ASSERT_TRUE(core_worker.Get(ids, 0, &results).IsTimedOut());
// Since array2 has been deleted from the plasma store, the Get should
// timeout and return nullptr for all results.
ASSERT_EQ(results.size(), 2);
ASSERT_TRUE(!results[0]);
ASSERT_TRUE(!results[1]);