Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GitHub

This documentation is part of the "Projects with Books" initiative at zenOSmosis.

The source code for this project is available on GitHub.

Method ID Generation

Loading…

Method ID Generation

Relevant source files

This page explains how the muxio RPC framework generates unique identifiers for RPC methods at compile time using the xxhash algorithm. Method IDs enable efficient method dispatch without runtime string comparisons or schema files.

For information about defining RPC services using these method IDs, see Creating Service Definitions. For details about the serialization format that carries method IDs over the wire, see Serialization with Bitcode.


Overview

The muxio RPC framework generates a unique 64-bit method identifier for each RPC method by hashing the method’s fully-qualified name at compile time. This approach provides several key benefits:

AspectImplementation
Hash Algorithmxxhash (xxHash64 variant)
InputFully-qualified method name as UTF-8 string
Output64-bit unsigned integer (u64)
Generation TimeCompile time (zero runtime overhead)
Collision HandlingDeterministic; same name always produces same ID

The generated method IDs are embedded directly into service definition constants, eliminating the need for runtime string hashing or lookup tables. Both client and server compile against the same service definitions, ensuring that method IDs match across platforms.

Sources:

  • Cargo.lock:1886-1889 (xxhash-rust dependency)
  • extensions/muxio-rpc-service/Cargo.toml:16 (xxhash-rust in dependencies)

The xxhash Algorithm

The muxio framework uses the xxhash-rust crate to generate method IDs. xxhash was selected for its specific characteristics:

graph LR
    Input["Method Name String\n(UTF-8 bytes)"]
XXH64["xxHash64 Algorithm"]
Output["64-bit Method ID\n(u64)"]
Input --> XXH64
 
   XXH64 --> Output
    
    Props["Properties:\n- Deterministic\n- Fast (compile-time only)\n- Non-cryptographic\n- Low collision rate\n- Platform-independent"]
XXH64 -.-> Props

Algorithm Characteristics

Why xxhash?

PropertyBenefit
DeterministicSame method name always produces the same ID across all platforms and compilations
FastMinimal compile-time overhead; speed matters less since generation is compile-time only
Non-cryptographicNo security requirements for method IDs; simpler algorithm reduces dependencies
Low collision rateStatistical likelihood of two different method names producing the same ID is negligible
64-bit outputLarge enough keyspace (2^64 possible IDs) to avoid collisions in practice

The framework does not perform collision detection because:

  1. The 64-bit keyspace makes collisions statistically improbable for any reasonable number of methods
  2. Methods are identified by fully-qualified names (including trait and module paths), further reducing collision likelihood
  3. If a collision does occur, it will manifest as a method routing error detectable during testing

Sources:

  • Cargo.lock:1886-1889 (xxhash-rust package metadata)
  • extensions/muxio-rpc-service/Cargo.toml:3 (core traits and method ID generation description)

Compile-Time Generation Mechanism

Method IDs are computed during compilation, not at runtime. The generation process integrates with Rust’s trait system and constant evaluation capabilities.

sequenceDiagram
    participant Source as "Service Definition Source Code"
    participant Compiler as "Rust Compiler"
    participant XXHash as "xxhash-rust Crate"
    participant Binary as "Compiled Binary"
    
    Note over Source: RpcMethodPrebuffered trait\nwith method name
    Source->>Compiler: Compile service definition
    Compiler->>XXHash: Hash method name constant
    XXHash-->>Compiler: Return u64 method ID
    Compiler->>Compiler: Embed ID as constant (METHOD_ID)
    Compiler->>Binary: Include ID in binary
    Note over Binary: Method ID available at runtime\nas a simple constant

Generation Flow

Constant Evaluation

The method ID is generated using Rust’s const fn capabilities, making the hash computation part of compile-time constant evaluation:

  1. Service definition declares a method name as a string constant
  2. The xxhash function (or wrapper) is invoked at compile time
  3. The resulting u64 is stored as a const associated with the method
  4. This constant is directly embedded in the compiled binary

This approach means:

  • Zero runtime cost : No hashing occurs during program execution
  • Type safety : Method IDs are compile-time constants that cannot be accidentally modified
  • Cross-platform consistency : The same source code produces identical method IDs on all platforms

