Back to Ip2region

README

binding/rust/README.md

3.15.07.9 KB
Original Source

:globe_with_meridians: 中文简体 | English

ip2region rust Query Client

Features

  • Supports queries using both ip strings and u32/u28 numeric types
  • Supports IPv4 and IPv6
  • Supports three modes: No Cache, Vector Index Cache, and Full Data Cache

Cache Policy Comparison and Description

Cache ModeIPv4 Memory UsageIPv6 Memory UsageIPv4 benchmark query timeIPv6 benchmark query time
No Cache1-2MB1-2MB54 us122us
vector index1-2MB1-2MB27 us100us
Full Cache20 MB200 MB120 ns178 ns
  • During the initialization of ip2region::Searcher, an IO operation occurs to read the xdb header information to initialize the Searcher. The header information mainly includes the IP version of the xdb. This operation does not affect the performance or time consumption of subsequent IP queries and occupies approximately 20 additional bytes of memory.
  • In No Cache mode and vector index cache mode, all xdb IO reads are performed on-demand (based on bytes offset and bytes length) for small amounts of information. Both are thread-safe, as verified by benchmark testing.
  • In Full Cache mode, the xdb file is read and loaded into memory at once. Testing shows the IPv6 xdb file occupies about 200MB of memory. If queries are infrequent, memory usage will gradually decrease.
  • In all cache modes, including during the initialization of ip2region::Searcher, the program is thread-safe. There are no globally modifiable intermediate variables. After ip2region::Searcher initialization is complete, calling the search function uses immutable references. Meanwhile, ip2region::Searcher can also be passed to different threads using Arc.

Usage

Create a new project using cargo, such as cargo new ip-test

Configure [dependencies] in Cargo.toml as follows:

toml
[dependencies]
ip2region = { git = "https://github.com/lionsoul2014/ip2region.git", branch = "master" }

Basic Usage Example

Write main.rs

rust
use ip2region::{CachePolicy, Searcher};

fn main() {
    for cache_policy in [
        CachePolicy::NoCache,
        CachePolicy::FullMemory,
        CachePolicy::VectorIndex,
    ] {
        // Create an IPv4 searcher
        let ipv4_seacher = Searcher::new("../ip2region/data/ip2region_v4.xdb".to_owned(), cache_policy).unwrap();
        for ip in [1_u32, 2, 3] {
            let result = ipv4_seacher.search(ip).unwrap();
            println!("CachePolicy: {cache_policy:?}, IP: {ip}, Result: {result}");
        }

        for ip in ["1.1.1.1", "2.2.2.2"] {
            let result = ipv4_seacher.search(ip).unwrap();
            println!("CachePolicy: {cache_policy:?}, IP: {ip}, Result: {result}");
        }

        // Create an IPv6 searcher
        let ipv6_seacher = Searcher::new("../ip2region/data/ip2region_v6.xdb".to_owned(), cache_policy).unwrap();
        for ip in ["2001::", "2001:4:112::"] {
            let result = ipv6_seacher.search(ip).unwrap();
            println!("CachePolicy: {cache_policy:?}, IP: {ip}, Result: {result}");
        }

        for ip in [1_u128, 2, 3<<125] {
            let result = ipv6_seacher.search(ip).unwrap();
            println!("CachePolicy: {cache_policy:?}, IP: {ip}, Result: {result}");
        }
    }
}

Cache policy benchmark

bash
$ cd binding/rust/ip2region
$ cargo test
$ cargo bench

// --snip---
ipv4_no_memory_bench    time:   [54.699 µs 57.401 µs 61.062 µs]
Found 16 outliers among 100 measurements (16.00%)
  10 (10.00%) high mild
  6 (6.00%) high severe

ipv4_vector_index_cache_bench
                        time:   [25.972 µs 26.151 µs 26.360 µs]
Found 9 outliers among 100 measurements (9.00%)
  1 (1.00%) low severe
  6 (6.00%) high mild
  2 (2.00%) high severe

ipv4_full_memory_cache_bench
                        time:   [132.04 ns 139.48 ns 149.20 ns]
Found 10 outliers among 100 measurements (10.00%)
  4 (4.00%) high mild
  6 (6.00%) high severe

ipv6_no_memory_bench    time:   [121.00 µs 122.14 µs 123.40 µs]
Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) high mild
  3 (3.00%) high severe

ipv6_vector_index_cache_bench
                        time:   [96.830 µs 100.23 µs 104.81 µs]
