diff --git a/flex/CMakeLists.txt b/flex/CMakeLists.txt index 6cd561409883..7384c052d32d 100644 --- a/flex/CMakeLists.txt +++ b/flex/CMakeLists.txt @@ -14,15 +14,12 @@ option(BUILD_HQPS "Whether to build HighQPS Engine" ON) option(BUILD_TEST "Whether to build test" ON) option(BUILD_DOC "Whether to build doc" ON) option(BUILD_ODPS_FRAGMENT_LOADER "Whether to build odps fragment loader" ON) -option(MONITOR_SESSIONS "Whether monitor sessions" OFF) #print options message(STATUS "Build HighQPS Engine: ${BUILD_HQPS}") message(STATUS "Build test: ${BUILD_TEST}") message(STATUS "Build doc: ${BUILD_DOC}") message(STATUS "Build odps fragment loader: ${BUILD_ODPS_FRAGMENT_LOADER}") -message(STATUS "Monitor sessions: ${MONITOR_SESSIONS}") -message(STATUS "Enable hugepage: ${ENABLE_HUGEPAGE}") # ------------------------------------------------------------------------------ # cmake configs @@ -43,11 +40,6 @@ if (BUILD_HQPS) add_definitions(-DBUILD_HQPS) endif () -if (MONITOR_SESSIONS) - message("Monitor sessions is enabled") - add_definitions(-DMONITOR_SESSIONS) -endif () - execute_process(COMMAND uname -r OUTPUT_VARIABLE LINUX_KERNEL_VERSION) string(STRIP ${LINUX_KERNEL_VERSION} LINUX_KERNEL_VERSION) message(${LINUX_KERNEL_VERSION}) diff --git a/flex/bin/rt_server.cc b/flex/bin/rt_server.cc index 11b23aab3ffd..b7db11aba48c 100644 --- a/flex/bin/rt_server.cc +++ b/flex/bin/rt_server.cc @@ -85,8 +85,9 @@ int main(int argc, char** argv) { auto schema = gs::Schema::LoadFromYaml(graph_schema_path); gs::GraphDBConfig config(schema, data_path, shard_num); config.memory_level = memory_level; - config.enable_auto_compaction = true; - config.service_port = http_port; + if (config.memory_level >= 2) { + config.enable_auto_compaction = true; + } db.Open(config); t0 += grape::GetCurrentTime(); diff --git a/flex/engines/graph_db/database/graph_db.cc b/flex/engines/graph_db/database/graph_db.cc index 42a455202e3c..120319f87532 100644 --- a/flex/engines/graph_db/database/graph_db.cc +++ b/flex/engines/graph_db/database/graph_db.cc @@ -62,7 +62,7 @@ GraphDB& GraphDB::get() { Result GraphDB::Open(const Schema& schema, const std::string& data_dir, int32_t thread_num, bool warmup, bool memory_only, - bool enable_auto_compaction, int port) { + bool enable_auto_compaction) { GraphDBConfig config(schema, data_dir, thread_num); config.warmup = warmup; if (memory_only) { @@ -71,7 +71,6 @@ Result GraphDB::Open(const Schema& schema, const std::string& data_dir, config.memory_level = 0; } config.enable_auto_compaction = enable_auto_compaction; - config.service_port = port; return Open(config); } @@ -135,57 +134,103 @@ Result GraphDB::Open(const GraphDBConfig& config) { graph_.Warmup(thread_num_); } - if (config.enable_auto_compaction && (config.service_port != -1)) { + if (config.enable_monitering) { + if (monitor_thread_running_) { + monitor_thread_running_ = false; + monitor_thread_.join(); + } + monitor_thread_running_ = true; + monitor_thread_ = std::thread([&]() { + std::vector last_eval_durations(thread_num_, 0); + std::vector last_query_nums(thread_num_, 0); + while (monitor_thread_running_) { + sleep(10); + size_t curr_allocated_size = 0; + double total_eval_durations = 0; + double min_eval_duration = std::numeric_limits::max(); + double max_eval_duration = 0; + int64_t total_query_num = 0; + int64_t min_query_num = std::numeric_limits::max(); + int64_t max_query_num = 0; + + for (int i = 0; i < thread_num_; ++i) { + curr_allocated_size += contexts_[i].allocator.allocated_memory(); + if (last_eval_durations[i] == 0) { + last_eval_durations[i] = contexts_[i].session.eval_duration(); + } else { + double curr = contexts_[i].session.eval_duration(); + double eval_duration = curr; + total_eval_durations += eval_duration; + min_eval_duration = std::min(min_eval_duration, eval_duration); + max_eval_duration = std::max(max_eval_duration, eval_duration); + + last_eval_durations[i] = curr; + } + if (last_query_nums[i] == 0) { + last_query_nums[i] = contexts_[i].session.query_num(); + } else { + int64_t curr = contexts_[i].session.query_num(); + total_query_num += curr; + min_query_num = std::min(min_query_num, curr); + max_query_num = std::max(max_query_num, curr); + + last_query_nums[i] = curr; + } + } + if (max_query_num != 0) { + double avg_eval_durations = + total_eval_durations / static_cast(thread_num_); + double avg_query_num = static_cast(total_query_num) / + static_cast(thread_num_); + double allocated_size_in_gb = + static_cast(curr_allocated_size) / 1024.0 / 1024.0 / + 1024.0; + LOG(INFO) << "allocated: " << allocated_size_in_gb << " GB, eval: [" + << min_eval_duration << ", " << avg_eval_durations << ", " + << max_eval_duration << "] s, query num: [" << min_query_num + << ", " << avg_query_num << ", " << max_query_num << "]"; + } + } + }); + } + + if (config.enable_auto_compaction) { if (compact_thread_running_) { compact_thread_running_ = false; compact_thread_.join(); } compact_thread_running_ = true; - compact_thread_ = std::thread( - [&](int http_port) { - size_t last_compaction_at = 0; - while (compact_thread_running_) { - size_t query_num_before = getExecutedQueryNum(); - sleep(30); - if (!compact_thread_running_) { - break; - } - size_t query_num_after = getExecutedQueryNum(); - if (query_num_before == query_num_after && - (query_num_after > (last_compaction_at + 100000))) { - VLOG(10) << "Trigger auto compaction"; - last_compaction_at = query_num_after; - std::string url = "127.0.0.1"; - httplib::Client cli(url, http_port); - cli.set_connection_timeout(0, 300000); - cli.set_read_timeout(300, 0); - cli.set_write_timeout(300, 0); - - std::vector buf; - Encoder encoder(buf); - encoder.put_string("COMPACTION"); - encoder.put_byte(0); - std::string content(buf.data(), buf.size()); - auto res = cli.Post("/interactive/query", content, "text/plain"); - std::string ret = res->body; - Decoder decoder(ret.data(), ret.size()); - std::string_view info = decoder.get_string(); - - VLOG(10) << "Finish compaction, info: " << info; - } - } - }, - config.service_port); + compact_thread_ = std::thread([&]() { + size_t last_compaction_at = 0; + while (compact_thread_running_) { + size_t query_num_before = getExecutedQueryNum(); + sleep(30); + if (!compact_thread_running_) { + break; + } + size_t query_num_after = getExecutedQueryNum(); + if (query_num_before == query_num_after && + (query_num_after > (last_compaction_at + 100000))) { + VLOG(10) << "Trigger auto compaction"; + last_compaction_at = query_num_after; + timestamp_t ts = this->version_manager_.acquire_update_timestamp(); + auto txn = CompactTransaction(this->graph_, this->contexts_[0].logger, + this->version_manager_, ts); + txn.Commit(); + VLOG(10) << "Finish compaction"; + } + } + }); } return Result(true); } void GraphDB::Close() { -#ifdef MONITOR_SESSIONS - monitor_thread_running_ = false; - monitor_thread_.join(); -#endif + if (monitor_thread_running_) { + monitor_thread_running_ = false; + monitor_thread_.join(); + } if (compact_thread_running_) { compact_thread_running_ = false; compact_thread_.join(); @@ -399,63 +444,6 @@ void GraphDB::openWalAndCreateContexts(const std::string& data_dir, initApps(graph_.schema().GetPlugins()); VLOG(1) << "Successfully restore load plugins"; - -#ifdef MONITOR_SESSIONS - monitor_thread_running_ = true; - monitor_thread_ = std::thread([&]() { - size_t last_allocated_size = 0; - std::vector last_eval_durations(thread_num_, 0); - std::vector last_query_nums(thread_num_, 0); - while (monitor_thread_running_) { - sleep(10); - size_t curr_allocated_size = 0; - double total_eval_durations = 0; - double min_eval_duration = std::numeric_limits::max(); - double max_eval_duration = 0; - int64_t total_query_num = 0; - int64_t min_query_num = std::numeric_limits::max(); - int64_t max_query_num = 0; - - for (int i = 0; i < thread_num_; ++i) { - curr_allocated_size += contexts_[i].allocator.allocated_memory(); - if (last_eval_durations[i] == 0) { - last_eval_durations[i] = contexts_[i].session.eval_duration(); - } else { - double curr = contexts_[i].session.eval_duration(); - double eval_duration = curr; - total_eval_durations += eval_duration; - min_eval_duration = std::min(min_eval_duration, eval_duration); - max_eval_duration = std::max(max_eval_duration, eval_duration); - - last_eval_durations[i] = curr; - } - if (last_query_nums[i] == 0) { - last_query_nums[i] = contexts_[i].session.query_num(); - } else { - int64_t curr = contexts_[i].session.query_num(); - total_query_num += curr; - min_query_num = std::min(min_query_num, curr); - max_query_num = std::max(max_query_num, curr); - - last_query_nums[i] = curr; - } - } - last_allocated_size = curr_allocated_size; - if (max_query_num != 0) { - double avg_eval_durations = - total_eval_durations / static_cast(thread_num_); - double avg_query_num = static_cast(total_query_num) / - static_cast(thread_num_); - double allocated_size_in_gb = - static_cast(curr_allocated_size) / 1024.0 / 1024.0 / 1024.0; - LOG(INFO) << "allocated: " << allocated_size_in_gb << " GB, eval: [" - << min_eval_duration << ", " << avg_eval_durations << ", " - << max_eval_duration << "] s, query num: [" << min_query_num - << ", " << avg_query_num << ", " << max_query_num << "]"; - } - } - }); -#endif } void GraphDB::showAppMetrics() const { @@ -469,12 +457,8 @@ void GraphDB::showAppMetrics() const { std::string query_name = "UNKNOWN"; if (i == 0) { query_name = "ServerApp"; - } else if (i <= 14) { - query_name = "IC" + std::to_string(i); - } else if (i <= 21) { - query_name = "IS" + std::to_string(i - 14); - } else if (i <= 29) { - query_name = "INS" + std::to_string(i - 21); + } else { + query_name = "Query-" + std::to_string(i); } summary.output(query_name); } diff --git a/flex/engines/graph_db/database/graph_db.h b/flex/engines/graph_db/database/graph_db.h index b7e3415b6210..bf53032993a0 100644 --- a/flex/engines/graph_db/database/graph_db.h +++ b/flex/engines/graph_db/database/graph_db.h @@ -47,24 +47,24 @@ struct GraphDBConfig { data_dir(data_dir_), thread_num(thread_num_), warmup(false), + enable_monitering(false), enable_auto_compaction(false), - service_port(-1), memory_level(1) {} Schema schema; std::string data_dir; int thread_num; bool warmup; + bool enable_monitering; bool enable_auto_compaction; - int service_port; /* - 0 - sync with disk; - 1 - mmap virtual memory; - 2 - prefering hugepages; + 0 - sync with disk; + 1 - mmap virtual memory; + 2 - prefering hugepages; 3 - force hugepages; */ - int memory_level; + int memory_level; }; class GraphDB { @@ -85,7 +85,7 @@ class GraphDB { Result Open(const Schema& schema, const std::string& data_dir, int32_t thread_num = 1, bool warmup = false, bool memory_only = true, - bool enable_auto_compaction = false, int port = -1); + bool enable_auto_compaction = false); Result Open(const GraphDBConfig& config); @@ -179,10 +179,8 @@ class GraphDB { std::array app_paths_; std::array, 256> app_factories_; -#ifdef MONITOR_SESSIONS std::thread monitor_thread_; bool monitor_thread_running_; -#endif timestamp_t last_compaction_ts_; bool compact_thread_running_ = false; diff --git a/flex/engines/graph_db/database/graph_db_session.cc b/flex/engines/graph_db/database/graph_db_session.cc index ceaeca3c7b6e..ad958a9c0b7b 100644 --- a/flex/engines/graph_db/database/graph_db_session.cc +++ b/flex/engines/graph_db/database/graph_db_session.cc @@ -13,9 +13,7 @@ * limitations under the License. */ -#ifdef MONITOR_SESSIONS #include -#endif #include "flex/engines/graph_db/app/app_base.h" #include "flex/engines/graph_db/database/graph_db.h" @@ -127,11 +125,9 @@ Result> GraphDBSession::Eval(const std::string& input) { app_metrics_[type].add_record( std::chrono::duration_cast(end - start) .count()); -#ifdef MONITOR_SESSIONS eval_duration_.fetch_add( std::chrono::duration_cast(end - start) .count()); -#endif ++query_num_; return result_buffer; } @@ -146,12 +142,10 @@ Result> GraphDBSession::Eval(const std::string& input) { result_buffer.clear(); } -#ifdef MONITOR_SESSIONS const auto end = std::chrono::high_resolution_clock::now(); eval_duration_.fetch_add( std::chrono::duration_cast(end - start) .count()); -#endif ++query_num_; return Result>( StatusCode::QueryFailed, @@ -180,13 +174,10 @@ bool GraphDBSession::Compact() { } } -#ifdef MONITOR_SESSIONS double GraphDBSession::eval_duration() const { return static_cast(eval_duration_.load()) / 1000000.0; } -#endif - int64_t GraphDBSession::query_num() const { return query_num_.load(); } #define likely(x) __builtin_expect(!!(x), 1) diff --git a/flex/engines/graph_db/database/graph_db_session.h b/flex/engines/graph_db/database/graph_db_session.h index e4adee1d84a3..73ba90404258 100644 --- a/flex/engines/graph_db/database/graph_db_session.h +++ b/flex/engines/graph_db/database/graph_db_session.h @@ -44,9 +44,7 @@ class GraphDBSession { logger_(logger), work_dir_(work_dir), thread_id_(thread_id), -#ifdef MONITOR_SESSIONS eval_duration_(0), -#endif query_num_(0) { for (auto& app : apps_) { app = nullptr; @@ -87,9 +85,7 @@ class GraphDBSession { bool Compact(); -#ifdef MONITOR_SESSIONS double eval_duration() const; -#endif const AppMetric& GetAppMetric(int idx) const; @@ -108,9 +104,7 @@ class GraphDBSession { std::array apps_; std::array app_metrics_; -#ifdef MONITOR_SESSIONS std::atomic eval_duration_; -#endif std::atomic query_num_; }; diff --git a/flex/engines/graph_db/database/read_transaction.cc b/flex/engines/graph_db/database/read_transaction.cc index 1bad63335b4c..f29696d95905 100644 --- a/flex/engines/graph_db/database/read_transaction.cc +++ b/flex/engines/graph_db/database/read_transaction.cc @@ -56,7 +56,7 @@ int ReadTransaction::vertex_iterator::FieldNum() const { ReadTransaction::edge_iterator::edge_iterator( label_t neighbor_label, label_t edge_label, - std::shared_ptr iter) + std::shared_ptr iter) : neighbor_label_(neighbor_label), edge_label_(edge_label), iter_(std::move(iter)) {} diff --git a/flex/engines/graph_db/database/read_transaction.h b/flex/engines/graph_db/database/read_transaction.h index 3430a712765a..86947af0a6fd 100644 --- a/flex/engines/graph_db/database/read_transaction.h +++ b/flex/engines/graph_db/database/read_transaction.h @@ -19,7 +19,7 @@ #include #include -#include "flex/storages/rt_mutable_graph/mutable_csr.h" +#include "flex/storages/rt_mutable_graph/csr/mutable_csr.h" #include "flex/storages/rt_mutable_graph/mutable_property_fragment.h" #include "flex/storages/rt_mutable_graph/types.h" @@ -218,6 +218,62 @@ class SingleGraphView { timestamp_t timestamp_; }; +template <> +class SingleGraphView { + public: + SingleGraphView(const SingleMutableCsr& csr, + timestamp_t timestamp) + : csr_(csr), timestamp_(timestamp) {} + + bool exist(vid_t v) const { + return (csr_.get_edge(v).timestamp.load() <= timestamp_); + } + + MutableNbr get_edge(vid_t v) const { + return csr_.get_edge(v); + } + + private: + const SingleMutableCsr& csr_; + timestamp_t timestamp_; +}; + +template +class SingleImmutableGraphView { + public: + SingleImmutableGraphView(const SingleImmutableCsr& csr) + : csr_(csr) {} + + bool exist(vid_t v) const { + return (csr_.get_edge(v).neighbor != std::numeric_limits::max()); + } + + const ImmutableNbr& get_edge(vid_t v) const { + return csr_.get_edge(v); + } + + private: + const SingleImmutableCsr& csr_; +}; + +template <> +class SingleImmutableGraphView { + public: + SingleImmutableGraphView(const SingleImmutableCsr& csr) + : csr_(csr) {} + + bool exist(vid_t v) const { + return (csr_.get_edge(v).neighbor != std::numeric_limits::max()); + } + + ImmutableNbr get_edge(vid_t v) const { + return csr_.get_edge(v); + } + + private: + const SingleImmutableCsr& csr_; +}; + class ReadTransaction { public: ReadTransaction(const MutablePropertyFragment& graph, VersionManager& vm, @@ -256,7 +312,7 @@ class ReadTransaction { class edge_iterator { public: edge_iterator(label_t neighbor_label, label_t edge_label, - std::shared_ptr iter); + std::shared_ptr iter); ~edge_iterator(); Any GetData() const; @@ -275,7 +331,7 @@ class ReadTransaction { label_t neighbor_label_; label_t edge_label_; - std::shared_ptr iter_; + std::shared_ptr iter_; }; vertex_iterator GetVertexIterator(label_t label) const; @@ -350,6 +406,22 @@ class ReadTransaction { return SingleGraphView(*csr, timestamp_); } + template + SingleImmutableGraphView GetOutgoingSingleImmutableGraphView( + label_t v_label, label_t neighbor_label, label_t edge_label) const { + auto csr = dynamic_cast*>( + graph_.get_oe_csr(v_label, neighbor_label, edge_label)); + return SingleImmutableGraphView(*csr); + } + + template + SingleImmutableGraphView GetIncomingSingleImmutableGraphView( + label_t v_label, label_t neighbor_label, label_t edge_label) const { + auto csr = dynamic_cast*>( + graph_.get_ie_csr(v_label, neighbor_label, edge_label)); + return SingleImmutableGraphView(*csr); + } + private: void release(); diff --git a/flex/engines/graph_db/database/transaction_utils.h b/flex/engines/graph_db/database/transaction_utils.h index 6be54dba52d2..df8af78d2e22 100644 --- a/flex/engines/graph_db/database/transaction_utils.h +++ b/flex/engines/graph_db/database/transaction_utils.h @@ -60,7 +60,9 @@ inline void deserialize_field(grape::OutArchive& arc, Any& prop) { } else if (prop.type == PropertyType::UInt32()) { arc >> prop.value.ui; } else if (prop.type == PropertyType::Date()) { - arc >> prop.value.d.milli_second; + int64_t date_val; + arc >> date_val; + prop.value.d.milli_second = date_val; } else if (prop.type == PropertyType::Day()) { uint32_t val; arc >> val; diff --git a/flex/engines/graph_db/database/update_transaction.cc b/flex/engines/graph_db/database/update_transaction.cc index c6c75b58f7fa..7c6bcd2d1c8f 100644 --- a/flex/engines/graph_db/database/update_transaction.cc +++ b/flex/engines/graph_db/database/update_transaction.cc @@ -153,8 +153,8 @@ bool UpdateTransaction::AddVertex(label_t label, const Any& oid, return true; } -static size_t get_offset( - const std::shared_ptr& base, vid_t target) { +static size_t get_offset(const std::shared_ptr& base, + vid_t target) { size_t offset = 0; while (base != nullptr && base->is_valid()) { if (base->get_neighbor() == target) { @@ -245,8 +245,7 @@ bool UpdateTransaction::vertex_iterator::SetField(int col_id, UpdateTransaction::edge_iterator::edge_iterator( bool dir, label_t label, vid_t v, label_t neighbor_label, label_t edge_label, const vid_t* aeb, const vid_t* aee, - std::shared_ptr init_iter, - UpdateTransaction* txn) + std::shared_ptr init_iter, UpdateTransaction* txn) : dir_(dir), label_(label), v_(v), @@ -605,7 +604,7 @@ void UpdateTransaction::IngestWal(MutablePropertyFragment& graph, CHECK(graph.get_lid(label, v, v_lid)); CHECK(graph.get_lid(neighbor_label, nbr, nbr_lid)); - std::shared_ptr edge_iter(nullptr); + std::shared_ptr edge_iter(nullptr); if (dir == 0) { edge_iter = graph.get_incoming_edges_mut(label, v_lid, neighbor_label, edge_label); @@ -778,7 +777,7 @@ void UpdateTransaction::applyEdgesUpdates() { continue; } - std::shared_ptr edge_iter = + std::shared_ptr edge_iter = graph_.get_outgoing_edges_mut(src_label, pair.first, dst_label, edge_label); for (auto& edge : updates) { @@ -833,7 +832,7 @@ void UpdateTransaction::applyEdgesUpdates() { if (updates.empty()) { continue; } - std::shared_ptr edge_iter = + std::shared_ptr edge_iter = graph_.get_incoming_edges_mut(dst_label, pair.first, src_label, edge_label); for (auto& edge : updates) { diff --git a/flex/engines/graph_db/database/update_transaction.h b/flex/engines/graph_db/database/update_transaction.h index e08f4e63e0ca..98d19bf2302f 100644 --- a/flex/engines/graph_db/database/update_transaction.h +++ b/flex/engines/graph_db/database/update_transaction.h @@ -21,7 +21,7 @@ #include "flat_hash_map/flat_hash_map.hpp" #include "flex/engines/graph_db/database/transaction_utils.h" -#include "flex/storages/rt_mutable_graph/mutable_csr.h" +#include "flex/storages/rt_mutable_graph/csr/mutable_csr.h" #include "flex/storages/rt_mutable_graph/types.h" #include "flex/utils/allocators.h" #include "flex/utils/id_indexer.h" @@ -83,7 +83,7 @@ class UpdateTransaction { public: edge_iterator(bool dir, label_t label, vid_t v, label_t neighbor_label, label_t edge_label, const vid_t* aeb, const vid_t* aee, - std::shared_ptr init_iter, + std::shared_ptr init_iter, UpdateTransaction* txn); ~edge_iterator(); @@ -115,7 +115,7 @@ class UpdateTransaction { const vid_t* added_edges_cur_; const vid_t* added_edges_end_; - std::shared_ptr init_iter_; + std::shared_ptr init_iter_; UpdateTransaction* txn_; size_t offset_; }; diff --git a/flex/engines/graph_db/grin/src/topology/adjacentlist.cc b/flex/engines/graph_db/grin/src/topology/adjacentlist.cc index 112da2e552d3..ac6928a0d97e 100644 --- a/flex/engines/graph_db/grin/src/topology/adjacentlist.cc +++ b/flex/engines/graph_db/grin/src/topology/adjacentlist.cc @@ -66,16 +66,14 @@ GRIN_ADJACENT_LIST_ITERATOR grin_get_adjacent_list_begin( void grin_destroy_adjacent_list_iter(GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { if (iter.edge_iter != nullptr) { - auto edge_iter = - static_cast(iter.edge_iter); + auto edge_iter = static_cast(iter.edge_iter); delete edge_iter; } } void grin_get_next_adjacent_list_iter(GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { - auto edge_iter = - static_cast(iter.edge_iter); + auto edge_iter = static_cast(iter.edge_iter); edge_iter->next(); } @@ -83,15 +81,13 @@ bool grin_is_adjacent_list_end(GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { if (iter.edge_iter == nullptr) { return true; } - auto edge_iter = - static_cast(iter.edge_iter); + auto edge_iter = static_cast(iter.edge_iter); return !edge_iter->is_valid(); } GRIN_VERTEX grin_get_neighbor_from_adjacent_list_iter( GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { - auto edge_iter = - static_cast(iter.edge_iter); + auto edge_iter = static_cast(iter.edge_iter); auto vid = edge_iter->get_neighbor(); auto label = iter.adj_list.edge_label; @@ -105,8 +101,7 @@ GRIN_VERTEX grin_get_neighbor_from_adjacent_list_iter( GRIN_EDGE grin_get_edge_from_adjacent_list_iter( GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { - auto edge_iter = - static_cast(iter.edge_iter); + auto edge_iter = static_cast(iter.edge_iter); GRIN_EDGE_T* edge = new GRIN_EDGE_T(); auto nbr = grin_get_neighbor_from_adjacent_list_iter(g, iter); if (iter.adj_list.dir == GRIN_DIRECTION::IN) { diff --git a/flex/engines/hqps_db/database/adj_list.h b/flex/engines/hqps_db/database/adj_list.h index ddacc4dfb682..9e01f3bebf06 100644 --- a/flex/engines/hqps_db/database/adj_list.h +++ b/flex/engines/hqps_db/database/adj_list.h @@ -21,7 +21,7 @@ #include #include "flex/engines/hqps_db/core/null_record.h" -#include "flex/storages/rt_mutable_graph/mutable_csr.h" +#include "flex/storages/rt_mutable_graph/csr/mutable_csr.h" #include "flex/utils/property/types.h" namespace gs { @@ -40,7 +40,7 @@ class EdgeIter { ptr1_(other.ptr1_), prop_names_(other.prop_names_) {} EdgeIter(const std::array& label_triplet, - std::shared_ptr ptr, + std::shared_ptr ptr, const std::vector* prop_names) : label_triplet_(label_triplet), ptr1_(ptr), prop_names_(prop_names) {} @@ -72,7 +72,7 @@ class EdgeIter { private: std::array label_triplet_; - std::shared_ptr ptr1_; + std::shared_ptr ptr1_; const std::vector* prop_names_; }; @@ -83,8 +83,7 @@ class SubGraph { public: using iterator = EdgeIter; using label_id_t = LabelT; - SubGraph(const MutableCsrBase* first, - const std::array& label_triplet, + SubGraph(const CsrBase* first, const std::array& label_triplet, const std::vector& prop_names) : first_(first), label_triplet_(label_triplet), prop_names_(prop_names) {} @@ -103,7 +102,7 @@ class SubGraph { const std::vector& GetPropNames() const { return prop_names_; } private: - const MutableCsrBase* first_; + const CsrBase* first_; // We assume first is out edge, second is in edge. std::array label_triplet_; std::vector prop_names_; @@ -477,7 +476,7 @@ class AdjListArray {}; template class AdjListArray { public: - using csr_base_t = MutableCsrBase; + using csr_base_t = CsrBase; using typed_csr_base_t = MutableCsr; using slice_t = MutableNbrSlice; AdjListArray() = default; @@ -557,7 +556,7 @@ class AdjListArray { template <> class AdjListArray { public: - using csr_base_t = MutableCsrBase; + using csr_base_t = CsrBase; using typed_csr_base_t = MutableCsr; using slice_t = MutableNbrSlice; AdjListArray() = default; diff --git a/flex/engines/hqps_db/database/mutable_csr_interface.h b/flex/engines/hqps_db/database/mutable_csr_interface.h index ebec57b434f3..b3b566ee9655 100644 --- a/flex/engines/hqps_db/database/mutable_csr_interface.h +++ b/flex/engines/hqps_db/database/mutable_csr_interface.h @@ -498,7 +498,7 @@ class MutableCSRInterface { GetSubGraph(const label_id_t src_label_id, const label_id_t dst_label_id, const label_id_t edge_label_id, const std::string& direction_str, const std::vector& prop_names) const { - const MutableCsrBase *csr = nullptr, *other_csr = nullptr; + const CsrBase *csr = nullptr, *other_csr = nullptr; if (direction_str == "out" || direction_str == "Out" || direction_str == "OUT") { csr = db_session_.graph().get_oe_csr(src_label_id, dst_label_id, diff --git a/flex/storages/rt_mutable_graph/csr/adj_list.h b/flex/storages/rt_mutable_graph/csr/adj_list.h new file mode 100644 index 000000000000..c8e7bcd46fa5 --- /dev/null +++ b/flex/storages/rt_mutable_graph/csr/adj_list.h @@ -0,0 +1,176 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STORAGES_RT_MUTABLE_GRAPH_CSR_ADJ_LIST_H_ +#define STORAGES_RT_MUTABLE_GRAPH_CSR_ADJ_LIST_H_ + +#include "flex/storages/rt_mutable_graph/csr/nbr.h" +#include "flex/storages/rt_mutable_graph/types.h" +#include "flex/utils/allocators.h" + +namespace gs { + +template +struct UninitializedUtils { + static void copy(T* new_buffer, T* old_buffer, size_t len) { + memcpy((void*) new_buffer, (void*) old_buffer, len * sizeof(T)); + } +}; + +template +class MutableAdjlist { + public: + using nbr_t = MutableNbr; + using slice_t = MutableNbrSlice; + using mut_slice_t = MutableNbrSliceMut; + MutableAdjlist() : buffer_(NULL), size_(0), capacity_(0) {} + MutableAdjlist(const MutableAdjlist& rhs) + : buffer_(rhs.buffer_), + size_(rhs.size_.load(std::memory_order_acquire)), + capacity_(rhs.capacity_) {} + ~MutableAdjlist() {} + + void init(nbr_t* ptr, int cap, int size) { + buffer_ = ptr; + capacity_ = cap; + size_ = size; + } + + void batch_put_edge(vid_t neighbor, const EDATA_T& data, timestamp_t ts = 0) { + CHECK_LT(size_, capacity_); + auto& nbr = buffer_[size_++]; + nbr.neighbor = neighbor; + nbr.data = data; + nbr.timestamp.store(ts); + } + + void put_edge(vid_t neighbor, const EDATA_T& data, timestamp_t ts, + Allocator& allocator) { + if (size_ == capacity_) { + capacity_ += ((capacity_) >> 1); + capacity_ = std::max(capacity_, 8); + nbr_t* new_buffer = + static_cast(allocator.allocate(capacity_ * sizeof(nbr_t))); + if (size_ > 0) { + UninitializedUtils::copy(new_buffer, buffer_, size_); + } + buffer_ = new_buffer; + } + auto& nbr = buffer_[size_.fetch_add(1)]; + nbr.neighbor = neighbor; + nbr.data = data; + nbr.timestamp.store(ts); + } + + slice_t get_edges() const { + slice_t ret; + ret.set_size(size_.load(std::memory_order_acquire)); + ret.set_begin(buffer_); + return ret; + } + + mut_slice_t get_edges_mut() { + mut_slice_t ret; + ret.set_size(size_.load()); + ret.set_begin(buffer_); + return ret; + } + + int capacity() const { return capacity_; } + int size() const { return size_; } + const nbr_t* data() const { return buffer_; } + nbr_t* data() { return buffer_; } + + private: + nbr_t* buffer_; + std::atomic size_; + int capacity_; +}; + +template <> +class MutableAdjlist { + public: + using nbr_t = MutableNbr; + using slice_t = MutableNbrSlice; + using mut_slice_t = MutableNbrSliceMut; + MutableAdjlist(StringColumn& column) + : buffer_(NULL), size_(0), capacity_(0) {} + MutableAdjlist(const MutableAdjlist& rhs) + : buffer_(rhs.buffer_), + size_(rhs.size_.load(std::memory_order_acquire)), + capacity_(rhs.capacity_) {} + + ~MutableAdjlist() {} + + void init(nbr_t* ptr, int cap, int size) { + buffer_ = ptr; + capacity_ = cap; + size_ = size; + } + + void batch_put_edge(vid_t neighbor, const size_t& data, timestamp_t ts = 0) { + CHECK_LT(size_, capacity_); + auto& nbr = buffer_[size_++]; + nbr.neighbor = neighbor; + nbr.data = data; + nbr.timestamp.store(ts); + } + + void put_edge(vid_t neighbor, const size_t& data, timestamp_t ts, + Allocator& allocator) { + if (size_ == capacity_) { + capacity_ += ((capacity_) >> 1); + capacity_ = std::max(capacity_, 8); + nbr_t* new_buffer = + static_cast(allocator.allocate(capacity_ * sizeof(nbr_t))); + if (size_ > 0) { + UninitializedUtils::copy(new_buffer, buffer_, size_); + } + buffer_ = new_buffer; + } + auto& nbr = buffer_[size_.fetch_add(1)]; + nbr.neighbor = neighbor; + nbr.data = data; + nbr.timestamp.store(ts); + } + + slice_t get_edges(const StringColumn& column) const { + slice_t ret(column); + ret.set_size(size_.load(std::memory_order_acquire)); + ret.set_begin(buffer_); + return ret; + } + + mut_slice_t get_edges_mut(StringColumn& column) { + mut_slice_t ret(column); + ret.set_size(size_.load()); + ret.set_begin(buffer_); + return ret; + } + + int capacity() const { return capacity_; } + int size() const { return size_; } + const nbr_t* data() const { return buffer_; } + nbr_t* data() { return buffer_; } + + private: + nbr_t* buffer_; + std::atomic size_; + int capacity_; +}; + +} // namespace gs + +#endif // STORAGES_RT_MUTABLE_GRAPH_CSR_ADJ_LIST_H_ diff --git a/flex/storages/rt_mutable_graph/csr/csr_base.h b/flex/storages/rt_mutable_graph/csr/csr_base.h new file mode 100644 index 000000000000..8129d010fed9 --- /dev/null +++ b/flex/storages/rt_mutable_graph/csr/csr_base.h @@ -0,0 +1,133 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STORAGES_RT_MUTABLE_GRAPH_CSR_CSR_BASE_H_ +#define STORAGES_RT_MUTABLE_GRAPH_CSR_CSR_BASE_H_ + +#include +#include + +#include "flex/storages/rt_mutable_graph/csr/nbr.h" +#include "flex/storages/rt_mutable_graph/types.h" + +namespace gs { + +class CsrConstEdgeIterBase { + public: + CsrConstEdgeIterBase() = default; + virtual ~CsrConstEdgeIterBase() = default; + + virtual vid_t get_neighbor() const = 0; + virtual Any get_data() const = 0; + virtual timestamp_t get_timestamp() const = 0; + virtual size_t size() const = 0; + + virtual CsrConstEdgeIterBase& operator+=(size_t offset) = 0; + + virtual void next() = 0; + virtual bool is_valid() const = 0; +}; + +class CsrEdgeIterBase { + public: + CsrEdgeIterBase() = default; + virtual ~CsrEdgeIterBase() = default; + + virtual vid_t get_neighbor() const = 0; + virtual Any get_data() const = 0; + virtual timestamp_t get_timestamp() const = 0; + virtual size_t size() const = 0; + + virtual CsrEdgeIterBase& operator+=(size_t offset) = 0; + + virtual void next() = 0; + virtual bool is_valid() const = 0; + + virtual void set_data(const Any& value, timestamp_t ts) = 0; +}; + +class CsrBase { + public: + CsrBase() = default; + virtual ~CsrBase() = default; + virtual size_t batch_init(const std::string& name, + const std::string& work_dir, + const std::vector& degree, + double reserve_ratio = 1.2) = 0; + virtual void batch_sort_by_edge_data(timestamp_t ts) { + LOG(FATAL) << "not supported..."; + } + virtual timestamp_t unsorted_since() const { return 0; } + + virtual void open(const std::string& name, const std::string& snapshot_dir, + const std::string& work_dir) = 0; + + virtual void open_in_memory(const std::string& prefix, size_t v_cap) = 0; + + virtual void open_with_hugepages(const std::string& prefix, + size_t v_cap = 0) { + LOG(FATAL) << "not supported..."; + } + + virtual void dump(const std::string& name, + const std::string& new_spanshot_dir) = 0; + + virtual void warmup(int thread_num) const = 0; + + virtual void resize(vid_t vnum) = 0; + virtual size_t size() const = 0; + + virtual std::shared_ptr edge_iter(vid_t v) const = 0; + virtual CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const = 0; + virtual std::shared_ptr edge_iter_mut(vid_t v) = 0; +}; + +template +class TypedCsrBase : public CsrBase { + public: + virtual void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, + timestamp_t ts = 0) = 0; + virtual void put_edge(vid_t src, vid_t dst, const EDATA_T& data, + timestamp_t ts, Allocator& alloc) = 0; +}; + +template <> +class TypedCsrBase : public CsrBase { + public: + virtual void batch_put_edge_with_index(vid_t src, vid_t dst, size_t index, + timestamp_t ts = 0) = 0; + virtual void put_edge_with_index(vid_t src, vid_t dst, size_t index, + timestamp_t ts, Allocator& alloc) = 0; +}; + +template +class TypedImmutableCsrBase : public TypedCsrBase { + public: + using slice_t = ImmutableNbrSlice; + + virtual slice_t get_edges(vid_t v) const = 0; +}; + +template +class TypedMutableCsrBase : public TypedCsrBase { + public: + using slice_t = MutableNbrSlice; + + virtual slice_t get_edges(vid_t v) const = 0; +}; + +} // namespace gs + +#endif // STORAGES_RT_MUTABLE_GRAPH_CSR_CSR_BASE_H_ \ No newline at end of file diff --git a/flex/storages/rt_mutable_graph/csr/immutable_csr.h b/flex/storages/rt_mutable_graph/csr/immutable_csr.h new file mode 100644 index 000000000000..e8a6b5361477 --- /dev/null +++ b/flex/storages/rt_mutable_graph/csr/immutable_csr.h @@ -0,0 +1,601 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STORAGES_RT_MUTABLE_GRAPH_CSR_IMMUTABLE_CSR_H_ +#define STORAGES_RT_MUTABLE_GRAPH_CSR_IMMUTABLE_CSR_H_ + +namespace gs { + +template +class ImmutableCsrConstEdgeIter : public CsrConstEdgeIterBase { + using const_nbr_ptr_t = typename ImmutableNbrSlice::const_nbr_ptr_t; + + public: + explicit ImmutableCsrConstEdgeIter(const ImmutableNbrSlice& slice) + : cur_(slice.begin()), end_(slice.end()) {} + ~ImmutableCsrConstEdgeIter() = default; + + vid_t get_neighbor() const override { return (*cur_).get_neighbor(); } + Any get_data() const override { + return AnyConverter::to_any((*cur_).get_data()); + } + timestamp_t get_timestamp() const override { return 0; } + + void next() override { ++cur_; } + CsrConstEdgeIterBase& operator+=(size_t offset) override { + cur_ += offset; + if (!(cur_ < end_)) { + cur_ = end_; + } + return *this; + } + bool is_valid() const override { return cur_ != end_; } + size_t size() const override { return end_ - cur_; } + + private: + const_nbr_ptr_t cur_; + const_nbr_ptr_t end_; +}; + +template +class ImmutableCsr : public TypedImmutableCsrBase { + public: + using nbr_t = ImmutableNbr; + using slice_t = ImmutableNbrSlice; + + size_t batch_init(const std::string& name, const std::string& work_dir, + const std::vector& degree, + double reserve_ratio) override { + size_t vnum = degree.size(); + adj_lists_.open(work_dir + "/" + name + ".adj", true); + adj_lists_.resize(vnum); + + size_t edge_num = 0; + for (auto d : degree) { + edge_num += d; + } + + nbr_list_.open(work_dir + "/" + name + ".nbr", true); + nbr_list_.resize(edge_num); + + degree_list_.open(work_dir + "/" + name + ".deg", true); + degree_list_.resize(vnum); + + nbr_t* ptr = nbr_list_.data(); + for (vid_t i = 0; i < vnum; ++i) { + int deg = degree[i]; + if (deg != 0) { + adj_lists_[i] = ptr; + } else { + adj_lists_[i] = NULL; + } + ptr += deg; + + degree_list_[i] = 0; + } + + unsorted_since_ = 0; + return edge_num; + } + + void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, + timestamp_t ts) override { + auto& nbr = adj_lists_[src][degree_list_[src]++]; + nbr.neighbor = dst; + nbr.data = data; + } + + void batch_sort_by_edge_data(timestamp_t ts) override { + size_t vnum = adj_lists_.size(); + for (size_t i = 0; i != vnum; ++i) { + std::sort(adj_lists_[i], adj_lists_[i] + degree_list_[i], + [](const nbr_t& lhs, const nbr_t& rhs) { + return lhs.data < rhs.data; + }); + } + unsorted_since_ = ts; + } + + timestamp_t unsorted_since() const override { return unsorted_since_; } + + void open(const std::string& name, const std::string& snapshot_dir, + const std::string& work_dir) override { + // Changes made to the CSR will not be synchronized to the file + // TODO(luoxiaojian): Implement the insert operation on ImmutableCsr. + if (snapshot_dir != "") { + degree_list_.open(snapshot_dir + "/" + name + ".deg", false); + nbr_list_.open(snapshot_dir + "/" + name + ".nbr", false); + load_meta(snapshot_dir + "/" + name); + } + + adj_lists_.open(work_dir + "/" + name + ".adj", true); + adj_lists_.resize(degree_list_.size()); + + nbr_t* ptr = nbr_list_.data(); + for (size_t i = 0; i < degree_list_.size(); ++i) { + int deg = degree_list_[i]; + adj_lists_[i] = ptr; + ptr += deg; + } + } + + void open_in_memory(const std::string& prefix, size_t v_cap) override { + degree_list_.open(prefix + ".deg", false); + load_meta(prefix); + nbr_list_.open(prefix + ".nbr", false); + adj_lists_.reset(); + v_cap = std::max(v_cap, degree_list_.size()); + adj_lists_.resize(v_cap); + size_t old_degree_size = degree_list_.size(); + degree_list_.resize(v_cap); + + nbr_t* ptr = nbr_list_.data(); + for (size_t i = 0; i < old_degree_size; ++i) { + int deg = degree_list_[i]; + if (deg != 0) { + adj_lists_[i] = ptr; + } else { + adj_lists_[i] = NULL; + } + ptr += deg; + } + for (size_t i = old_degree_size; i < degree_list_.size(); ++i) { + degree_list_[i] = 0; + adj_lists_[i] = NULL; + } + } + + void open_with_hugepages(const std::string& prefix, size_t v_cap) override { + degree_list_.open_with_hugepages(prefix + ".deg", v_cap); + load_meta(prefix); + nbr_list_.open_with_hugepages(prefix + ".nbr"); + adj_lists_.reset(); + v_cap = std::max(v_cap, degree_list_.size()); + adj_lists_.resize(v_cap); + size_t old_degree_size = degree_list_.size(); + degree_list_.resize(v_cap); + + nbr_t* ptr = nbr_list_.data(); + for (size_t i = 0; i < old_degree_size; ++i) { + int deg = degree_list_[i]; + if (deg != 0) { + adj_lists_[i] = ptr; + } else { + adj_lists_[i] = NULL; + } + ptr += deg; + } + for (size_t i = old_degree_size; i < degree_list_.size(); ++i) { + degree_list_[i] = 0; + adj_lists_[i] = NULL; + } + } + + void dump(const std::string& name, + const std::string& new_snapshot_dir) override { + dump_meta(new_snapshot_dir + "/" + name); + size_t vnum = adj_lists_.size(); + { + FILE* fout = + fopen((new_snapshot_dir + "/" + name + ".deg").c_str(), "wb"); + fwrite(degree_list_.data(), sizeof(int), vnum, fout); + fflush(fout); + fclose(fout); + } + { + FILE* fout = + fopen((new_snapshot_dir + "/" + name + ".nbr").c_str(), "wb"); + for (size_t k = 0; k < vnum; ++k) { + if (adj_lists_[k] != NULL && degree_list_[k] != 0) { + fwrite(adj_lists_[k], sizeof(nbr_t), degree_list_[k], fout); + } + } + fflush(fout); + fclose(fout); + } + } + + void warmup(int thread_num) const override {} + + void resize(vid_t vnum) override { + if (vnum > adj_lists_.size()) { + size_t old_size = adj_lists_.size(); + adj_lists_.resize(vnum); + for (size_t k = old_size; k != vnum; ++k) { + adj_lists_[k] = NULL; + degree_list_[k] = 0; + } + } else { + adj_lists_.resize(vnum); + degree_list_.resize(vnum); + } + } + + size_t size() const override { return adj_lists_.size(); } + + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>(get_edges(v)); + } + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new ImmutableCsrConstEdgeIter(get_edges(v)); + } + std::shared_ptr edge_iter_mut(vid_t v) override { + return nullptr; + } + + void put_edge(vid_t src, vid_t dst, const EDATA_T& data, timestamp_t ts, + Allocator& alloc) override { + LOG(FATAL) << "Put single edge is not supported"; + } + + slice_t get_edges(vid_t v) const override { + slice_t ret; + ret.set_begin(adj_lists_[v]); + ret.set_size(degree_list_[v]); + return ret; + } + + private: + void load_meta(const std::string& prefix) { + std::string meta_file_path = prefix + ".meta"; + if (std::filesystem::exists(meta_file_path)) { + FILE* meta_file_fd = fopen(meta_file_path.c_str(), "r"); + CHECK_EQ(fread(&unsorted_since_, sizeof(timestamp_t), 1, meta_file_fd), + 1); + fclose(meta_file_fd); + } else { + unsorted_since_ = 0; + } + } + + void dump_meta(const std::string& prefix) const { + std::string meta_file_path = prefix + ".meta"; + FILE* meta_file_fd = fopen((prefix + ".meta").c_str(), "wb"); + CHECK_EQ(fwrite(&unsorted_since_, sizeof(timestamp_t), 1, meta_file_fd), 1); + fflush(meta_file_fd); + fclose(meta_file_fd); + } + + mmap_array adj_lists_; + mmap_array degree_list_; + mmap_array nbr_list_; + timestamp_t unsorted_since_; +}; + +template +class SingleImmutableCsr : public TypedImmutableCsrBase { + public: + using nbr_t = ImmutableNbr; + using slice_t = ImmutableNbrSlice; + + SingleImmutableCsr() {} + ~SingleImmutableCsr() {} + + size_t batch_init(const std::string& name, const std::string& work_dir, + const std::vector& degree, + double reserve_ratio) override { + size_t vnum = degree.size(); + nbr_list_.open(work_dir + "/" + name + ".snbr", true); + nbr_list_.resize(vnum); + for (size_t k = 0; k != vnum; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + return vnum; + } + + void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, + timestamp_t ts) override { + CHECK_EQ(nbr_list_[src].neighbor, std::numeric_limits::max()); + nbr_list_[src].neighbor = dst; + nbr_list_[src].data = data; + } + + void batch_sort_by_edge_data(timestamp_t ts) override {} + + timestamp_t unsorted_since() const override { + return std::numeric_limits::max(); + } + + void open(const std::string& name, const std::string& snapshot_dir, + const std::string& work_dir) override { + if (!std::filesystem::exists(work_dir + "/" + name + ".snbr")) { + copy_file(snapshot_dir + "/" + name + ".snbr", + work_dir + "/" + name + ".snbr"); + } + nbr_list_.open(work_dir + "/" + name + ".snbr", true); + } + + void open_in_memory(const std::string& prefix, size_t v_cap) override { + nbr_list_.open(prefix + ".snbr", false); + if (nbr_list_.size() < v_cap) { + size_t old_size = nbr_list_.size(); + nbr_list_.reset(); + nbr_list_.resize(v_cap); + FILE* fin = fopen((prefix + ".snbr").c_str(), "r"); + CHECK_EQ(fread(nbr_list_.data(), sizeof(nbr_t), old_size, fin), old_size); + fclose(fin); + for (size_t k = old_size; k != v_cap; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + } + } + + void open_with_hugepages(const std::string& prefix, size_t v_cap) override { + nbr_list_.open_with_hugepages(prefix + ".snbr", v_cap); + size_t old_size = nbr_list_.size(); + if (old_size < v_cap) { + nbr_list_.resize(v_cap); + for (size_t k = old_size; k != v_cap; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + } + } + + void dump(const std::string& name, + const std::string& new_snapshot_dir) override { + assert(!nbr_list_.filename().empty() && + std::filesystem::exists(nbr_list_.filename())); + std::filesystem::create_hard_link(nbr_list_.filename(), + new_snapshot_dir + "/" + name + ".snbr"); + } + + void warmup(int thread_num) const override { + size_t vnum = nbr_list_.size(); + std::vector threads; + std::atomic v_i(0); + std::atomic output(0); + const size_t chunk = 4096; + for (int i = 0; i < thread_num; ++i) { + threads.emplace_back([&]() { + size_t ret = 0; + while (true) { + size_t begin = std::min(v_i.fetch_add(chunk), vnum); + size_t end = std::min(begin + chunk, vnum); + if (begin == end) { + break; + } + while (begin < end) { + auto& nbr = nbr_list_[begin]; + ret += nbr.neighbor; + ++begin; + } + } + output.fetch_add(ret); + }); + } + for (auto& thrd : threads) { + thrd.join(); + } + (void) output.load(); + } + + void resize(vid_t vnum) override { + if (vnum > nbr_list_.size()) { + size_t old_size = nbr_list_.size(); + nbr_list_.resize(vnum); + for (size_t k = old_size; k != vnum; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + } else { + nbr_list_.resize(vnum); + } + } + + size_t size() const override { return nbr_list_.size(); } + + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>(get_edges(v)); + } + + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new ImmutableCsrConstEdgeIter(get_edges(v)); + } + + std::shared_ptr edge_iter_mut(vid_t v) override { + return nullptr; + } + + void put_edge(vid_t src, vid_t dst, const EDATA_T& data, timestamp_t ts, + Allocator&) override { + CHECK_LT(src, nbr_list_.size()); + CHECK_EQ(nbr_list_[src].neighbor, std::numeric_limits::max()); + nbr_list_[src].neighbor = dst; + nbr_list_[src].data = data; + } + + slice_t get_edges(vid_t i) const override { + slice_t ret; + ret.set_size( + nbr_list_[i].neighbor == std::numeric_limits::max() ? 0 : 1); + if (ret.size() != 0) { + ret.set_begin(&nbr_list_[i]); + } + return ret; + } + + const nbr_t& get_edge(vid_t i) const { return nbr_list_[i]; } + + private: + mmap_array nbr_list_; +}; + +template <> +class SingleImmutableCsr + : public TypedImmutableCsrBase { + public: + using nbr_t = ImmutableNbr; + using slice_t = ImmutableNbrSlice; + + SingleImmutableCsr(StringColumn& column) : column_(column) {} + ~SingleImmutableCsr() {} + + size_t batch_init(const std::string& name, const std::string& work_dir, + const std::vector& degree, + double reserve_ratio) override { + size_t vnum = degree.size(); + nbr_list_.open(work_dir + "/" + name + ".snbr", true); + nbr_list_.resize(vnum); + for (size_t k = 0; k != vnum; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + return vnum; + } + + void batch_put_edge_with_index(vid_t src, vid_t dst, size_t data, + timestamp_t ts) override { + CHECK_EQ(nbr_list_[src].neighbor, std::numeric_limits::max()); + nbr_list_[src].neighbor = dst; + nbr_list_[src].data = data; + } + + void batch_sort_by_edge_data(timestamp_t ts) override {} + + timestamp_t unsorted_since() const override { + return std::numeric_limits::max(); + } + + void open(const std::string& name, const std::string& snapshot_dir, + const std::string& work_dir) override { + if (!std::filesystem::exists(work_dir + "/" + name + ".snbr")) { + copy_file(snapshot_dir + "/" + name + ".snbr", + work_dir + "/" + name + ".snbr"); + } + nbr_list_.open(work_dir + "/" + name + ".snbr", true); + } + + void open_in_memory(const std::string& prefix, size_t v_cap) override { + nbr_list_.open(prefix + ".snbr", false); + if (nbr_list_.size() < v_cap) { + size_t old_size = nbr_list_.size(); + nbr_list_.reset(); + nbr_list_.resize(v_cap); + FILE* fin = fopen((prefix + ".snbr").c_str(), "r"); + CHECK_EQ(fread(nbr_list_.data(), sizeof(nbr_t), old_size, fin), old_size); + fclose(fin); + for (size_t k = old_size; k != v_cap; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + } + } + + void open_with_hugepages(const std::string& prefix, size_t v_cap) override { + nbr_list_.open_with_hugepages(prefix + ".snbr", v_cap); + size_t old_size = nbr_list_.size(); + if (old_size < v_cap) { + nbr_list_.resize(v_cap); + for (size_t k = old_size; k != v_cap; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + } + } + + void dump(const std::string& name, + const std::string& new_snapshot_dir) override { + assert(!nbr_list_.filename().empty() && + std::filesystem::exists(nbr_list_.filename())); + std::filesystem::create_hard_link(nbr_list_.filename(), + new_snapshot_dir + "/" + name + ".snbr"); + } + + void warmup(int thread_num) const override { + size_t vnum = nbr_list_.size(); + std::vector threads; + std::atomic v_i(0); + std::atomic output(0); + const size_t chunk = 4096; + for (int i = 0; i < thread_num; ++i) { + threads.emplace_back([&]() { + size_t ret = 0; + while (true) { + size_t begin = std::min(v_i.fetch_add(chunk), vnum); + size_t end = std::min(begin + chunk, vnum); + if (begin == end) { + break; + } + while (begin < end) { + auto& nbr = nbr_list_[begin]; + ret += nbr.neighbor; + ++begin; + } + } + output.fetch_add(ret); + }); + } + for (auto& thrd : threads) { + thrd.join(); + } + (void) output.load(); + } + + void resize(vid_t vnum) override { + if (vnum > nbr_list_.size()) { + size_t old_size = nbr_list_.size(); + nbr_list_.resize(vnum); + for (size_t k = old_size; k != vnum; ++k) { + nbr_list_[k].neighbor = std::numeric_limits::max(); + } + } else { + nbr_list_.resize(vnum); + } + } + + size_t size() const override { return nbr_list_.size(); } + + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>( + get_edges(v)); + } + + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new ImmutableCsrConstEdgeIter(get_edges(v)); + } + + std::shared_ptr edge_iter_mut(vid_t v) override { + return nullptr; + } + + void put_edge_with_index(vid_t src, vid_t dst, size_t data, timestamp_t ts, + Allocator&) override { + CHECK_LT(src, nbr_list_.size()); + CHECK_EQ(nbr_list_[src].neighbor, std::numeric_limits::max()); + nbr_list_[src].neighbor = dst; + nbr_list_[src].data = data; + } + + slice_t get_edges(vid_t i) const override { + slice_t ret(column_); + ret.set_size( + nbr_list_[i].neighbor == std::numeric_limits::max() ? 0 : 1); + if (ret.size() != 0) { + ret.set_begin(&nbr_list_[i]); + } + return ret; + } + + ImmutableNbr get_edge(vid_t i) const { + ImmutableNbr nbr; + nbr.neighbor = nbr_list_[i].neighbor; + nbr.data = column_.get_view(nbr_list_[i].data); + return nbr; + } + + private: + StringColumn& column_; + mmap_array nbr_list_; +}; + +} // namespace gs + +#endif // STORAGES_RT_MUTABLE_GRAPH_CSR_IMMUTABLE_CSR_H_ \ No newline at end of file diff --git a/flex/storages/rt_mutable_graph/mutable_csr.cc b/flex/storages/rt_mutable_graph/csr/mutable_csr.cc similarity index 96% rename from flex/storages/rt_mutable_graph/mutable_csr.cc rename to flex/storages/rt_mutable_graph/csr/mutable_csr.cc index 3467741dd421..3949cd80f789 100644 --- a/flex/storages/rt_mutable_graph/mutable_csr.cc +++ b/flex/storages/rt_mutable_graph/csr/mutable_csr.cc @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "flex/storages/rt_mutable_graph/mutable_csr.h" +#include "flex/storages/rt_mutable_graph/csr/mutable_csr.h" #include "grape/serialization/in_archive.h" #include "grape/serialization/out_archive.h" diff --git a/flex/storages/rt_mutable_graph/mutable_csr.h b/flex/storages/rt_mutable_graph/csr/mutable_csr.h similarity index 55% rename from flex/storages/rt_mutable_graph/mutable_csr.h rename to flex/storages/rt_mutable_graph/csr/mutable_csr.h index ef5271deb965..24649cac3d0a 100644 --- a/flex/storages/rt_mutable_graph/mutable_csr.h +++ b/flex/storages/rt_mutable_graph/csr/mutable_csr.h @@ -13,531 +13,27 @@ * limitations under the License. */ -#ifndef GRAPHSCOPE_GRAPH_MUTABLE_CSR_H_ -#define GRAPHSCOPE_GRAPH_MUTABLE_CSR_H_ +#ifndef STORAGES_RT_MUTABLE_GRAPH_CSR_MUTABLE_CSR_H_ +#define STORAGES_RT_MUTABLE_GRAPH_CSR_MUTABLE_CSR_H_ -#include -#include -#include #include -#include -#include - -#include "flex/storages/rt_mutable_graph/types.h" -#include "flex/utils/allocators.h" -#include "flex/utils/mmap_array.h" -#include "flex/utils/property/column.h" -#include "flex/utils/property/types.h" -#include "grape/serialization/in_archive.h" -#include "grape/serialization/out_archive.h" -#include "grape/utils/concurrent_queue.h" - -namespace gs { - -template -struct MutableNbr { - MutableNbr() = default; - MutableNbr(const MutableNbr& rhs) - : neighbor(rhs.neighbor), - timestamp(rhs.timestamp.load()), - data(rhs.data) {} - ~MutableNbr() = default; - - MutableNbr& operator=(const MutableNbr& rhs) { - neighbor = rhs.neighbor; - timestamp.store(rhs.timestamp.load()); - data = rhs.data; - return *this; - } - - const EDATA_T& get_data() const { return data; } - vid_t get_neighbor() const { return neighbor; } - timestamp_t get_timestamp() const { return timestamp.load(); } - - void set_data(const EDATA_T& val, timestamp_t ts) { - data = val; - timestamp.store(ts); - } - void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } - void set_timestamp(timestamp_t ts) { timestamp.store(ts); } - - vid_t neighbor; - std::atomic timestamp; - EDATA_T data; -}; - -template <> -struct MutableNbr { - MutableNbr() = default; - MutableNbr(const MutableNbr& rhs) - : neighbor(rhs.neighbor), timestamp(rhs.timestamp.load()) {} - ~MutableNbr() = default; - - MutableNbr& operator=(const MutableNbr& rhs) { - neighbor = rhs.neighbor; - timestamp.store(rhs.timestamp.load()); - return *this; - } - - void set_data(const grape::EmptyType&, timestamp_t ts) { - timestamp.store(ts); - } - void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } - void set_timestamp(timestamp_t ts) { timestamp.store(ts); } - const grape::EmptyType& get_data() const { return data; } - vid_t get_neighbor() const { return neighbor; } - timestamp_t get_timestamp() const { return timestamp.load(); } - vid_t neighbor; - union { - std::atomic timestamp; - grape::EmptyType data; - }; -}; - -template -class MutableNbrSlice { - public: - using const_nbr_t = const MutableNbr; - using const_nbr_ptr_t = const MutableNbr*; - MutableNbrSlice() = default; - MutableNbrSlice(const MutableNbrSlice& rhs) - : ptr_(rhs.ptr_), size_(rhs.size_) {} - ~MutableNbrSlice() = default; - - void set_size(int size) { size_ = size; } - int size() const { return size_; } - - void set_begin(const_nbr_ptr_t ptr) { ptr_ = ptr; } - - const_nbr_ptr_t begin() const { return ptr_; } - const_nbr_ptr_t end() const { return ptr_ + size_; } - - static MutableNbrSlice empty() { - MutableNbrSlice ret; - ret.set_begin(nullptr); - ret.set_size(0); - return ret; - } - - private: - const_nbr_ptr_t ptr_; - int size_; -}; - -template <> -class MutableNbrSlice { - public: - struct MutableColumnNbr { - using const_nbr_t = const MutableNbr; - using const_nbr_ptr_t = const MutableNbr*; - - MutableColumnNbr(const_nbr_ptr_t ptr, const StringColumn& column) - : ptr_(ptr), column_(column) {} - vid_t get_neighbor() const { return ptr_->neighbor; } - std::string_view get_data() const { return column_.get_view(ptr_->data); } - timestamp_t get_timestamp() const { return ptr_->timestamp.load(); } - - const MutableColumnNbr& operator*() const { return *this; } - const MutableColumnNbr* operator->() const { return this; } - const MutableColumnNbr& operator=(const MutableColumnNbr& nbr) const { - ptr_ = nbr.ptr_; - return *this; - } - bool operator==(const MutableColumnNbr& nbr) const { - return ptr_ == nbr.ptr_; - } - bool operator!=(const MutableColumnNbr& nbr) const { - return ptr_ != nbr.ptr_; - } - const MutableColumnNbr& operator++() const { - ++ptr_; - return *this; - } - - const MutableColumnNbr& operator+=(size_t n) const { - ptr_ += n; - return *this; - } - - size_t operator-(const MutableColumnNbr& nbr) const { - return ptr_ - nbr.ptr_; - } - - bool operator<(const MutableColumnNbr& nbr) const { - return ptr_ < nbr.ptr_; - } - - mutable const_nbr_ptr_t ptr_; - const StringColumn& column_; - }; - using const_nbr_t = const MutableColumnNbr; - using const_nbr_ptr_t = const MutableColumnNbr; - MutableNbrSlice(const StringColumn& column) : slice_(), column_(column) {} - MutableNbrSlice(const MutableNbrSlice& rhs) - : slice_(rhs.slice_), column_(rhs.column_) {} - ~MutableNbrSlice() = default; - void set_size(int size) { slice_.set_size(size); } - int size() const { return slice_.size(); } - void set_begin(const MutableNbr* ptr) { slice_.set_begin(ptr); } - - const MutableColumnNbr begin() const { - return MutableColumnNbr(slice_.begin(), column_); - } - const MutableColumnNbr end() const { - return MutableColumnNbr(slice_.end(), column_); - } - - static MutableNbrSlice empty(const StringColumn& column) { - MutableNbrSlice ret(column); - ret.set_begin(nullptr); - ret.set_size(0); - return ret; - } - - private: - MutableNbrSlice slice_; - const StringColumn& column_; -}; - -template -class MutableNbrSliceMut { - public: - using nbr_t = MutableNbr; - using nbr_ptr_t = MutableNbr*; - MutableNbrSliceMut() = default; - ~MutableNbrSliceMut() = default; - - void set_size(int size) { size_ = size; } - int size() const { return size_; } - - void set_begin(nbr_t* ptr) { ptr_ = ptr; } - - nbr_t* begin() { return ptr_; } - nbr_t* end() { return ptr_ + size_; } - - static MutableNbrSliceMut empty() { - MutableNbrSliceMut ret; - ret.set_begin(nullptr); - ret.set_size(0); - return ret; - } - - private: - nbr_t* ptr_; - int size_; -}; - -template <> -class MutableNbrSliceMut { - public: - struct MutableColumnNbr { - using nbr_t = MutableNbr; - - MutableColumnNbr(nbr_t* ptr, StringColumn& column) - : ptr_(ptr), column_(column) {} - vid_t neighbor() const { return ptr_->neighbor; } - std::string_view data() { return column_.get_view(ptr_->data); } - vid_t get_neighbor() const { return ptr_->neighbor; } - const std::string_view get_data() const { - return column_.get_view(ptr_->data); - } - timestamp_t get_timestamp() const { return ptr_->timestamp.load(); } - size_t get_index() const { return ptr_->data; } - void set_data(const std::string_view& sw, timestamp_t ts) { - column_.set_value(ptr_->data, sw); - ptr_->timestamp.store(ts); - } - void set_neighbor(vid_t neighbor) { ptr_->neighbor = neighbor; } - - void set_timestamp(timestamp_t ts) { ptr_->timestamp.store(ts); } - - const MutableColumnNbr& operator*() const { return *this; } - MutableColumnNbr& operator*() { return *this; } - MutableColumnNbr& operator=(const MutableColumnNbr& nbr) { - ptr_ = nbr.ptr_; - return *this; - } - bool operator==(const MutableColumnNbr& nbr) const { - return ptr_ == nbr.ptr_; - } - bool operator!=(const MutableColumnNbr& nbr) const { - return ptr_ != nbr.ptr_; - } - - MutableColumnNbr& operator++() { - ptr_++; - return *this; - } - MutableColumnNbr& operator+=(size_t n) { - ptr_ += n; - return *this; - } - - bool operator<(const MutableColumnNbr& nbr) { return ptr_ < nbr.ptr_; } - nbr_t* ptr_; - StringColumn & column_; - }; - using nbr_ptr_t = MutableColumnNbr; - - MutableNbrSliceMut(StringColumn& column) : column_(column) {} - ~MutableNbrSliceMut() = default; - void set_size(int size) { slice_.set_size(size); } - int size() const { return slice_.size(); } - - void set_begin(MutableNbr* ptr) { slice_.set_begin(ptr); } - - MutableColumnNbr begin() { return MutableColumnNbr(slice_.begin(), column_); } - MutableColumnNbr end() { return MutableColumnNbr(slice_.end(), column_); } - - static MutableNbrSliceMut empty(StringColumn& column) { - MutableNbrSliceMut ret(column); - ret.set_begin(nullptr); - ret.set_size(0); - return ret; - } - - private: - MutableNbrSliceMut slice_; - StringColumn& column_; -}; - -template -struct UninitializedUtils { - static void copy(T* new_buffer, T* old_buffer, size_t len) { - memcpy((void*) new_buffer, (void*) old_buffer, len * sizeof(T)); - } -}; - -template -class MutableAdjlist { - public: - using nbr_t = MutableNbr; - using slice_t = MutableNbrSlice; - using mut_slice_t = MutableNbrSliceMut; - MutableAdjlist() : buffer_(NULL), size_(0), capacity_(0) {} - MutableAdjlist(const MutableAdjlist& rhs) - : buffer_(rhs.buffer_), - size_(rhs.size_.load(std::memory_order_acquire)), - capacity_(rhs.capacity_) {} - ~MutableAdjlist() {} - - void init(nbr_t* ptr, int cap, int size) { - buffer_ = ptr; - capacity_ = cap; - size_ = size; - } - - void batch_put_edge(vid_t neighbor, const EDATA_T& data, timestamp_t ts = 0) { - CHECK_LT(size_, capacity_); - auto& nbr = buffer_[size_++]; - nbr.neighbor = neighbor; - nbr.data = data; - nbr.timestamp.store(ts); - } - - void put_edge(vid_t neighbor, const EDATA_T& data, timestamp_t ts, - Allocator& allocator) { - if (size_ == capacity_) { - capacity_ += ((capacity_) >> 1); - capacity_ = std::max(capacity_, 8); - nbr_t* new_buffer = - static_cast(allocator.allocate(capacity_ * sizeof(nbr_t))); - if (size_ > 0) { - UninitializedUtils::copy(new_buffer, buffer_, size_); - } - buffer_ = new_buffer; - } - auto& nbr = buffer_[size_.fetch_add(1)]; - nbr.neighbor = neighbor; - nbr.data = data; - nbr.timestamp.store(ts); - } - - slice_t get_edges() const { - slice_t ret; - ret.set_size(size_.load(std::memory_order_acquire)); - ret.set_begin(buffer_); - return ret; - } - - mut_slice_t get_edges_mut() { - mut_slice_t ret; - ret.set_size(size_.load()); - ret.set_begin(buffer_); - return ret; - } - - int capacity() const { return capacity_; } - int size() const { return size_; } - const nbr_t* data() const { return buffer_; } - nbr_t* data() { return buffer_; } - - private: - nbr_t* buffer_; - std::atomic size_; - int capacity_; -}; - -template <> -class MutableAdjlist { - public: - using nbr_t = MutableNbr; - using slice_t = MutableNbrSlice; - using mut_slice_t = MutableNbrSliceMut; - MutableAdjlist(StringColumn& column) - : buffer_(NULL), size_(0), capacity_(0) {} - MutableAdjlist(const MutableAdjlist& rhs) - : buffer_(rhs.buffer_), - size_(rhs.size_.load(std::memory_order_acquire)), - capacity_(rhs.capacity_) {} - - ~MutableAdjlist() {} - - void init(nbr_t* ptr, int cap, int size) { - buffer_ = ptr; - capacity_ = cap; - size_ = size; - } - - void batch_put_edge(vid_t neighbor, const size_t& data, timestamp_t ts = 0) { - CHECK_LT(size_, capacity_); - auto& nbr = buffer_[size_++]; - nbr.neighbor = neighbor; - nbr.data = data; - nbr.timestamp.store(ts); - } - - void put_edge(vid_t neighbor, const size_t& data, timestamp_t ts, - Allocator& allocator) { - if (size_ == capacity_) { - capacity_ += ((capacity_) >> 1); - capacity_ = std::max(capacity_, 8); - nbr_t* new_buffer = - static_cast(allocator.allocate(capacity_ * sizeof(nbr_t))); - if (size_ > 0) { - UninitializedUtils::copy(new_buffer, buffer_, size_); - } - buffer_ = new_buffer; - } - auto& nbr = buffer_[size_.fetch_add(1)]; - nbr.neighbor = neighbor; - nbr.data = data; - nbr.timestamp.store(ts); - } - - slice_t get_edges(const StringColumn& column) const { - slice_t ret(column); - ret.set_size(size_.load(std::memory_order_acquire)); - ret.set_begin(buffer_); - return ret; - } - - mut_slice_t get_edges_mut(StringColumn& column) { - mut_slice_t ret(column); - ret.set_size(size_.load()); - ret.set_begin(buffer_); - return ret; - } - - int capacity() const { return capacity_; } - int size() const { return size_; } - const nbr_t* data() const { return buffer_; } - nbr_t* data() { return buffer_; } - - private: - nbr_t* buffer_; - std::atomic size_; - int capacity_; -}; - -class MutableCsrConstEdgeIterBase { - public: - MutableCsrConstEdgeIterBase() = default; - virtual ~MutableCsrConstEdgeIterBase() = default; - - virtual vid_t get_neighbor() const = 0; - virtual Any get_data() const = 0; - virtual timestamp_t get_timestamp() const = 0; - virtual size_t size() const = 0; - - virtual MutableCsrConstEdgeIterBase& operator+=(size_t offset) = 0; - - virtual void next() = 0; - virtual bool is_valid() const = 0; -}; - -class MutableCsrEdgeIterBase { - public: - MutableCsrEdgeIterBase() = default; - virtual ~MutableCsrEdgeIterBase() = default; - - virtual vid_t get_neighbor() const = 0; - virtual Any get_data() const = 0; - virtual timestamp_t get_timestamp() const = 0; - virtual void set_data(const Any& value, timestamp_t ts) = 0; - virtual MutableCsrEdgeIterBase& operator+=(size_t offset) = 0; - virtual void next() = 0; - virtual bool is_valid() const = 0; -}; - -class MutableCsrBase { - public: - MutableCsrBase() {} - virtual ~MutableCsrBase() {} - - virtual size_t batch_init(const std::string& name, - const std::string& work_dir, - const std::vector& degree, - double reserve_ratio = 1.2) = 0; - - virtual void batch_sort_by_edge_data(timestamp_t ts) { - LOG(FATAL) << "not supported..."; - } - - virtual timestamp_t unsorted_since() const { return 0; } - - virtual void open(const std::string& name, const std::string& snapshot_dir, - const std::string& work_dir) = 0; - - virtual void open_in_memory(const std::string& prefix, size_t v_cap = 0) = 0; - virtual void open_with_hugepages(const std::string& prefix, - size_t v_cap = 0) { - LOG(FATAL) << "not supported..."; - } - - virtual void dump(const std::string& name, - const std::string& new_spanshot_dir) = 0; - - virtual void warmup(int thread_num) const = 0; - - virtual void resize(vid_t vnum) = 0; - virtual size_t size() const = 0; - virtual void put_generic_edge(vid_t src, vid_t dst, const Any& data, - timestamp_t ts, Allocator& alloc) = 0; - - virtual void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - timestamp_t ts, Allocator& alloc) = 0; - - virtual void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - timestamp_t ts, Allocator& alloc) = 0; - - virtual std::shared_ptr edge_iter( - vid_t v) const = 0; +#include "grape/utils/concurrent_queue.h" - virtual MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const = 0; +#include "flex/storages/rt_mutable_graph/csr/adj_list.h" +#include "flex/storages/rt_mutable_graph/csr/csr_base.h" +#include "flex/storages/rt_mutable_graph/csr/nbr.h" - virtual std::shared_ptr edge_iter_mut(vid_t v) = 0; -}; +namespace gs { template -class TypedMutableCsrConstEdgeIter : public MutableCsrConstEdgeIterBase { +class MutableCsrConstEdgeIter : public CsrConstEdgeIterBase { using const_nbr_ptr_t = typename MutableNbrSlice::const_nbr_ptr_t; public: - explicit TypedMutableCsrConstEdgeIter(const MutableNbrSlice& slice) + explicit MutableCsrConstEdgeIter(const MutableNbrSlice& slice) : cur_(slice.begin()), end_(slice.end()) {} - ~TypedMutableCsrConstEdgeIter() = default; + ~MutableCsrConstEdgeIter() = default; vid_t get_neighbor() const override { return (*cur_).get_neighbor(); } Any get_data() const override { @@ -546,7 +42,7 @@ class TypedMutableCsrConstEdgeIter : public MutableCsrConstEdgeIterBase { timestamp_t get_timestamp() const override { return (*cur_).get_timestamp(); } void next() override { ++cur_; } - TypedMutableCsrConstEdgeIter& operator+=(size_t offset) override { + CsrConstEdgeIterBase& operator+=(size_t offset) override { cur_ += offset; if (!(cur_ < end_)) { cur_ = end_; @@ -562,13 +58,13 @@ class TypedMutableCsrConstEdgeIter : public MutableCsrConstEdgeIterBase { }; template -class TypedMutableCsrEdgeIter : public MutableCsrEdgeIterBase { +class MutableCsrEdgeIter : public CsrEdgeIterBase { using nbr_t = MutableNbr; public: - explicit TypedMutableCsrEdgeIter(MutableNbrSliceMut slice) + explicit MutableCsrEdgeIter(MutableNbrSliceMut slice) : cur_(slice.begin()), end_(slice.end()) {} - ~TypedMutableCsrEdgeIter() = default; + ~MutableCsrEdgeIter() = default; vid_t get_neighbor() const override { return cur_->neighbor; } Any get_data() const override { @@ -581,7 +77,7 @@ class TypedMutableCsrEdgeIter : public MutableCsrEdgeIterBase { cur_->timestamp.store(ts); } - MutableCsrEdgeIterBase& operator+=(size_t offset) override { + CsrEdgeIterBase& operator+=(size_t offset) override { if (cur_ + offset >= end_) { cur_ = end_; } else { @@ -592,6 +88,7 @@ class TypedMutableCsrEdgeIter : public MutableCsrEdgeIterBase { void next() override { ++cur_; } bool is_valid() const override { return cur_ != end_; } + size_t size() const override { return end_ - cur_; } private: nbr_t* cur_; @@ -599,14 +96,13 @@ class TypedMutableCsrEdgeIter : public MutableCsrEdgeIterBase { }; template <> -class TypedMutableCsrEdgeIter - : public MutableCsrEdgeIterBase { +class MutableCsrEdgeIter : public CsrEdgeIterBase { using nbr_ptr_t = typename MutableNbrSliceMut::nbr_ptr_t; public: - explicit TypedMutableCsrEdgeIter(MutableNbrSliceMut slice) + explicit MutableCsrEdgeIter(MutableNbrSliceMut slice) : cur_(slice.begin()), end_(slice.end()) {} - ~TypedMutableCsrEdgeIter() = default; + ~MutableCsrEdgeIter() = default; vid_t get_neighbor() const override { return cur_.get_neighbor(); } Any get_data() const override { @@ -620,7 +116,7 @@ class TypedMutableCsrEdgeIter size_t get_index() const { return cur_.get_index(); } void set_timestamp(timestamp_t ts) { cur_.set_timestamp(ts); } - MutableCsrEdgeIterBase& operator+=(size_t offset) override { + CsrEdgeIterBase& operator+=(size_t offset) override { cur_ += offset; if (!(cur_ < end_)) { cur_ = end_; @@ -630,34 +126,13 @@ class TypedMutableCsrEdgeIter void next() override { ++cur_; } bool is_valid() const override { return cur_ != end_; } + size_t size() const override { return end_.ptr_ - cur_.ptr_; } private: nbr_ptr_t cur_; nbr_ptr_t end_; }; -template -class TypedMutableCsrBase : public MutableCsrBase { - public: - using slice_t = MutableNbrSlice; - virtual void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, - timestamp_t ts = 0) = 0; - virtual void put_edge(vid_t src, vid_t dst, const EDATA_T& data, - timestamp_t ts, Allocator& alloc) = 0; - virtual slice_t get_edges(vid_t i) const = 0; -}; - -template <> -class TypedMutableCsrBase : public MutableCsrBase { - public: - using slice_t = MutableNbrSlice; - virtual slice_t get_edges(vid_t i) const = 0; - virtual void batch_put_edge_with_index(vid_t src, vid_t dst, - const size_t& data, - timestamp_t ts = 0) = 0; - virtual void put_edge_with_index(vid_t src, vid_t dst, size_t index, - timestamp_t ts, Allocator& alloc) = 0; -}; template class MutableCsr : public TypedMutableCsrBase { public: @@ -702,6 +177,25 @@ class MutableCsr : public TypedMutableCsrBase { return edge_num; } + void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, + timestamp_t ts) override { + adj_lists_[src].batch_put_edge(dst, data, ts); + } + + void batch_sort_by_edge_data(timestamp_t ts) override { + size_t vnum = adj_lists_.size(); + for (size_t i = 0; i != vnum; ++i) { + std::sort(adj_lists_[i].data(), + adj_lists_[i].data() + adj_lists_[i].size(), + [](const nbr_t& lhs, const nbr_t& rhs) { + return lhs.data < rhs.data; + }); + } + unsorted_since_ = ts; + } + + timestamp_t unsorted_since() const override { return unsorted_since_; } + void open(const std::string& name, const std::string& snapshot_dir, const std::string& work_dir) override { mmap_array degree_list; @@ -800,40 +294,6 @@ class MutableCsr : public TypedMutableCsrBase { } } - void warmup(int thread_num) const override { - size_t vnum = adj_lists_.size(); - std::vector threads; - std::atomic v_i(0); - const size_t chunk = 4096; - std::atomic output(0); - for (int i = 0; i < thread_num; ++i) { - threads.emplace_back([&]() { - size_t ret = 0; - while (true) { - size_t begin = std::min(v_i.fetch_add(chunk), vnum); - size_t end = std::min(begin + chunk, vnum); - - if (begin == end) { - break; - } - - while (begin < end) { - auto adj_list = get_edges(begin); - for (auto& nbr : adj_list) { - ret += nbr.neighbor; - } - ++begin; - } - } - output.fetch_add(ret); - }); - } - for (auto& thrd : threads) { - thrd.join(); - } - (void) output.load(); - } - void dump(const std::string& name, const std::string& new_spanshot_dir) override { size_t vnum = adj_lists_.size(); @@ -888,6 +348,40 @@ class MutableCsr : public TypedMutableCsrBase { } } + void warmup(int thread_num) const override { + size_t vnum = adj_lists_.size(); + std::vector threads; + std::atomic v_i(0); + const size_t chunk = 4096; + std::atomic output(0); + for (int i = 0; i < thread_num; ++i) { + threads.emplace_back([&]() { + size_t ret = 0; + while (true) { + size_t begin = std::min(v_i.fetch_add(chunk), vnum); + size_t end = std::min(begin + chunk, vnum); + + if (begin == end) { + break; + } + + while (begin < end) { + auto adj_list = get_edges(begin); + for (auto& nbr : adj_list) { + ret += nbr.neighbor; + } + ++begin; + } + } + output.fetch_add(ret); + }); + } + for (auto& thrd : threads) { + thrd.join(); + } + (void) output.load(); + } + void resize(vid_t vnum) override { if (vnum > adj_lists_.size()) { size_t old_size = adj_lists_.size(); @@ -901,19 +395,16 @@ class MutableCsr : public TypedMutableCsrBase { adj_lists_.resize(vnum); } } - size_t size() const override { return adj_lists_.size(); } - void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, - timestamp_t ts = 0) override { - adj_lists_[src].batch_put_edge(dst, data, ts); + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>(get_edges(v)); } - - void put_generic_edge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) override { - EDATA_T value; - ConvertAny::to(data, value); - put_edge(src, dst, value, ts, alloc); + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new MutableCsrConstEdgeIter(get_edges(v)); + } + std::shared_ptr edge_iter_mut(vid_t v) override { + return std::make_shared>(get_edges_mut(v)); } void put_edge(vid_t src, vid_t dst, const EDATA_T& data, timestamp_t ts, @@ -924,53 +415,11 @@ class MutableCsr : public TypedMutableCsrBase { locks_[src].unlock(); } - int degree(vid_t i) const { return adj_lists_[i].size(); } - - slice_t get_edges(vid_t i) const override { - return adj_lists_[i].get_edges(); + slice_t get_edges(vid_t v) const override { + return adj_lists_[v].get_edges(); } - mut_slice_t get_edges_mut(vid_t i) { return adj_lists_[i].get_edges_mut(); } - void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, timestamp_t ts, - Allocator& alloc) override { - EDATA_T value; - arc >> value; - put_edge(src, dst, value, ts, alloc); - } - - void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - timestamp_t ts, Allocator& alloc) override { - EDATA_T value; - arc.Peek(value); - put_edge(src, dst, value, ts, alloc); - } - - std::shared_ptr edge_iter( - vid_t v) const override { - return std::make_shared>( - get_edges(v)); - } - - MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { - return new TypedMutableCsrConstEdgeIter(get_edges(v)); - } - std::shared_ptr edge_iter_mut(vid_t v) override { - return std::make_shared>(get_edges_mut(v)); - } - - void batch_sort_by_edge_data(timestamp_t ts) override { - size_t vnum = adj_lists_.size(); - for (size_t i = 0; i != vnum; ++i) { - std::sort(adj_lists_[i].data(), - adj_lists_[i].data() + adj_lists_[i].size(), - [](const nbr_t& lhs, const nbr_t& rhs) { - return lhs.data < rhs.data; - }); - } - unsorted_since_ = ts; - } - - timestamp_t unsorted_since() const override { return unsorted_since_; } + mut_slice_t get_edges_mut(vid_t i) { return adj_lists_[i].get_edges_mut(); } private: void load_meta(const std::string& prefix) { @@ -1008,8 +457,7 @@ class MutableCsr using slice_t = MutableNbrSlice; using mut_slice_t = MutableNbrSliceMut; - MutableCsr(StringColumn& column, std::atomic& column_idx) - : column_(column), column_idx_(column_idx), locks_(nullptr) {} + MutableCsr(StringColumn& column) : column_(column), locks_(nullptr) {} ~MutableCsr() { if (locks_ != nullptr) { delete[] locks_; @@ -1041,6 +489,11 @@ class MutableCsr return edge_num; } + void batch_put_edge_with_index(vid_t src, vid_t dst, size_t data, + timestamp_t ts) override { + adj_lists_[src].batch_put_edge(dst, data, ts); + } + void open(const std::string& name, const std::string& snapshot_dir, const std::string& work_dir) override { mmap_array degree_list; @@ -1078,40 +531,6 @@ class MutableCsr } } - void warmup(int thread_num) const override { - size_t vnum = adj_lists_.size(); - std::vector threads; - std::atomic v_i(0); - const size_t chunk = 4096; - std::atomic output(0); - for (int i = 0; i < thread_num; ++i) { - threads.emplace_back([&]() { - size_t ret = 0; - while (true) { - size_t begin = std::min(v_i.fetch_add(chunk), vnum); - size_t end = std::min(begin + chunk, vnum); - - if (begin == end) { - break; - } - - while (begin < end) { - auto adj_list = get_edges(begin); - for (auto& nbr : adj_list) { - ret += nbr.get_neighbor(); - } - ++begin; - } - } - output.fetch_add(ret); - }); - } - for (auto& thrd : threads) { - thrd.join(); - } - (void) output.load(); - } - void dump(const std::string& name, const std::string& new_spanshot_dir) override { size_t vnum = adj_lists_.size(); @@ -1148,6 +567,40 @@ class MutableCsr } } + void warmup(int thread_num) const override { + size_t vnum = adj_lists_.size(); + std::vector threads; + std::atomic v_i(0); + const size_t chunk = 4096; + std::atomic output(0); + for (int i = 0; i < thread_num; ++i) { + threads.emplace_back([&]() { + size_t ret = 0; + while (true) { + size_t begin = std::min(v_i.fetch_add(chunk), vnum); + size_t end = std::min(begin + chunk, vnum); + + if (begin == end) { + break; + } + + while (begin < end) { + auto adj_list = get_edges(begin); + for (auto& nbr : adj_list) { + ret += nbr.get_neighbor(); + } + ++begin; + } + } + output.fetch_add(ret); + }); + } + for (auto& thrd : threads) { + thrd.join(); + } + (void) output.load(); + } + void resize(vid_t vnum) override { if (vnum > adj_lists_.size()) { size_t old_size = adj_lists_.size(); @@ -1164,9 +617,17 @@ class MutableCsr size_t size() const override { return adj_lists_.size(); } - void put_generic_edge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) override { - LOG(FATAL) << "not implemented\n"; + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>( + get_edges(v)); + } + + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new MutableCsrConstEdgeIter(get_edges(v)); + } + std::shared_ptr edge_iter_mut(vid_t v) override { + return std::make_shared>( + get_edges_mut(v)); } void put_edge(vid_t src, vid_t dst, size_t data, timestamp_t ts, @@ -1176,57 +637,22 @@ class MutableCsr adj_lists_[src].put_edge(dst, data, ts, alloc); locks_[src].unlock(); } + void put_edge_with_index(vid_t src, vid_t dst, size_t index, timestamp_t ts, Allocator& alloc) override { put_edge(src, dst, index, ts, alloc); } - void batch_put_edge_with_index(vid_t src, vid_t dst, const size_t& data, - timestamp_t ts = 0) override { - adj_lists_[src].batch_put_edge(dst, data, ts); - } - - int degree(vid_t i) const { return adj_lists_[i].size(); } - slice_t get_edges(vid_t i) const override { return adj_lists_[i].get_edges(column_); } + mut_slice_t get_edges_mut(vid_t i) { return adj_lists_[i].get_edges_mut(column_); } - void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, timestamp_t ts, - Allocator& alloc) override { - auto row_id = column_idx_.load(); - put_edge(src, dst, row_id - 1, ts, alloc); - } - - void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - timestamp_t ts, Allocator& alloc) override { - std::string_view sw; - arc >> sw; - auto row_id = column_idx_.fetch_add(1); - column_.set_value(row_id, sw); - put_edge(src, dst, row_id, ts, alloc); - } - - std::shared_ptr edge_iter( - vid_t v) const override { - return std::make_shared>( - get_edges(v)); - } - - MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { - return new TypedMutableCsrConstEdgeIter(get_edges(v)); - } - std::shared_ptr edge_iter_mut(vid_t v) override { - return std::make_shared>( - get_edges_mut(v)); - } - private: StringColumn& column_; - std::atomic& column_idx_; grape::SpinLock* locks_; mmap_array adj_lists_; mmap_array nbr_list_; @@ -1254,6 +680,21 @@ class SingleMutableCsr : public TypedMutableCsrBase { return vnum; } + void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, + timestamp_t ts = 0) override { + nbr_list_[src].neighbor = dst; + nbr_list_[src].data = data; + CHECK_EQ(nbr_list_[src].timestamp.load(), + std::numeric_limits::max()); + nbr_list_[src].timestamp.store(ts); + } + + void batch_sort_by_edge_data(timestamp_t ts) override {} + + timestamp_t unsorted_since() const override { + return std::numeric_limits::max(); + } + void open(const std::string& name, const std::string& snapshot_dir, const std::string& work_dir) override { if (!std::filesystem::exists(work_dir + "/" + name + ".snbr")) { @@ -1297,6 +738,36 @@ class SingleMutableCsr : public TypedMutableCsrBase { new_snapshot_dir + "/" + name + ".snbr"); } + void warmup(int thread_num) const override { + size_t vnum = nbr_list_.size(); + std::vector threads; + std::atomic v_i(0); + std::atomic output(0); + const size_t chunk = 4096; + for (int i = 0; i < thread_num; ++i) { + threads.emplace_back([&]() { + size_t ret = 0; + while (true) { + size_t begin = std::min(v_i.fetch_add(chunk), vnum); + size_t end = std::min(begin + chunk, vnum); + if (begin == end) { + break; + } + while (begin < end) { + auto& nbr = nbr_list_[begin]; + ret += nbr.neighbor; + ++begin; + } + } + output.fetch_add(ret); + }); + } + for (auto& thrd : threads) { + thrd.join(); + } + (void) output.load(); + } + void resize(vid_t vnum) override { if (vnum > nbr_list_.size()) { size_t old_size = nbr_list_.size(); @@ -1311,24 +782,18 @@ class SingleMutableCsr : public TypedMutableCsrBase { size_t size() const override { return nbr_list_.size(); } - void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, - timestamp_t ts = 0) override { - nbr_list_[src].neighbor = dst; - nbr_list_[src].data = data; - CHECK_EQ(nbr_list_[src].timestamp.load(), - std::numeric_limits::max()); - nbr_list_[src].timestamp.store(ts); + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>(get_edges(v)); } - - void put_generic_edge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) override { - EDATA_T value; - ConvertAny::to(data, value); - put_edge(src, dst, value, ts, alloc); + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new MutableCsrConstEdgeIter(get_edges(v)); + } + std::shared_ptr edge_iter_mut(vid_t v) override { + return std::make_shared>(get_edges_mut(v)); } void put_edge(vid_t src, vid_t dst, const EDATA_T& data, timestamp_t ts, - Allocator&) override { + Allocator& alloc) override { CHECK_LT(src, nbr_list_.size()); nbr_list_[src].neighbor = dst; nbr_list_[src].data = data; @@ -1336,14 +801,14 @@ class SingleMutableCsr : public TypedMutableCsrBase { nbr_list_[src].timestamp.store(ts); } - slice_t get_edges(vid_t i) const override { + slice_t get_edges(vid_t v) const override { slice_t ret; - ret.set_size(nbr_list_[i].timestamp.load() == + ret.set_size(nbr_list_[v].timestamp.load() == std::numeric_limits::max() ? 0 : 1); if (ret.size() != 0) { - ret.set_begin(&nbr_list_[i]); + ret.set_begin(&nbr_list_[v]); } return ret; } @@ -1362,70 +827,6 @@ class SingleMutableCsr : public TypedMutableCsrBase { const nbr_t& get_edge(vid_t i) const { return nbr_list_[i]; } - void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, timestamp_t ts, - Allocator& alloc) override { - EDATA_T value; - arc >> value; - put_edge(src, dst, value, ts, alloc); - } - - void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - timestamp_t ts, Allocator& alloc) override { - EDATA_T value; - arc.Peek(value); - put_edge(src, dst, value, ts, alloc); - } - - std::shared_ptr edge_iter( - vid_t v) const override { - return std::make_shared>( - get_edges(v)); - } - - MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { - return new TypedMutableCsrConstEdgeIter(get_edges(v)); - } - - std::shared_ptr edge_iter_mut(vid_t v) override { - return std::make_shared>(get_edges_mut(v)); - } - - void warmup(int thread_num) const override { - size_t vnum = nbr_list_.size(); - std::vector threads; - std::atomic v_i(0); - std::atomic output(0); - const size_t chunk = 4096; - for (int i = 0; i < thread_num; ++i) { - threads.emplace_back([&]() { - size_t ret = 0; - while (true) { - size_t begin = std::min(v_i.fetch_add(chunk), vnum); - size_t end = std::min(begin + chunk, vnum); - if (begin == end) { - break; - } - while (begin < end) { - auto& nbr = nbr_list_[begin]; - ret += nbr.neighbor; - ++begin; - } - } - output.fetch_add(ret); - }); - } - for (auto& thrd : threads) { - thrd.join(); - } - (void) output.load(); - } - - void batch_sort_by_edge_data(timestamp_t ts) override {} - - timestamp_t unsorted_since() const override { - return std::numeric_limits::max(); - } - private: mmap_array nbr_list_; }; @@ -1438,8 +839,7 @@ class SingleMutableCsr using slice_t = MutableNbrSlice; using mut_slice_t = MutableNbrSliceMut; - SingleMutableCsr(StringColumn& column, std::atomic& column_idx) - : column_(column), column_idx_(column_idx) {} + SingleMutableCsr(StringColumn& column) : column_(column) {} ~SingleMutableCsr() {} size_t batch_init(const std::string& name, const std::string& work_dir, @@ -1454,6 +854,21 @@ class SingleMutableCsr return vnum; } + void batch_put_edge_with_index(vid_t src, vid_t dst, size_t data, + timestamp_t ts) override { + nbr_list_[src].neighbor = dst; + nbr_list_[src].data = data; + CHECK_EQ(nbr_list_[src].timestamp.load(), + std::numeric_limits::max()); + nbr_list_[src].timestamp.store(ts); + } + + void batch_sort_by_edge_data(timestamp_t ts) override {} + + timestamp_t unsorted_since() const override { + return std::numeric_limits::max(); + } + void open(const std::string& name, const std::string& snapshot_dir, const std::string& work_dir) override { if (!std::filesystem::exists(work_dir + "/" + name + ".snbr")) { @@ -1475,6 +890,36 @@ class SingleMutableCsr new_snapshot_dir + "/" + name + ".snbr"); } + void warmup(int thread_num) const override { + size_t vnum = nbr_list_.size(); + std::vector threads; + std::atomic v_i(0); + std::atomic output(0); + const size_t chunk = 4096; + for (int i = 0; i < thread_num; ++i) { + threads.emplace_back([&]() { + size_t ret = 0; + while (true) { + size_t begin = std::min(v_i.fetch_add(chunk), vnum); + size_t end = std::min(begin + chunk, vnum); + if (begin == end) { + break; + } + while (begin < end) { + auto& nbr = nbr_list_[begin]; + ret += nbr.neighbor; + ++begin; + } + } + output.fetch_add(ret); + }); + } + for (auto& thrd : threads) { + thrd.join(); + } + (void) output.load(); + } + void resize(vid_t vnum) override { if (vnum > nbr_list_.size()) { size_t old_size = nbr_list_.size(); @@ -1489,9 +934,18 @@ class SingleMutableCsr size_t size() const override { return nbr_list_.size(); } - void put_generic_edge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) override { - LOG(FATAL) << "not implemented\n"; + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>( + get_edges(v)); + } + + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new MutableCsrConstEdgeIter(get_edges(v)); + } + + std::shared_ptr edge_iter_mut(vid_t v) override { + return std::make_shared>( + get_edges_mut(v)); } void put_edge(vid_t src, vid_t dst, size_t data, timestamp_t ts, Allocator&) { @@ -1502,6 +956,11 @@ class SingleMutableCsr nbr_list_[src].timestamp.store(ts); } + void put_edge_with_index(vid_t src, vid_t dst, size_t index, timestamp_t ts, + Allocator& alloc) override { + put_edge(src, dst, index, ts, alloc); + } + slice_t get_edges(vid_t i) const override { slice_t ret(column_); ret.set_size(nbr_list_[i].timestamp.load() == @@ -1526,100 +985,24 @@ class SingleMutableCsr return ret; } - const MutableNbr& get_edge(vid_t i) const { - nbr_.neighbor = nbr_list_[i].neighbor; - nbr_.timestamp.store(nbr_list_[i].timestamp.load()); - nbr_.data = column_.get_view(nbr_list_[i].data); - return nbr_; - } - - void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, timestamp_t ts, - Allocator& alloc) override { - auto row_id = column_idx_.load(); - put_edge(src, dst, row_id - 1, ts, alloc); - } - - void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - timestamp_t ts, Allocator& alloc) override { - std::string_view sw; - arc >> sw; - - auto row_id = column_idx_.fetch_add(1); - column_.set_value(row_id, sw); - put_edge(src, dst, row_id, ts, alloc); - } - void put_edge_with_index(vid_t src, vid_t dst, size_t index, timestamp_t ts, - Allocator& alloc) override { - put_edge(src, dst, index, ts, alloc); - } - - void batch_put_edge_with_index(vid_t src, vid_t dst, const size_t& data, - timestamp_t ts = 0) override { - nbr_list_[src].neighbor = dst; - nbr_list_[src].data = data; - CHECK_EQ(nbr_list_[src].timestamp.load(), - std::numeric_limits::max()); - nbr_list_[src].timestamp.store(ts); - } - - std::shared_ptr edge_iter( - vid_t v) const override { - return std::make_shared>( - get_edges(v)); - } - - MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { - return new TypedMutableCsrConstEdgeIter(get_edges(v)); - } - - std::shared_ptr edge_iter_mut(vid_t v) override { - return std::make_shared>( - get_edges_mut(v)); - } - - void warmup(int thread_num) const override { - size_t vnum = nbr_list_.size(); - std::vector threads; - std::atomic v_i(0); - std::atomic output(0); - const size_t chunk = 4096; - for (int i = 0; i < thread_num; ++i) { - threads.emplace_back([&]() { - size_t ret = 0; - while (true) { - size_t begin = std::min(v_i.fetch_add(chunk), vnum); - size_t end = std::min(begin + chunk, vnum); - if (begin == end) { - break; - } - while (begin < end) { - auto& nbr = nbr_list_[begin]; - ret += nbr.neighbor; - ++begin; - } - } - output.fetch_add(ret); - }); - } - for (auto& thrd : threads) { - thrd.join(); - } - (void) output.load(); + MutableNbr get_edge(vid_t i) const { + MutableNbr nbr; + nbr.neighbor = nbr_list_[i].neighbor; + nbr.timestamp.store(nbr_list_[i].timestamp.load()); + nbr.data = column_.get_view(nbr_list_[i].data); + return nbr; } private: StringColumn& column_; - std::atomic& column_idx_; - mmap_array nbr_list_; - mutable MutableNbr nbr_; }; template class EmptyCsr : public TypedMutableCsrBase { + public: using slice_t = MutableNbrSlice; - public: EmptyCsr() = default; ~EmptyCsr() = default; @@ -1645,35 +1028,21 @@ class EmptyCsr : public TypedMutableCsrBase { size_t size() const override { return 0; } - slice_t get_edges(vid_t i) const override { return slice_t::empty(); } - - void put_generic_edge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator&) override {} - void batch_put_edge(vid_t src, vid_t dst, const EDATA_T& data, timestamp_t ts = 0) override {} void put_edge(vid_t src, vid_t dst, const EDATA_T& data, timestamp_t ts, Allocator&) override {} - void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, timestamp_t ts, - Allocator&) override { - EDATA_T value; - arc >> value; - } - void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - const timestamp_t ts, Allocator&) override {} - - std::shared_ptr edge_iter( - vid_t v) const override { - return std::make_shared>( + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>( MutableNbrSlice::empty()); } - MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { - return new TypedMutableCsrConstEdgeIter( + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new MutableCsrConstEdgeIter( MutableNbrSlice::empty()); } - std::shared_ptr edge_iter_mut(vid_t v) override { - return std::make_shared>( + std::shared_ptr edge_iter_mut(vid_t v) override { + return std::make_shared>( MutableNbrSliceMut::empty()); } @@ -1682,16 +1051,17 @@ class EmptyCsr : public TypedMutableCsrBase { timestamp_t unsorted_since() const override { return std::numeric_limits::max(); } + + slice_t get_edges(vid_t v) const override { return slice_t::empty(); } }; template <> class EmptyCsr : public TypedMutableCsrBase { + public: using slice_t = MutableNbrSlice; - public: - EmptyCsr(StringColumn& column, std::atomic& column_idx) - : column_(column), column_idx_(column_idx) {} + EmptyCsr(StringColumn& column) : column_(column) {} ~EmptyCsr() = default; size_t batch_init(const std::string& name, const std::string& work_dir, @@ -1714,43 +1084,28 @@ class EmptyCsr size_t size() const override { return 0; } - slice_t get_edges(vid_t i) const override { return slice_t::empty(column_); } - - void put_generic_edge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator&) override { - LOG(FATAL) << "not implemented\n"; - } - - void ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, timestamp_t ts, - Allocator&) override {} - - void peek_ingest_edge(vid_t src, vid_t dst, grape::OutArchive& arc, - const timestamp_t ts, Allocator&) override { - std::string_view sw; - arc >> sw; - auto row_id = column_idx_.fetch_add(1); - column_.set_value(row_id, sw); - } void put_edge_with_index(vid_t src, vid_t dst, size_t index, timestamp_t ts, Allocator& alloc) override {} - void batch_put_edge_with_index(vid_t src, vid_t dst, const size_t& data, + void batch_put_edge_with_index(vid_t src, vid_t dst, size_t data, timestamp_t ts = 0) override {} - std::shared_ptr edge_iter( - vid_t v) const override { - return std::make_shared>( + std::shared_ptr edge_iter(vid_t v) const override { + return std::make_shared>( MutableNbrSlice::empty(column_)); } - MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { - return new TypedMutableCsrConstEdgeIter( + CsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new MutableCsrConstEdgeIter( MutableNbrSlice::empty(column_)); } - std::shared_ptr edge_iter_mut(vid_t v) override { - return std::make_shared>( + std::shared_ptr edge_iter_mut(vid_t v) override { + return std::make_shared>( MutableNbrSliceMut::empty(column_)); } + + slice_t get_edges(vid_t v) const override { return slice_t::empty(column_); } + StringColumn& column_; - std::atomic& column_idx_; }; + } // namespace gs -#endif // GRAPHSCOPE_GRAPH_MUTABLE_CSR_H_ +#endif // STORAGES_RT_MUTABLE_GRAPH_CSR_MUTABLE_CSR_H_ diff --git a/flex/storages/rt_mutable_graph/csr/nbr.h b/flex/storages/rt_mutable_graph/csr/nbr.h new file mode 100644 index 000000000000..cee2675d6bf8 --- /dev/null +++ b/flex/storages/rt_mutable_graph/csr/nbr.h @@ -0,0 +1,462 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STORAGES_RT_MUTABLE_GRAPH_CSR_NBR_H_ +#define STORAGES_RT_MUTABLE_GRAPH_CSR_NBR_H_ + +#include "grape/types.h" + +#include "flex/storages/rt_mutable_graph/types.h" +#include "flex/utils/property/column.h" +#include "flex/utils/property/types.h" + +namespace gs { + +template +struct ImmutableNbr { + ImmutableNbr() = default; + ImmutableNbr(const ImmutableNbr& rhs) + : neighbor(rhs.neighbor), data(rhs.data) {} + ~ImmutableNbr() = default; + + ImmutableNbr& operator=(const ImmutableNbr& rhs) { + neighbor = rhs.neighbor; + data = rhs.data; + return *this; + } + + const EDATA_T& get_data() const { return data; } + vid_t get_neighbor() const { return neighbor; } + + void set_data(const EDATA_T& val) { data = val; } + void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } + + bool exists() const { return neighbor != std::numeric_limits::max(); } + + vid_t neighbor; + EDATA_T data; +}; + +template <> +struct __attribute__((packed)) ImmutableNbr { + ImmutableNbr() = default; + ImmutableNbr(const ImmutableNbr& rhs) + : neighbor(rhs.neighbor), data(rhs.data) {} + ~ImmutableNbr() = default; + + ImmutableNbr& operator=(const ImmutableNbr& rhs) { + neighbor = rhs.neighbor; + data = rhs.data; + return *this; + } + + const Date& get_data() const { return data; } + vid_t get_neighbor() const { return neighbor; } + + void set_data(const Date& val) { data = val; } + void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } + + bool exists() const { return neighbor != std::numeric_limits::max(); } + + vid_t neighbor; + Date data; +}; + +template <> +struct ImmutableNbr { + ImmutableNbr() = default; + ImmutableNbr(const ImmutableNbr& rhs) : neighbor(rhs.neighbor) {} + ~ImmutableNbr() = default; + + ImmutableNbr& operator=(const ImmutableNbr& rhs) { + neighbor = rhs.neighbor; + return *this; + } + + void set_data(const grape::EmptyType&) {} + void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } + const grape::EmptyType& get_data() const { return data; } + vid_t get_neighbor() const { return neighbor; } + union { + vid_t neighbor; + grape::EmptyType data; + }; +}; + +template +class ImmutableNbrSlice { + public: + using const_nbr_t = const ImmutableNbr; + using const_nbr_ptr_t = const ImmutableNbr*; + ImmutableNbrSlice() = default; + ImmutableNbrSlice(const ImmutableNbrSlice& rhs) + : ptr_(rhs.ptr_), size_(rhs.size_) {} + ~ImmutableNbrSlice() = default; + + void set_size(int size) { size_ = size; } + int size() const { return size_; } + + void set_begin(const_nbr_ptr_t ptr) { ptr_ = ptr; } + + const_nbr_ptr_t begin() const { return ptr_; } + const_nbr_ptr_t end() const { return ptr_ + size_; } + + static ImmutableNbrSlice empty() { + ImmutableNbrSlice ret; + ret.set_begin(nullptr); + ret.set_size(0); + return ret; + } + + private: + const_nbr_ptr_t ptr_; + int size_; +}; + +template <> +class ImmutableNbrSlice { + public: + struct ColumnNbr { + using const_nbr_t = const ImmutableNbr; + using const_nbr_ptr_t = const ImmutableNbr*; + + ColumnNbr(const_nbr_ptr_t ptr, const StringColumn& column) + : ptr_(ptr), column_(column) {} + vid_t get_neighbor() const { return ptr_->neighbor; } + std::string_view get_data() const { return column_.get_view(ptr_->data); } + + const ColumnNbr& operator*() const { return *this; } + const ColumnNbr* operator->() const { return this; } + const ColumnNbr& operator=(const ColumnNbr& nbr) const { + ptr_ = nbr.ptr_; + return *this; + } + bool operator==(const ColumnNbr& nbr) const { return ptr_ == nbr.ptr_; } + bool operator!=(const ColumnNbr& nbr) const { return ptr_ != nbr.ptr_; } + const ColumnNbr& operator++() const { + ++ptr_; + return *this; + } + + const ColumnNbr& operator+=(size_t n) const { + ptr_ += n; + return *this; + } + + size_t operator-(const ColumnNbr& nbr) const { return ptr_ - nbr.ptr_; } + + bool operator<(const ColumnNbr& nbr) const { return ptr_ < nbr.ptr_; } + + mutable const_nbr_ptr_t ptr_; + const StringColumn& column_; + }; + using const_nbr_t = const ColumnNbr; + using const_nbr_ptr_t = const ColumnNbr; + ImmutableNbrSlice(const StringColumn& column) : slice_(), column_(column) {} + ImmutableNbrSlice(const ImmutableNbrSlice& rhs) + : slice_(rhs.slice_), column_(rhs.column_) {} + ~ImmutableNbrSlice() = default; + void set_size(int size) { slice_.set_size(size); } + int size() const { return slice_.size(); } + + void set_begin(const ImmutableNbr* ptr) { slice_.set_begin(ptr); } + + const ColumnNbr begin() const { return ColumnNbr(slice_.begin(), column_); } + const ColumnNbr end() const { return ColumnNbr(slice_.end(), column_); } + + static ImmutableNbrSlice empty(const StringColumn& column) { + ImmutableNbrSlice ret(column); + ret.set_begin(nullptr); + ret.set_size(0); + return ret; + } + + private: + ImmutableNbrSlice slice_; + const StringColumn& column_; +}; + +template +struct MutableNbr { + MutableNbr() = default; + MutableNbr(const MutableNbr& rhs) + : neighbor(rhs.neighbor), + timestamp(rhs.timestamp.load()), + data(rhs.data) {} + ~MutableNbr() = default; + + MutableNbr& operator=(const MutableNbr& rhs) { + neighbor = rhs.neighbor; + timestamp.store(rhs.timestamp.load()); + data = rhs.data; + return *this; + } + + const EDATA_T& get_data() const { return data; } + vid_t get_neighbor() const { return neighbor; } + timestamp_t get_timestamp() const { return timestamp.load(); } + + void set_data(const EDATA_T& val, timestamp_t ts) { + data = val; + timestamp.store(ts); + } + void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } + void set_timestamp(timestamp_t ts) { timestamp.store(ts); } + + vid_t neighbor; + std::atomic timestamp; + EDATA_T data; +}; + +template <> +struct MutableNbr { + MutableNbr() = default; + MutableNbr(const MutableNbr& rhs) + : neighbor(rhs.neighbor), timestamp(rhs.timestamp.load()) {} + ~MutableNbr() = default; + + MutableNbr& operator=(const MutableNbr& rhs) { + neighbor = rhs.neighbor; + timestamp.store(rhs.timestamp.load()); + return *this; + } + + void set_data(const grape::EmptyType&, timestamp_t ts) { + timestamp.store(ts); + } + void set_neighbor(vid_t neighbor) { this->neighbor = neighbor; } + void set_timestamp(timestamp_t ts) { timestamp.store(ts); } + const grape::EmptyType& get_data() const { return data; } + vid_t get_neighbor() const { return neighbor; } + timestamp_t get_timestamp() const { return timestamp.load(); } + vid_t neighbor; + union { + std::atomic timestamp; + grape::EmptyType data; + }; +}; + +template +class MutableNbrSlice { + public: + using const_nbr_t = const MutableNbr; + using const_nbr_ptr_t = const MutableNbr*; + MutableNbrSlice() = default; + MutableNbrSlice(const MutableNbrSlice& rhs) + : ptr_(rhs.ptr_), size_(rhs.size_) {} + ~MutableNbrSlice() = default; + + void set_size(int size) { size_ = size; } + int size() const { return size_; } + + void set_begin(const_nbr_ptr_t ptr) { ptr_ = ptr; } + + const_nbr_ptr_t begin() const { return ptr_; } + const_nbr_ptr_t end() const { return ptr_ + size_; } + + static MutableNbrSlice empty() { + MutableNbrSlice ret; + ret.set_begin(nullptr); + ret.set_size(0); + return ret; + } + + private: + const_nbr_ptr_t ptr_; + int size_; +}; + +template <> +class MutableNbrSlice { + public: + struct MutableColumnNbr { + using const_nbr_t = const MutableNbr; + using const_nbr_ptr_t = const MutableNbr*; + + MutableColumnNbr(const_nbr_ptr_t ptr, const StringColumn& column) + : ptr_(ptr), column_(column) {} + vid_t get_neighbor() const { return ptr_->neighbor; } + std::string_view get_data() const { return column_.get_view(ptr_->data); } + timestamp_t get_timestamp() const { return ptr_->timestamp.load(); } + + const MutableColumnNbr& operator*() const { return *this; } + const MutableColumnNbr* operator->() const { return this; } + const MutableColumnNbr& operator=(const MutableColumnNbr& nbr) const { + ptr_ = nbr.ptr_; + return *this; + } + bool operator==(const MutableColumnNbr& nbr) const { + return ptr_ == nbr.ptr_; + } + bool operator!=(const MutableColumnNbr& nbr) const { + return ptr_ != nbr.ptr_; + } + const MutableColumnNbr& operator++() const { + ++ptr_; + return *this; + } + + const MutableColumnNbr& operator+=(size_t n) const { + ptr_ += n; + return *this; + } + + size_t operator-(const MutableColumnNbr& nbr) const { + return ptr_ - nbr.ptr_; + } + + bool operator<(const MutableColumnNbr& nbr) const { + return ptr_ < nbr.ptr_; + } + + mutable const_nbr_ptr_t ptr_; + const StringColumn& column_; + }; + using const_nbr_t = const MutableColumnNbr; + using const_nbr_ptr_t = const MutableColumnNbr; + MutableNbrSlice(const StringColumn& column) : slice_(), column_(column) {} + MutableNbrSlice(const MutableNbrSlice& rhs) + : slice_(rhs.slice_), column_(rhs.column_) {} + ~MutableNbrSlice() = default; + void set_size(int size) { slice_.set_size(size); } + int size() const { return slice_.size(); } + + void set_begin(const MutableNbr* ptr) { slice_.set_begin(ptr); } + + const MutableColumnNbr begin() const { + return MutableColumnNbr(slice_.begin(), column_); + } + const MutableColumnNbr end() const { + return MutableColumnNbr(slice_.end(), column_); + } + + static MutableNbrSlice empty(const StringColumn& column) { + MutableNbrSlice ret(column); + ret.set_begin(nullptr); + ret.set_size(0); + return ret; + } + + private: + MutableNbrSlice slice_; + const StringColumn& column_; +}; + +template +class MutableNbrSliceMut { + public: + using nbr_t = MutableNbr; + using nbr_ptr_t = MutableNbr*; + MutableNbrSliceMut() = default; + ~MutableNbrSliceMut() = default; + + void set_size(int size) { size_ = size; } + int size() const { return size_; } + + void set_begin(nbr_t* ptr) { ptr_ = ptr; } + + nbr_t* begin() { return ptr_; } + nbr_t* end() { return ptr_ + size_; } + + static MutableNbrSliceMut empty() { + MutableNbrSliceMut ret; + ret.set_begin(nullptr); + ret.set_size(0); + return ret; + } + + private: + nbr_t* ptr_; + int size_; +}; + +template <> +class MutableNbrSliceMut { + public: + struct MutableColumnNbr { + using nbr_t = MutableNbr; + + MutableColumnNbr(nbr_t* ptr, StringColumn& column) + : ptr_(ptr), column_(column) {} + vid_t neighbor() const { return ptr_->neighbor; } + std::string_view data() { return column_.get_view(ptr_->data); } + vid_t get_neighbor() const { return ptr_->neighbor; } + const std::string_view get_data() const { + return column_.get_view(ptr_->data); + } + timestamp_t get_timestamp() const { return ptr_->timestamp.load(); } + size_t get_index() const { return ptr_->data; } + void set_data(const std::string_view& sw, timestamp_t ts) { + column_.set_value(ptr_->data, sw); + ptr_->timestamp.store(ts); + } + void set_neighbor(vid_t neighbor) { ptr_->neighbor = neighbor; } + + void set_timestamp(timestamp_t ts) { ptr_->timestamp.store(ts); } + + const MutableColumnNbr& operator*() const { return *this; } + MutableColumnNbr& operator*() { return *this; } + MutableColumnNbr& operator=(const MutableColumnNbr& nbr) { + ptr_ = nbr.ptr_; + return *this; + } + bool operator==(const MutableColumnNbr& nbr) const { + return ptr_ == nbr.ptr_; + } + bool operator!=(const MutableColumnNbr& nbr) const { + return ptr_ != nbr.ptr_; + } + + MutableColumnNbr& operator++() { + ptr_++; + return *this; + } + MutableColumnNbr& operator+=(size_t n) { + ptr_ += n; + return *this; + } + + bool operator<(const MutableColumnNbr& nbr) { return ptr_ < nbr.ptr_; } + + nbr_t* ptr_; + StringColumn & column_; + }; + using nbr_ptr_t = MutableColumnNbr; + + MutableNbrSliceMut(StringColumn& column) : column_(column) {} + ~MutableNbrSliceMut() = default; + void set_size(int size) { slice_.set_size(size); } + int size() const { return slice_.size(); } + + void set_begin(MutableNbr* ptr) { slice_.set_begin(ptr); } + + MutableColumnNbr begin() { return MutableColumnNbr(slice_.begin(), column_); } + MutableColumnNbr end() { return MutableColumnNbr(slice_.end(), column_); } + + static MutableNbrSliceMut empty(StringColumn& column) { + MutableNbrSliceMut ret(column); + ret.set_begin(nullptr); + ret.set_size(0); + return ret; + } + + private: + MutableNbrSliceMut slice_; + StringColumn& column_; +}; + +} // namespace gs + +#endif // STORAGES_RT_MUTABLE_GRAPH_CSR_NBR_H_ diff --git a/flex/storages/rt_mutable_graph/dual_csr.h b/flex/storages/rt_mutable_graph/dual_csr.h index a2eea20ab9d6..c5baf0cd9a27 100644 --- a/flex/storages/rt_mutable_graph/dual_csr.h +++ b/flex/storages/rt_mutable_graph/dual_csr.h @@ -19,7 +19,8 @@ #include #include -#include "flex/storages/rt_mutable_graph/mutable_csr.h" +#include "flex/storages/rt_mutable_graph/csr/immutable_csr.h" +#include "flex/storages/rt_mutable_graph/csr/mutable_csr.h" #include "flex/utils/allocators.h" namespace gs { @@ -52,39 +53,57 @@ class DualCsrBase { const std::string& edata_name, const std::string& new_snapshot_dir) = 0; - virtual void PutEdge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) = 0; - - virtual void SortByEdgeData(timestamp_t ts) = 0; - virtual void IngestEdge(vid_t src, vid_t dst, grape::OutArchive& oarc, timestamp_t timestamp, Allocator& alloc) = 0; + virtual void SortByEdgeData(timestamp_t ts) = 0; + virtual void UpdateEdge(vid_t src, vid_t dst, const Any& oarc, timestamp_t timestamp, Allocator& alloc) = 0; - virtual MutableCsrBase* GetInCsr() = 0; - virtual MutableCsrBase* GetOutCsr() = 0; + void Resize(vid_t src_vertex_num, vid_t dst_vertex_num) { + GetInCsr()->resize(dst_vertex_num); + GetOutCsr()->resize(src_vertex_num); + } + + void Warmup(int thread_num) { + GetInCsr()->warmup(thread_num); + GetOutCsr()->warmup(thread_num); + } + + virtual CsrBase* GetInCsr() = 0; + virtual CsrBase* GetOutCsr() = 0; + virtual const CsrBase* GetInCsr() const = 0; + virtual const CsrBase* GetOutCsr() const = 0; }; template class DualCsr : public DualCsrBase { public: - DualCsr(EdgeStrategy oe_strategy, EdgeStrategy ie_strategy) + DualCsr(EdgeStrategy oe_strategy, EdgeStrategy ie_strategy, bool oe_mutable, + bool ie_mutable) : in_csr_(nullptr), out_csr_(nullptr) { if (ie_strategy == EdgeStrategy::kNone) { in_csr_ = new EmptyCsr(); } else if (ie_strategy == EdgeStrategy::kMultiple) { in_csr_ = new MutableCsr(); } else if (ie_strategy == EdgeStrategy::kSingle) { - in_csr_ = new SingleMutableCsr(); + if (ie_mutable) { + in_csr_ = new SingleMutableCsr(); + } else { + in_csr_ = new SingleImmutableCsr(); + } } if (oe_strategy == EdgeStrategy::kNone) { out_csr_ = new EmptyCsr(); } else if (oe_strategy == EdgeStrategy::kMultiple) { out_csr_ = new MutableCsr(); } else if (oe_strategy == EdgeStrategy::kSingle) { - out_csr_ = new SingleMutableCsr(); + if (oe_mutable) { + out_csr_ = new SingleMutableCsr(); + } else { + out_csr_ = new SingleImmutableCsr(); + } } } ~DualCsr() { @@ -133,14 +152,17 @@ class DualCsr : public DualCsrBase { out_csr_->dump(oe_name, new_snapshot_dir); } - MutableCsrBase* GetInCsr() override { return in_csr_; } - MutableCsrBase* GetOutCsr() override { return out_csr_; } - void PutEdge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) override { - EDATA_T prop; - ConvertAny::to(data, prop); - in_csr_->put_edge(dst, src, prop, ts, alloc); - out_csr_->put_edge(src, dst, prop, ts, alloc); + CsrBase* GetInCsr() override { return in_csr_; } + CsrBase* GetOutCsr() override { return out_csr_; } + const CsrBase* GetInCsr() const override { return in_csr_; } + const CsrBase* GetOutCsr() const override { return out_csr_; } + + void IngestEdge(vid_t src, vid_t dst, grape::OutArchive& oarc, timestamp_t ts, + Allocator& alloc) override { + EDATA_T data; + oarc >> data; + in_csr_->put_edge(dst, src, data, ts, alloc); + out_csr_->put_edge(src, dst, data, ts, alloc); } void SortByEdgeData(timestamp_t ts) override { @@ -177,22 +199,14 @@ class DualCsr : public DualCsrBase { } } - void IngestEdge(vid_t src, vid_t dst, grape::OutArchive& oarc, timestamp_t ts, - Allocator& alloc) override { - EDATA_T data; - oarc >> data; - in_csr_->put_edge(dst, src, data, ts, alloc); - out_csr_->put_edge(src, dst, data, ts, alloc); - } - void BatchPutEdge(vid_t src, vid_t dst, const EDATA_T& data) { in_csr_->batch_put_edge(dst, src, data); out_csr_->batch_put_edge(src, dst, data); } private: - TypedMutableCsrBase* in_csr_; - TypedMutableCsrBase* out_csr_; + TypedCsrBase* in_csr_; + TypedCsrBase* out_csr_; }; template <> @@ -203,18 +217,18 @@ class DualCsr : public DualCsrBase { out_csr_(nullptr), column_(StorageStrategy::kMem, width) { if (ie_strategy == EdgeStrategy::kNone) { - in_csr_ = new EmptyCsr(column_, column_idx_); + in_csr_ = new EmptyCsr(column_); } else if (ie_strategy == EdgeStrategy::kMultiple) { - in_csr_ = new MutableCsr(column_, column_idx_); + in_csr_ = new MutableCsr(column_); } else if (ie_strategy == EdgeStrategy::kSingle) { - in_csr_ = new SingleMutableCsr(column_, column_idx_); + in_csr_ = new SingleMutableCsr(column_); } if (oe_strategy == EdgeStrategy::kNone) { - out_csr_ = new EmptyCsr(column_, column_idx_); + out_csr_ = new EmptyCsr(column_); } else if (oe_strategy == EdgeStrategy::kMultiple) { - out_csr_ = new MutableCsr(column_, column_idx_); + out_csr_ = new MutableCsr(column_); } else if (oe_strategy == EdgeStrategy::kSingle) { - out_csr_ = new SingleMutableCsr(column_, column_idx_); + out_csr_ = new SingleMutableCsr(column_); } } ~DualCsr() { @@ -273,13 +287,17 @@ class DualCsr : public DualCsrBase { column_.dump(new_snapshot_dir + "/" + edata_name); } - MutableCsrBase* GetInCsr() override { return in_csr_; } - MutableCsrBase* GetOutCsr() override { return out_csr_; } - void PutEdge(vid_t src, vid_t dst, const Any& data, timestamp_t ts, - Allocator& alloc) override { - std::string_view val = data.AsStringView(); + CsrBase* GetInCsr() override { return in_csr_; } + CsrBase* GetOutCsr() override { return out_csr_; } + const CsrBase* GetInCsr() const override { return in_csr_; } + const CsrBase* GetOutCsr() const override { return out_csr_; } + + void IngestEdge(vid_t src, vid_t dst, grape::OutArchive& oarc, timestamp_t ts, + Allocator& alloc) override { + std::string_view prop; + oarc >> prop; size_t row_id = column_idx_.fetch_add(1); - column_.set_value(row_id, val); + column_.set_value(row_id, prop); in_csr_->put_edge_with_index(dst, src, row_id, ts, alloc); out_csr_->put_edge_with_index(src, dst, row_id, ts, alloc); } @@ -292,8 +310,7 @@ class DualCsr : public DualCsrBase { Allocator& alloc) override { auto oe_ptr = out_csr_->edge_iter_mut(src); std::string_view prop = data.AsStringView(); - auto oe = - dynamic_cast*>(oe_ptr.get()); + auto oe = dynamic_cast*>(oe_ptr.get()); size_t index = std::numeric_limits::max(); while (oe != nullptr && oe->is_valid()) { if (oe->get_neighbor() == dst) { @@ -304,8 +321,7 @@ class DualCsr : public DualCsrBase { oe->next(); } auto ie_ptr = in_csr_->edge_iter_mut(dst); - auto ie = - dynamic_cast*>(ie_ptr.get()); + auto ie = dynamic_cast*>(ie_ptr.get()); while (ie != nullptr && ie->is_valid()) { if (ie->get_neighbor() == src) { ie->set_timestamp(ts); @@ -324,16 +340,6 @@ class DualCsr : public DualCsrBase { } } - void IngestEdge(vid_t src, vid_t dst, grape::OutArchive& oarc, timestamp_t ts, - Allocator& alloc) override { - std::string_view prop; - oarc >> prop; - size_t row_id = column_idx_.fetch_add(1); - column_.set_value(row_id, prop); - in_csr_->put_edge_with_index(dst, src, row_id, ts, alloc); - out_csr_->put_edge_with_index(src, dst, row_id, ts, alloc); - } - void BatchPutEdge(vid_t src, vid_t dst, const std::string_view& data) { size_t row_id = column_idx_.fetch_add(1); column_.set_value(row_id, data); @@ -350,8 +356,8 @@ class DualCsr : public DualCsrBase { } private: - TypedMutableCsrBase* in_csr_; - TypedMutableCsrBase* out_csr_; + TypedCsrBase* in_csr_; + TypedCsrBase* out_csr_; std::atomic column_idx_; StringColumn column_; }; diff --git a/flex/storages/rt_mutable_graph/loader/basic_fragment_loader.h b/flex/storages/rt_mutable_graph/loader/basic_fragment_loader.h index 1d0d630f8da1..ae643b1819e3 100644 --- a/flex/storages/rt_mutable_graph/loader/basic_fragment_loader.h +++ b/flex/storages/rt_mutable_graph/loader/basic_fragment_loader.h @@ -90,7 +90,12 @@ class BasicFragmentLoader { dual_csr_list_[index] = new DualCsr( oe_strategy, ie_strategy, prop[0].additional_type_info.max_length); } else { - dual_csr_list_[index] = new DualCsr(oe_strategy, ie_strategy); + bool oe_mutable = schema_.outgoing_edge_mutable( + src_label_name, dst_label_name, edge_label_name); + bool ie_mutable = schema_.incoming_edge_mutable( + src_label_name, dst_label_name, edge_label_name); + dual_csr_list_[index] = new DualCsr(oe_strategy, ie_strategy, + oe_mutable, ie_mutable); } ie_[index] = dual_csr_list_[index]->GetInCsr(); oe_[index] = dual_csr_list_[index]->GetOutCsr(); @@ -120,7 +125,6 @@ class BasicFragmentLoader { src_label_name, dst_label_name, edge_label_name); EdgeStrategy ie_strategy = schema_.get_incoming_edge_strategy( src_label_name, dst_label_name, edge_label_name); - if constexpr (std::is_same_v) { const auto& prop = schema_.get_edge_properties(src_label_id, dst_label_id, edge_label_id); @@ -142,7 +146,13 @@ class BasicFragmentLoader { } } else { - auto dual_csr = new DualCsr(oe_strategy, ie_strategy); + bool oe_mutable = schema_.outgoing_edge_mutable( + src_label_name, dst_label_name, edge_label_name); + bool ie_mutable = schema_.incoming_edge_mutable( + src_label_name, dst_label_name, edge_label_name); + + auto dual_csr = new DualCsr(oe_strategy, ie_strategy, oe_mutable, + ie_mutable); dual_csr_list_[index] = dual_csr; ie_[index] = dual_csr_list_[index]->GetInCsr(); @@ -176,7 +186,7 @@ class BasicFragmentLoader { std::string work_dir_; size_t vertex_label_num_, edge_label_num_; std::vector> lf_indexers_; - std::vector ie_, oe_; + std::vector ie_, oe_; std::vector dual_csr_list_; std::vector vertex_data_; }; diff --git a/flex/storages/rt_mutable_graph/mutable_property_fragment.cc b/flex/storages/rt_mutable_graph/mutable_property_fragment.cc index 3c0b0b4a3737..116ae4020481 100644 --- a/flex/storages/rt_mutable_graph/mutable_property_fragment.cc +++ b/flex/storages/rt_mutable_graph/mutable_property_fragment.cc @@ -34,13 +34,9 @@ MutablePropertyFragment::~MutablePropertyFragment() { for (size_t e_label = 0; e_label != edge_label_num_; ++e_label) { size_t index = src_label * vertex_label_num_ * edge_label_num_ + dst_label * edge_label_num_ + e_label; - if (ie_[index] != NULL) { - ie_[index]->resize(degree_list[dst_label]); - } - if (oe_[index] != NULL) { - oe_[index]->resize(degree_list[src_label]); - } if (dual_csr_list_[index] != NULL) { + dual_csr_list_[index]->Resize(degree_list[src_label], + degree_list[dst_label]); delete dual_csr_list_[index]; } } @@ -80,26 +76,27 @@ void MutablePropertyFragment::DumpSchema(const std::string& schema_path) { } inline DualCsrBase* create_csr(EdgeStrategy oes, EdgeStrategy ies, - const std::vector& properties) { + const std::vector& properties, + bool oe_mutable, bool ie_mutable) { if (properties.empty()) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties.size() == 1) { if (properties[0] == PropertyType::kBool) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kInt32) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kUInt32) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kDate) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kInt64) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kUInt64) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kDouble) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0] == PropertyType::kFloat) { - return new DualCsr(oes, ies); + return new DualCsr(oes, ies, oe_mutable, ie_mutable); } else if (properties[0].type_enum == impl::PropertyTypeImpl::kVarChar) { return new DualCsr( oes, ies, properties[0].additional_type_info.max_length); @@ -222,8 +219,12 @@ void MutablePropertyFragment::Open(const std::string& work_dir, src_label, dst_label, edge_label); EdgeStrategy ie_strategy = schema_.get_incoming_edge_strategy( src_label, dst_label, edge_label); - dual_csr_list_[index] = - create_csr(oe_strategy, ie_strategy, properties); + bool oe_mutable = + schema_.outgoing_edge_mutable(src_label, dst_label, edge_label); + bool ie_mutable = + schema_.incoming_edge_mutable(src_label, dst_label, edge_label); + dual_csr_list_[index] = create_csr(oe_strategy, ie_strategy, properties, + oe_mutable, ie_mutable); ie_[index] = dual_csr_list_[index]->GetInCsr(); oe_[index] = dual_csr_list_[index]->GetOutCsr(); if (memory_level == 0) { @@ -245,8 +246,8 @@ void MutablePropertyFragment::Open(const std::string& work_dir, edata_prefix(src_label, dst_label, edge_label), snapshot_dir, vertex_capacities[src_label_i], vertex_capacities[dst_label_i]); } - ie_[index]->resize(vertex_capacities[dst_label_i]); - oe_[index]->resize(vertex_capacities[src_label_i]); + dual_csr_list_[index]->Resize(vertex_capacities[src_label_i], + vertex_capacities[dst_label_i]); } } } @@ -311,8 +312,8 @@ void MutablePropertyFragment::Dump(const std::string& work_dir, size_t index = src_label_i * vertex_label_num_ * edge_label_num_ + dst_label_i * edge_label_num_ + e_label_i; if (dual_csr_list_[index] != NULL) { - ie_[index]->resize(vertex_num[dst_label_i]); - oe_[index]->resize(vertex_num[src_label_i]); + dual_csr_list_[index]->Resize(vertex_num[src_label_i], + vertex_num[dst_label_i]); if (schema_.get_sort_on_compaction(src_label, dst_label, edge_label)) { dual_csr_list_[index]->SortByEdgeData(version + 1); @@ -331,14 +332,9 @@ void MutablePropertyFragment::Dump(const std::string& work_dir, void MutablePropertyFragment::Warmup(int thread_num) { double t = -grape::GetCurrentTime(); - for (auto ptr : ie_) { - if (ptr != NULL) { - ptr->warmup(thread_num); - } - } - for (auto ptr : oe_) { + for (auto ptr : dual_csr_list_) { if (ptr != NULL) { - ptr->warmup(thread_num); + ptr->Warmup(thread_num); } } for (auto& indexer : lf_indexers_) { @@ -354,8 +350,7 @@ void MutablePropertyFragment::IngestEdge(label_t src_label, vid_t src_lid, Allocator& alloc) { size_t index = src_label * vertex_label_num_ * edge_label_num_ + dst_label * edge_label_num_ + edge_label; - ie_[index]->peek_ingest_edge(dst_lid, src_lid, arc, ts, alloc); - oe_[index]->ingest_edge(src_lid, dst_lid, arc, ts, alloc); + dual_csr_list_[index]->IngestEdge(src_lid, dst_lid, arc, ts, alloc); } void MutablePropertyFragment::UpdateEdge(label_t src_label, vid_t src_lid, @@ -396,81 +391,71 @@ vid_t MutablePropertyFragment::add_vertex(label_t label, const Any& id) { return lf_indexers_[label].insert(id); } -std::shared_ptr +std::shared_ptr MutablePropertyFragment::get_outgoing_edges(label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const { - size_t index = label * vertex_label_num_ * edge_label_num_ + - neighbor_label * edge_label_num_ + edge_label; - return oe_[index]->edge_iter(u); + return get_oe_csr(label, neighbor_label, edge_label)->edge_iter(u); } -std::shared_ptr +std::shared_ptr MutablePropertyFragment::get_incoming_edges(label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const { - size_t index = neighbor_label * vertex_label_num_ * edge_label_num_ + - label * edge_label_num_ + edge_label; - return ie_[index]->edge_iter(u); + return get_ie_csr(label, neighbor_label, edge_label)->edge_iter(u); } -MutableCsrConstEdgeIterBase* MutablePropertyFragment::get_outgoing_edges_raw( +CsrConstEdgeIterBase* MutablePropertyFragment::get_outgoing_edges_raw( label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const { - size_t index = label * vertex_label_num_ * edge_label_num_ + - neighbor_label * edge_label_num_ + edge_label; - return oe_[index]->edge_iter_raw(u); + return get_oe_csr(label, neighbor_label, edge_label)->edge_iter_raw(u); } -MutableCsrConstEdgeIterBase* MutablePropertyFragment::get_incoming_edges_raw( +CsrConstEdgeIterBase* MutablePropertyFragment::get_incoming_edges_raw( label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const { - size_t index = neighbor_label * vertex_label_num_ * edge_label_num_ + - label * edge_label_num_ + edge_label; - return ie_[index]->edge_iter_raw(u); + return get_ie_csr(label, neighbor_label, edge_label)->edge_iter_raw(u); } -std::shared_ptr +std::shared_ptr MutablePropertyFragment::get_outgoing_edges_mut(label_t label, vid_t u, label_t neighbor_label, label_t edge_label) { - size_t index = label * vertex_label_num_ * edge_label_num_ + - neighbor_label * edge_label_num_ + edge_label; - return oe_[index]->edge_iter_mut(u); + return get_oe_csr(label, neighbor_label, edge_label)->edge_iter_mut(u); } -std::shared_ptr +std::shared_ptr MutablePropertyFragment::get_incoming_edges_mut(label_t label, vid_t u, label_t neighbor_label, label_t edge_label) { - size_t index = neighbor_label * vertex_label_num_ * edge_label_num_ + - label * edge_label_num_ + edge_label; - return ie_[index]->edge_iter_mut(u); + return get_ie_csr(label, neighbor_label, edge_label)->edge_iter_mut(u); } -MutableCsrBase* MutablePropertyFragment::get_oe_csr(label_t label, - label_t neighbor_label, - label_t edge_label) { +CsrBase* MutablePropertyFragment::get_oe_csr(label_t label, + label_t neighbor_label, + label_t edge_label) { size_t index = label * vertex_label_num_ * edge_label_num_ + neighbor_label * edge_label_num_ + edge_label; return oe_[index]; } -const MutableCsrBase* MutablePropertyFragment::get_oe_csr( - label_t label, label_t neighbor_label, label_t edge_label) const { +const CsrBase* MutablePropertyFragment::get_oe_csr(label_t label, + label_t neighbor_label, + label_t edge_label) const { size_t index = label * vertex_label_num_ * edge_label_num_ + neighbor_label * edge_label_num_ + edge_label; return oe_[index]; } -MutableCsrBase* MutablePropertyFragment::get_ie_csr(label_t label, - label_t neighbor_label, - label_t edge_label) { +CsrBase* MutablePropertyFragment::get_ie_csr(label_t label, + label_t neighbor_label, + label_t edge_label) { size_t index = neighbor_label * vertex_label_num_ * edge_label_num_ + label * edge_label_num_ + edge_label; return ie_[index]; } -const MutableCsrBase* MutablePropertyFragment::get_ie_csr( - label_t label, label_t neighbor_label, label_t edge_label) const { +const CsrBase* MutablePropertyFragment::get_ie_csr(label_t label, + label_t neighbor_label, + label_t edge_label) const { size_t index = neighbor_label * vertex_label_num_ * edge_label_num_ + label * edge_label_num_ + edge_label; return ie_[index]; diff --git a/flex/storages/rt_mutable_graph/mutable_property_fragment.h b/flex/storages/rt_mutable_graph/mutable_property_fragment.h index f15b0864f49b..58733652564a 100644 --- a/flex/storages/rt_mutable_graph/mutable_property_fragment.h +++ b/flex/storages/rt_mutable_graph/mutable_property_fragment.h @@ -22,8 +22,8 @@ #include "flex/storages/rt_mutable_graph/schema.h" +#include "flex/storages/rt_mutable_graph/csr/mutable_csr.h" #include "flex/storages/rt_mutable_graph/dual_csr.h" -#include "flex/storages/rt_mutable_graph/mutable_csr.h" #include "flex/storages/rt_mutable_graph/types.h" #include "flex/utils/arrow_utils.h" #include "flex/utils/id_indexer.h" @@ -75,43 +75,43 @@ class MutablePropertyFragment { Any get_oid(label_t label, vid_t lid) const; vid_t add_vertex(label_t label, const Any& id); - std::shared_ptr get_outgoing_edges( + std::shared_ptr get_outgoing_edges( label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const; - std::shared_ptr get_incoming_edges( + std::shared_ptr get_incoming_edges( label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const; - std::shared_ptr get_outgoing_edges_mut( + std::shared_ptr get_outgoing_edges_mut( label_t label, vid_t u, label_t neighbor_label, label_t edge_label); - std::shared_ptr get_incoming_edges_mut( + std::shared_ptr get_incoming_edges_mut( label_t label, vid_t u, label_t neighbor_label, label_t edge_label); - MutableCsrConstEdgeIterBase* get_outgoing_edges_raw(label_t label, vid_t u, - label_t neighbor_label, - label_t edge_label) const; + CsrConstEdgeIterBase* get_outgoing_edges_raw(label_t label, vid_t u, + label_t neighbor_label, + label_t edge_label) const; - MutableCsrConstEdgeIterBase* get_incoming_edges_raw(label_t label, vid_t u, - label_t neighbor_label, - label_t edge_label) const; + CsrConstEdgeIterBase* get_incoming_edges_raw(label_t label, vid_t u, + label_t neighbor_label, + label_t edge_label) const; - MutableCsrBase* get_oe_csr(label_t label, label_t neighbor_label, - label_t edge_label); + CsrBase* get_oe_csr(label_t label, label_t neighbor_label, + label_t edge_label); - const MutableCsrBase* get_oe_csr(label_t label, label_t neighbor_label, - label_t edge_label) const; + const CsrBase* get_oe_csr(label_t label, label_t neighbor_label, + label_t edge_label) const; - MutableCsrBase* get_ie_csr(label_t label, label_t neighbor_label, - label_t edge_label); + CsrBase* get_ie_csr(label_t label, label_t neighbor_label, + label_t edge_label); - const MutableCsrBase* get_ie_csr(label_t label, label_t neighbor_label, - label_t edge_label) const; + const CsrBase* get_ie_csr(label_t label, label_t neighbor_label, + label_t edge_label) const; void loadSchema(const std::string& filename); Schema schema_; std::vector> lf_indexers_; - std::vector ie_, oe_; + std::vector ie_, oe_; std::vector dual_csr_list_; std::vector
vertex_data_; diff --git a/flex/storages/rt_mutable_graph/schema.cc b/flex/storages/rt_mutable_graph/schema.cc index 66281a7188a2..eebb7558df14 100644 --- a/flex/storages/rt_mutable_graph/schema.cc +++ b/flex/storages/rt_mutable_graph/schema.cc @@ -33,6 +33,8 @@ void Schema::Clear() { eprop_names_.clear(); ie_strategy_.clear(); oe_strategy_.clear(); + ie_mutability_.clear(); + oe_mutability_.clear(); sort_on_compactions_.clear(); max_vnum_.clear(); plugin_name_to_path_and_id_.clear(); @@ -60,8 +62,8 @@ void Schema::add_edge_label(const std::string& src_label, const std::string& edge_label, const std::vector& properties, const std::vector& prop_names, - EdgeStrategy oe, EdgeStrategy ie, - bool sort_on_compaction) { + EdgeStrategy oe, EdgeStrategy ie, bool oe_mutable, + bool ie_mutable, bool sort_on_compaction) { label_t src_label_id = vertex_label_to_index(src_label); label_t dst_label_id = vertex_label_to_index(dst_label); label_t edge_label_id = edge_label_to_index(edge_label); @@ -71,6 +73,8 @@ void Schema::add_edge_label(const std::string& src_label, eproperties_[label_id] = properties; oe_strategy_[label_id] = oe; ie_strategy_[label_id] = ie; + oe_mutability_[label_id] = oe_mutable; + ie_mutability_[label_id] = ie_mutable; eprop_names_[label_id] = prop_names; sort_on_compactions_[label_id] = sort_on_compaction; } @@ -232,6 +236,28 @@ EdgeStrategy Schema::get_incoming_edge_strategy( return ie_strategy_.at(index); } +bool Schema::outgoing_edge_mutable(const std::string& src_label, + const std::string& dst_label, + const std::string& label) const { + label_t src, dst, edge; + CHECK(vlabel_indexer_.get_index(src_label, src)); + CHECK(vlabel_indexer_.get_index(dst_label, dst)); + CHECK(elabel_indexer_.get_index(label, edge)); + uint32_t index = generate_edge_label(src, dst, edge); + return oe_mutability_.at(index); +} + +bool Schema::incoming_edge_mutable(const std::string& src_label, + const std::string& dst_label, + const std::string& label) const { + label_t src, dst, edge; + CHECK(vlabel_indexer_.get_index(src_label, src)); + CHECK(vlabel_indexer_.get_index(dst_label, dst)); + CHECK(elabel_indexer_.get_index(label, edge)); + uint32_t index = generate_edge_label(src, dst, edge); + return ie_mutability_.at(index); +} + bool Schema::get_sort_on_compaction(const std::string& src_label, const std::string& dst_label, const std::string& label) const { @@ -280,7 +306,7 @@ void Schema::Serialize(std::unique_ptr& writer) const { grape::InArchive arc; arc << v_primary_keys_ << vproperties_ << vprop_names_ << vprop_storage_ << eproperties_ << eprop_names_ << ie_strategy_ << oe_strategy_ - << sort_on_compactions_ << max_vnum_; + << ie_mutability_ << oe_mutability_ << sort_on_compactions_ << max_vnum_; CHECK(writer->WriteArchive(arc)); } @@ -292,7 +318,7 @@ void Schema::Deserialize(std::unique_ptr& reader) { CHECK(reader->ReadArchive(arc)); arc >> v_primary_keys_ >> vproperties_ >> vprop_names_ >> vprop_storage_ >> eproperties_ >> eprop_names_ >> ie_strategy_ >> oe_strategy_ >> - sort_on_compactions_ >> max_vnum_; + ie_mutability_ >> oe_mutability_ >> sort_on_compactions_ >> max_vnum_; } label_t Schema::vertex_label_to_index(const std::string& label) { @@ -745,6 +771,7 @@ static bool parse_edge_schema(YAML::Node node, Schema& schema) { << cur_ie << ", oe strategy: " << cur_oe; } // check if x_csr_params presents + bool oe_mutable = true, ie_mutable = true; if (cur_node["x_csr_params"]) { auto csr_node = cur_node["x_csr_params"]; if (csr_node["edge_storage_strategy"]) { @@ -798,6 +825,45 @@ static bool parse_edge_schema(YAML::Node node, Schema& schema) { VLOG(10) << "Do not sort on compaction for edge: " << src_label_name << "-[" << edge_label_name << "]->" << dst_label_name; } + + if (csr_node["oe_mutability"]) { + std::string mutability_str; + if (get_scalar(csr_node, "oe_mutability", mutability_str)) { + // mutability_str to upper_case + std::transform(mutability_str.begin(), mutability_str.end(), + mutability_str.begin(), ::toupper); + if (mutability_str == "IMMUTABLE") { + oe_mutable = false; + } else if (mutability_str == "MUTABLE") { + oe_mutable = true; + } else { + LOG(ERROR) << "oe_mutability is not set properly for edge: " + << src_label_name << "-[" << edge_label_name << "]->" + << dst_label_name + << ", expect IMMUTABLE/MUTABLE, got:" << mutability_str; + return false; + } + } + } + if (csr_node["ie_mutability"]) { + std::string mutability_str; + if (get_scalar(csr_node, "ie_mutability", mutability_str)) { + // mutability_str to upper_case + std::transform(mutability_str.begin(), mutability_str.end(), + mutability_str.begin(), ::toupper); + if (mutability_str == "IMMUTABLE") { + ie_mutable = false; + } else if (mutability_str == "MUTABLE") { + ie_mutable = true; + } else { + LOG(ERROR) << "ie_mutability is not set properly for edge: " + << src_label_name << "-[" << edge_label_name << "]->" + << dst_label_name + << ", expect IMMUTABLE/MUTABLE, got:" << mutability_str; + return false; + } + } + } } VLOG(10) << "edge " << edge_label_name << " from " << src_label_name @@ -805,7 +871,7 @@ static bool parse_edge_schema(YAML::Node node, Schema& schema) { << " properties"; schema.add_edge_label(src_label_name, dst_label_name, edge_label_name, property_types, prop_names, cur_oe, cur_ie, - cur_sort_on_compaction); + oe_mutable, ie_mutable, cur_sort_on_compaction); } // check the type_id equals to storage's label_id diff --git a/flex/storages/rt_mutable_graph/schema.h b/flex/storages/rt_mutable_graph/schema.h index 3eefc91a4f9d..ad8627ab4976 100644 --- a/flex/storages/rt_mutable_graph/schema.h +++ b/flex/storages/rt_mutable_graph/schema.h @@ -65,6 +65,7 @@ class Schema { const std::vector& prop_names, EdgeStrategy oe = EdgeStrategy::kMultiple, EdgeStrategy ie = EdgeStrategy::kMultiple, + bool oe_mutable = true, bool ie_mutable = true, bool sort_on_compaction = false); label_t vertex_label_num() const; @@ -145,6 +146,14 @@ class Schema { const std::string& dst_label, const std::string& label) const; + bool outgoing_edge_mutable(const std::string& src_label, + const std::string& dst_label, + const std::string& label) const; + + bool incoming_edge_mutable(const std::string& src_label, + const std::string& dst_label, + const std::string& label) const; + bool get_sort_on_compaction(const std::string& src_label, const std::string& dst_label, const std::string& label) const; @@ -201,6 +210,8 @@ class Schema { std::map> eprop_names_; std::map oe_strategy_; std::map ie_strategy_; + std::map oe_mutability_; + std::map ie_mutability_; std::map sort_on_compactions_; std::vector max_vnum_; std::unordered_map> diff --git a/flex/utils/property/types.cc b/flex/utils/property/types.cc index f4f893406900..0b04865ecd5d 100644 --- a/flex/utils/property/types.cc +++ b/flex/utils/property/types.cc @@ -193,7 +193,9 @@ grape::OutArchive& operator>>(grape::OutArchive& out_archive, Any& value) { } else if (value.type == PropertyType::Double()) { out_archive >> value.value.db; } else if (value.type == PropertyType::Date()) { - out_archive >> value.value.d.milli_second; + int64_t date_val; + out_archive >> date_val; + value.value.d.milli_second = date_val; } else if (value.type == PropertyType::Day()) { uint32_t val; out_archive >> val; diff --git a/flex/utils/property/types.h b/flex/utils/property/types.h index 3eb8601d00f1..d95fd5043661 100644 --- a/flex/utils/property/types.h +++ b/flex/utils/property/types.h @@ -121,7 +121,7 @@ struct PropertyType { bool operator!=(const PropertyType& other) const; }; -struct Date { +struct __attribute__((packed)) Date { Date() = default; ~Date() = default; Date(int64_t x);