Sources:

  • extensions/muxio-rpc-service/Cargo.toml:3 (compile-time method ID generation description)
  • Cargo.lock:858-867 (muxio-rpc-service dependencies including xxhash-rust)

Integration with Service Definitions

Method IDs are tightly integrated with the RpcMethodPrebuffered trait, which defines the contract for RPC methods.

graph TB
    Trait["RpcMethodPrebuffered Trait"]
MethodName["METHOD_NAME: &'static str\ne.g., 'MyService::calculate'"]
MethodID["METHOD_ID: u64\nxxhash64(METHOD_NAME)"]
Params["Params Type\n(Serializable)"]
Response["Response Type\n(Serializable)"]
Trait --> MethodName
 
   Trait --> MethodID
 
   Trait --> Params
 
   Trait --> Response
    
    MethodName -.generates.-> MethodID
    
    RpcRequest["RpcRequest Structure"]
RpcRequest --> MethodIDField["method_id: u64"]
RpcRequest --> ParamsField["params: Vec<u8>\n(serialized)"]
MethodID -.copied into.-> MethodIDField
    Params -.serialized into.-> ParamsField

Method ID in Service Definition Structure

Method ID Storage and Usage

Each service definition provides:

ComponentTypePurpose
METHOD_NAME&'static strHuman-readable method identifier (used for debugging/logging)
METHOD_IDu64Hashed identifier used in binary protocol
ParamsAssociated typeRequest parameter structure
ResponseAssociated typeResponse result structure

The METHOD_ID constant is used when:

  • Encoding requests : Client includes method ID in RpcRequest header
  • Dispatching requests : Server uses method ID to route to the appropriate handler
  • Validating responses : Client verifies the response corresponds to the correct method

Sources:

  • extensions/muxio-rpc-service/Cargo.toml:3 (core traits and types description)
  • Cargo.lock:858-867 (muxio-rpc-service package with xxhash dependency)

sequenceDiagram
    participant Client as "RPC Client"
    participant Network as "Binary Transport"
    participant Dispatcher as "RpcDispatcher"
    participant Endpoint as "RpcServiceEndpoint"
    participant Handler as "Method Handler"
    
    Note over Client: METHOD_ID = xxhash64("Add")
    Client->>Client: Create RpcRequest with METHOD_ID
    Client->>Network: Serialize and send request
    Network->>Dispatcher: Receive binary frames
    Dispatcher->>Dispatcher: Extract method_id from RpcRequest
    Dispatcher->>Endpoint: Route by method_id (u64 comparison)
    
    alt Method ID Registered
        Endpoint->>Handler: Invoke handler for METHOD_ID
        Handler-->>Endpoint: Return response
        Endpoint-->>Dispatcher: Send RpcResponse
    else Method ID Unknown
        Endpoint-->>Dispatcher: Return MethodNotFound error
    end
    
    Dispatcher-->>Network: Serialize and send response
    Network-->>Client: Deliver response

Method Dispatch Using IDs

At runtime, method IDs enable efficient dispatch without string comparisons or lookup tables.

Request Processing Flow

Dispatch Performance Characteristics

The use of 64-bit integer method IDs provides:

CharacteristicBenefit
O(1) lookupHash map dispatch using HashMap<u64, Handler>
No string allocationMethod names never allocated at runtime
Cache-friendlyInteger comparison much faster than string comparison
Minimal memory8 bytes per method ID vs. variable-length strings

The endpoint maintains a dispatch table:

HashMap<u64, Arc<dyn MethodHandler>>
  key: METHOD_ID (e.g., 0x12ab34cd56ef7890)
  value: Handler function for that method

When a request arrives with method_id = 0x12ab34cd56ef7890, the dispatcher performs a simple hash map lookup to find the handler.

Sources:

  • extensions/muxio-rpc-service/Cargo.toml:3 (service traits and method dispatch)
  • Cargo.lock:883-895 (muxio-rpc-service-endpoint package)

graph TB
    subgraph "Development Time"
        Define["Define Service:\ntrait MyMethod"]