Found 8 outliers among 100 measurements (8.00%)
  2 (2.00%) high mild
  6 (6.00%) high severe

ipv6_full_memory_cache_bench
                        time:   [175.29 ns 178.82 ns 183.77 ns]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) high mild
  4 (4.00%) high severe
// --snip--

Testing, Result Verification, and Benchmark

bash
$ cd binding/rust/example
$ cargo build -r

The location of the built executable is binding/rust/target/release/searcher

Testing IPv6 and IPv4 requires verifying query results against the contents of ipv6_source.txt and ipv4_source.txt.

The query results shown here represent data at the current time; subsequent results may differ due to updates and corrections in the IP region segments of ip_source.txt and xdb binary data.

Test IPv6

bash
$ cd binding/rust
$ cargo build -r
$ ./target/release/searcher --xdb='../../data/ip2region_v6.xdb' query
ip2region xdb searcher test program, type `quit` or `Ctrl + c` to exit
ip2region>> ::
region: Ok(""), took: 79.651412ms
ip2region>> 240e:3b7:3273:51d0:cd38:8ae1:e3c0:b708
region: Ok("中国|广东省|深圳市|电信|CN"), took: 7.575µs
ip2region>> 2001::
region: Ok("0|0|Reserved|Reserved|Reserved"), took: 7.256µs
ip2region>> 2001:268:9a02:8888::
region: Ok("Japan|Aichi|Nagoya|KDDI CORPORATION|JP"), took: 7.921µs
ip2region>> 2a02:26f7:b408:a6c2::
region: Ok("United States|Virginia|Emporia|Akamai Technologies, Inc.|US"), took: 8.461µs
ip2region>> 2c99::
region: Ok("0|0|Reserved|Reserved|Reserved"), took: 5.33µs

Test IPv4

bash
$ cd binding/rust
$ cargo build -r
$  ./target/release/searcher --xdb='../../data/ip2region_v4.xdb' query
ip2region xdb searcher test program, type `quit` or `Ctrl + c` to exit
ip2region>> 1.2.3.4
region: Ok("Australia|Queensland|Brisbane|0|AU"), took: 6.07µs
ip2region>> 1.1.2.1
region: Ok("中国|福建省|福州市|0|CN"), took: 5.653µs
ip2region>> 2.2.21.1
region: Ok("United States|Texas|0|Oracle Svenska AB|US"), took: 4.556µs

Benchmark and Result Verification

Test performance via the searcher program while comparing query results against ip sources files to check for errors.

bash
$ cd binding/rust/example
$ cargo build -r
## Perform IPv4 bench test using data/ip2region_v4.xdb and data/ipv4_source.txt:
$ RUST_LOG=debug ../target/release/searcher --xdb='../../../data/ip2region_v4.xdb' bench '../../../data/ipv4_source.txt'
2025-09-24T07:02:07.840535Z DEBUG ip2region::searcher: Load xdb file with header header=Header { version: 3, index_policy: VectorIndex, create_time: 1757125456, start_index_ptr: 955933, end_index_ptr: 11042415, ip_version: V4, runtime_ptr_bytes: 4 }
2025-09-24T07:02:07.840894Z DEBUG ip2region::searcher: Load vector index cache
2025-09-24T07:02:07.840905Z DEBUG ip2region::searcher: Load full cache filepath="../../../data/ip2region_v4.xdb"
2025-09-24T07:02:08.409990Z  INFO searcher: Benchmark finished count=3404406 took=569.388667ms avg_took=167ns

## Perform IPv6 bench test using data/ip2region_v6.xdb and data/ipv6_source.txt:
$ RUST_LOG=debug ../target/release/searcher --xdb='../../../data/ip2region_v6.xdb' bench '../../../data/ipv6_source.txt'
2025-09-24T07:01:48.991835Z DEBUG ip2region::searcher: Load xdb file with header header=Header { version: 3, index_policy: VectorIndex, create_time: 1756970508, start_index_ptr: 6585371, end_index_ptr: 647078145, ip_version: V6, runtime_ptr_bytes: 4 }
2025-09-24T07:01:48.992557Z DEBUG ip2region::searcher: Load vector index cache
2025-09-24T07:01:48.992563Z DEBUG ip2region::searcher: Load full cache filepath="../../../data/ip2region_v6.xdb"
2025-09-24T07:01:59.775879Z  INFO searcher: Benchmark finished count=38335905 took=10.784124584s avg_took=281ns