neug-rust 0.1.0

Safe Rust bindings for the NeuG C++ graph database engine
docs.rs failed to build neug-rust-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

neug-rust

A Safe Rust wrapper for the alibaba/neug C++ graph database engine.

High-performance embedded graph database for analytics and real-time transactions.
graphscope.io/neug

Overview

This project provides high-level, idiomatic Rust bindings to the neug C++ library. It is designed as a Cargo workspace with two main crates:

  • neug-sys: Contains the low-level, unsafe FFI bindings generated by bindgen and the build script that compiles the underlying C++ library using CMake.
  • neug-rust (in the neug-bindings directory): Provides a safe, user-friendly Rust API (Database, Connection, etc.) that wraps the raw C++ pointers and handles memory management automatically.

Note: The architecture and intelligent CMake build mechanism of this repository were heavily inspired by the excellent zvec-rust-binding project. Like zvec, our build script will automatically download the required C++ source code during cargo build if it is not present locally, bypassing the crates.io size limits.

Prerequisites

Building neug from source requires several C++ dependencies installed on your system, as defined by its CMake configuration. Please ensure you have the following installed (e.g., via brew on macOS or apt on Linux):

  • CMake (>= 3.16)
  • C++20 compatible compiler (Clang/GCC)
  • OpenSSL
  • gflags, glog

Note: Heavy dependencies like Apache Arrow, Protobuf, and Abseil are automatically downloaded and built by the internal CMake script.

Getting Started

Local Development

  1. Clone the repository with submodules:

    git clone --recursive https://github.com/miofthena/neug-rust.git
    cd neug-rust
    

    (If already cloned, run git submodule update --init --recursive)

  2. Build the workspace:

    cargo build
    

    Note: The first build will take a significant amount of time (often >5 minutes) as it compiles the entire C++ codebase and its dependencies.

  3. Run Tests:

    cargo test
    
  4. Run Examples:

    cargo run --example simple_example
    cargo run --example crud_operations
    cargo run --example parallel_query
    

Speeding up C++ Compilation

To prevent the underlying C++ library (neug-cpp) from compiling from scratch on subsequent builds or across workspaces, it is highly recommended to install a compiler cache tool. Our build script automatically detects and utilizes them:

  • Install sccache (via cargo install sccache or brew/apt)
  • Or install ccache (via brew/apt)

Performance & Benchmarks

The library is continuously benchmarked using criterion to measure the overhead introduced by the Rust FFI boundary and data preparation. Because the wrappers are extremely thin, the actual dispatch overhead is practically non-existent.

Running the realistic workloads (cargo bench) on an Apple Silicon (M-series) chip yields the following Rust Wrapper Overhead:

  • Connection Lifecycle: ~1.85 µs - The time required to initialize and teardown a safe Rust connection proxy pointing to the C++ engine.
  • Query Dispatch (Parse & Execute): ~98.2 µs - The total time it takes to allocate strings in Rust, pass them across the FFI boundary, and have the C++ engine parse and execute a simple Cypher MATCH query.

(Note: These benchmarks measure the overhead of the Rust bindings, not the underlying neug C++ engine's execution time, as that varies by workload).

Usage Example

use neug_rust::{Database, Mode};
use tempfile::tempdir;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let dir = tempdir()?;
    
    // 1. Initialize the database
    let mut db = Database::open(dir.path(), Mode::ReadWrite)?;

    // 2. Open a connection
    let mut conn = db.connect()?;

    // 3. Execute DDL / DML queries
    conn.execute("CREATE NODE TABLE person(id INT64, name STRING, age INT64, PRIMARY KEY(id));")?;
    conn.execute("CREATE REL TABLE knows(FROM person TO person, weight DOUBLE);")?;

    // 4. Query data
    let _result = conn.execute("MATCH (n)-[e]-(m) return count(e);")?;
    println!("Queries executed successfully.");

    // The database and connections are automatically closed when dropped.
    Ok(())
}

Contributing

  1. Add high-level, safe Rust abstractions in neug-bindings/src/.
  2. Ensure you adhere to standard Rust community practices (e.g., cargo fmt, cargo clippy).
  3. Add tests to verify your safe wrappers in neug-bindings/tests/.

License

This wrapper is licensed under the same terms as the neug project (Apache License 2.0).