mirror of
https://github.com/lionsoul2014/ip2region.git
synced 2025-12-08 19:25:22 +00:00
Feat: improve bench query code in rust example, add usage at Readme
This commit is contained in:
parent
b6410e16d0
commit
d3592eb7cd
@ -66,7 +66,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## Benchmark 测试
|
||||
## Cache policy benchmark
|
||||
|
||||
```bash
|
||||
$ git lfs pull
|
||||
@ -111,3 +111,53 @@ Found 6 outliers among 100 measurements (6.00%)
|
||||
4 (4.00%) high severe
|
||||
// --snip--
|
||||
```
|
||||
|
||||
## 测试与结果验证,benchmark
|
||||
```bash
|
||||
$ git lfs pull
|
||||
$ cd binding/rust/example
|
||||
$ cargo build -r
|
||||
```
|
||||
构建的执行程序位置 `binding/rust/target/release/searcher`
|
||||
|
||||
#### 测试 IPv6
|
||||
```bash
|
||||
$ cd binding/rust
|
||||
$ ./target/release/searcher --xdb='../../data/ip2region_v6.xdb' query
|
||||
|
||||
ip2region xdb searcher test program, type `quit` or `Ctrl + c` to exit
|
||||
ip2region>> 2001:5:4::
|
||||
region: Ok("荷兰|北荷兰省|阿姆斯特丹|专线用户"), took: 284.80775ms
|
||||
ip2region>> 2001::
|
||||
region: Ok("美国|加利福尼亚州|洛杉矶|专线用户"), took: 12.75µs
|
||||
ip2region>> 2001:5:6::
|
||||
region: Ok("荷兰|北荷兰省|阿姆斯特丹|专线用户"), took: 52.958µs
|
||||
ip2region>> 2001:5:5::
|
||||
region: Ok("比利时|弗拉芒大区|泽勒|专线用户"), took: 123.375µs
|
||||
ip2region>>
|
||||
```
|
||||
|
||||
#### 测试 IPv4
|
||||
```bash
|
||||
$ cd binding/rust
|
||||
$ ./target/release/searcher --xdb='../../data/ip2region_v4.xdb' query
|
||||
ip2region xdb searcher test program, type `quit` or `Ctrl + c` to exit
|
||||
ip2region>> 1.1.2.1
|
||||
region: Ok("中国|福建省|福州市|电信"), took: 5.342625ms
|
||||
ip2region>> 2.2.21.1
|
||||
region: Ok("法国|0|0|橘子电信"), took: 25.667µs
|
||||
ip2region>>
|
||||
```
|
||||
|
||||
#### Benchmark 与验证结果
|
||||
|
||||
通过 searcher 程序来测试性能,同时依据 ip sources 文件对比查询结果,检测是否存在错误
|
||||
|
||||
```bash
|
||||
$ cd binding/rust/example
|
||||
$ cargo build -r
|
||||
## 通过 data/ip2region_v4.xdb 和 data/ipv4_source.txt 进行 ipv4 的 bench 测试:
|
||||
$ RUST_LOG=debug ../target/release/searcher --xdb='../../../data/ip2region_v4.xdb' bench '../../../data/ipv4_source.txt'
|
||||
## 通过 data/ip2region_v6.xdb 和 data/ipv6_source.txt 进行 ipv6 的 bench 测试:
|
||||
$ RUST_LOG=debug ../target/release/searcher --xdb='../../../data/ip2region_v6.xdb' bench '../../../data/ipv6_source.txt'
|
||||
```
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rust-example"
|
||||
default-run = "rust-example"
|
||||
name = "searcher"
|
||||
default-run = "searcher"
|
||||
version = "0.2.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.89.0"
|
||||
@ -13,3 +13,4 @@ license = "Apache-2.0"
|
||||
ip2region = { path = "../ip2region" }
|
||||
clap = { version = "4.5", features = ["derive", "env"] }
|
||||
tracing-subscriber = "0.3"
|
||||
tracing = "0.1"
|
||||
|
||||
@ -12,9 +12,9 @@ use clap::{Parser, Subcommand, ValueEnum};
|
||||
///
|
||||
/// cd binding/rust/example
|
||||
///
|
||||
/// cargo run -r -- --xdb=$XDB bench $CHECK
|
||||
/// ./searcher --xdb=$XDB bench $CHECK
|
||||
///
|
||||
/// cargo run -r -- --xdb=$XDB query
|
||||
/// ./searcher --xdb=$XDB query
|
||||
///
|
||||
/// ```
|
||||
#[derive(Parser)]
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
extern crate core;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::io::{BufRead, BufReader};
|
||||
@ -7,49 +5,52 @@ use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::cmd::{Action, CmdCachePolicy, Command};
|
||||
use clap::Parser;
|
||||
use tracing::info;
|
||||
use ip2region::{CachePolicy, Searcher};
|
||||
|
||||
use crate::cmd::{Action, CmdCachePolicy, Command};
|
||||
|
||||
mod cmd;
|
||||
|
||||
macro_rules! perform_check {
|
||||
($searcher:expr, $start_ip:expr, $end_ip:expr, $check:expr) => {{
|
||||
let start_ip = $start_ip;
|
||||
let end_ip = $end_ip;
|
||||
|
||||
let mid_ip = (start_ip >> 1) + (end_ip >> 1);
|
||||
|
||||
let checks = [
|
||||
start_ip,
|
||||
(start_ip >> 1) + (mid_ip >> 1),
|
||||
mid_ip,
|
||||
(mid_ip >> 1) + (end_ip >> 1),
|
||||
end_ip,
|
||||
];
|
||||
for ip in checks.iter() {
|
||||
if *ip > start_ip || *ip < end_ip {
|
||||
// IP not in start - end ip
|
||||
// This happens when start ip equals end ip
|
||||
continue;
|
||||
}
|
||||
let result = $searcher.search(*ip).unwrap();
|
||||
assert_eq!(result.as_str(), $check);
|
||||
}
|
||||
checks.len()
|
||||
}};
|
||||
}
|
||||
|
||||
fn check(searcher: &Searcher, start_ip: IpAddr, end_ip: IpAddr, check: &str) -> usize {
|
||||
match (start_ip, end_ip) {
|
||||
(IpAddr::V4(start_ip), IpAddr::V4(end_ip)) => {
|
||||
let start_ip = u32::from(start_ip);
|
||||
let end_ip = u32::from(end_ip);
|
||||
let mid_ip = (start_ip >> 1) + (end_ip >> 1);
|
||||
|
||||
let checks = [
|
||||
start_ip,
|
||||
(start_ip >> 1) + (mid_ip >> 1),
|
||||
mid_ip,
|
||||
(mid_ip >> 1) + (end_ip >> 1),
|
||||
end_ip,
|
||||
];
|
||||
for ip in checks.iter() {
|
||||
let result = searcher.search(*ip).unwrap();
|
||||
assert_eq!(result.as_str(), check);
|
||||
(IpAddr::V4(original_start_ip), IpAddr::V4(original_end_ip)) => {
|
||||
let start_ip = u32::from(original_start_ip);
|
||||
let end_ip = u32::from(original_end_ip);
|
||||
perform_check!(searcher, start_ip, end_ip, check)
|
||||
}
|
||||
checks.len()
|
||||
}
|
||||
(IpAddr::V6(start_ip), IpAddr::V6(end_ip)) => {
|
||||
let start_ip = u128::from(start_ip);
|
||||
let end_ip = u128::from(end_ip);
|
||||
let mid_ip = (start_ip >> 1) + (end_ip >> 1);
|
||||
|
||||
let checks = [
|
||||
start_ip,
|
||||
(start_ip >> 1) + (mid_ip >> 1),
|
||||
mid_ip,
|
||||
(mid_ip >> 1) + (end_ip >> 1),
|
||||
end_ip,
|
||||
];
|
||||
for ip in checks.iter() {
|
||||
let result = searcher.search(*ip).unwrap();
|
||||
assert_eq!(result.as_str(), check);
|
||||
}
|
||||
checks.len()
|
||||
(IpAddr::V6(original_start_ip), IpAddr::V6(original_end_ip)) => {
|
||||
let start_ip = u128::from(original_start_ip);
|
||||
let end_ip = u128::from(original_end_ip);
|
||||
perform_check!(searcher, start_ip, end_ip, check)
|
||||
}
|
||||
_ => panic!("invalid start ip and end ip"),
|
||||
}
|
||||
@ -59,35 +60,18 @@ fn bench(searcher: &Searcher, check_filepath: &str) {
|
||||
let file = File::open(check_filepath).unwrap();
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
let lines = reader.lines().take(100_000).collect::<Vec<_>>();
|
||||
let now = Instant::now();
|
||||
let mut count = 0;
|
||||
|
||||
for line in lines {
|
||||
let line = line.unwrap();
|
||||
if !line.contains('|') {
|
||||
continue;
|
||||
}
|
||||
for line in reader.lines().map_while(Result::ok) {
|
||||
let ip_test_line = line.splitn(3, '|').collect::<Vec<&str>>();
|
||||
if ip_test_line.len() != 3 {
|
||||
panic!("this line {line} don`t have enough `|` for spilt");
|
||||
}
|
||||
if ip_test_line.len() == 3 {
|
||||
let start_ip = IpAddr::from_str(ip_test_line[0]).unwrap();
|
||||
let end_ip = IpAddr::from_str(ip_test_line[1]).unwrap();
|
||||
if end_ip < start_ip {
|
||||
panic!("start ip({start_ip}) should not be greater than end ip({end_ip})")
|
||||
}
|
||||
{
|
||||
count += check(searcher, start_ip, end_ip, ip_test_line[2]);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"Bench finished, total: {count},\
|
||||
took: {:?} ,\
|
||||
cost: {:?}/op",
|
||||
now.elapsed(),
|
||||
now.elapsed() / count as u32
|
||||
)
|
||||
info!(count, took=?now.elapsed(), avg_took=?(now.elapsed() / (count as u32)), "Benchmark finished");
|
||||
}
|
||||
|
||||
fn query(searcher: &Searcher) {
|
||||
|
||||
@ -3,4 +3,5 @@ mod header;
|
||||
mod ip_value;
|
||||
mod searcher;
|
||||
|
||||
pub use self::searcher::{CachePolicy, Searcher};
|
||||
pub use searcher::{CachePolicy, Searcher};
|
||||
pub use ip_value::IpValueExt;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user