Name["METHOD_NAME =\n'MyService::add'"]
Hash["Compile-time xxhash64"]
Constant["const METHOD_ID: u64 =\n0x3f8a4b2c1d9e7654"]
Define --> Name
 
       Name --> Hash
 
       Hash --> Constant
    end
    
    subgraph "Client Runtime"
        CallSite["Call my_method(params)"]
CreateReq["Create RpcRequest:\nmethod_id: 0x3f8a4b2c1d9e7654\nparams: serialized"]
Encode["Encode to binary frames"]
CallSite --> CreateReq
        Constant -.embedded in.-> CreateReq
 
       CreateReq --> Encode
    end
    
    subgraph "Network"
        Transport["WebSocket/TCP Transport\nBinary protocol"]
end
    
    subgraph "Server Runtime"
        Decode["Decode binary frames"]
ExtractID["Extract method_id:\n0x3f8a4b2c1d9e7654"]
Lookup["HashMap lookup:\nhandlers[0x3f8a4b2c1d9e7654]"]
Execute["Execute handler function"]
Decode --> ExtractID
 
       ExtractID --> Lookup
 
       Lookup --> Execute
        Constant -.registered in.-> Lookup
    end
    
 
   Encode --> Transport
 
   Transport --> Decode
    
    style Constant fill:#f9f9f9
    style CreateReq fill:#f9f9f9
    style Lookup fill:#f9f9f9

Complete Method ID Lifecycle

This diagram traces a method ID from definition through compilation, serialization, and dispatch:

Sources:

  • extensions/muxio-rpc-service/Cargo.toml:1-9 (service definition crate overview)
  • Cargo.lock:858-867 (muxio-rpc-service dependencies)
  • Cargo.lock:883-895 (muxio-rpc-service-endpoint for handler registration)

Benefits and Design Trade-offs

Advantages

BenefitExplanation
Zero Runtime CostHash computation happens once at compile time; runtime operations use simple integer comparisons
Type SafetyMethod IDs are compile-time constants; cannot be accidentally modified or corrupted
Platform IndependenceSame method name produces identical ID on all platforms (Windows, Linux, macOS, WASM)
No Schema FilesService definitions are Rust code; no external IDL or schema generation tools required
Fast DispatchInteger hash map lookup is faster than string comparison or reflection-based dispatch
Compact Wire Format8-byte method ID vs. variable-length method name string

Design Considerations

ConsiderationMitigation
Hash Collisions64-bit keyspace makes collisions statistically improbable; detected during testing if they occur
Method VersioningChanging a method name produces a new ID; requires coordinated client/server updates
DebuggingMethod names are logged alongside IDs for human readability during development
Binary CompatibilityChanging method names breaks wire compatibility; version management required at application level

The framework prioritizes simplicity and performance over elaborate versioning mechanisms. Applications requiring complex API evolution strategies should implement versioning at a higher level (e.g., versioned service definitions or API paths).

Sources:

  • extensions/muxio-rpc-service/Cargo.toml:3 (compile-time method ID generation)
  • Cargo.lock:1886-1889 (xxhash-rust algorithm choice)

Example: Method ID Generation in Practice

Consider a simple service definition:

Method Definition Components

Step-by-Step Process

  1. Definition : Developer writes struct AddMethod implementing RpcMethodPrebuffered
  2. Naming : Trait defines const METHOD_NAME: &'static str = "calculator::Add"
  3. Hashing : Compiler invokes xxhash64("calculator::Add") at compile time
  4. Constant : Result (e.g., 0x9c5f3a2b8d7e4f61) stored as const METHOD_ID: u64
  5. Client Usage : When calling Add, client creates RpcRequest { method_id: 0x9c5f3a2b8d7e4f61, ... }
  6. Server Registration : Server registers handler: handlers.insert(0x9c5f3a2b8d7e4f61, add_handler)
  7. Dispatch : Server receives request, extracts method_id, performs HashMap lookup, invokes handler

This entire flow occurs with zero string operations at runtime, providing efficient method dispatch across client and server implementations.

Sources:

  • extensions/muxio-rpc-service/Cargo.toml:1-18 (service definition crate structure)
  • Cargo.lock:858-867 (muxio-rpc-service dependencies including xxhash-rust)