Skip to content

Commit

Permalink
Merge pull request #27 from lta-rs/0.6.0
Browse files Browse the repository at this point in the history
0.6.0
  • Loading branch information
zeon256 authored Feb 3, 2024
2 parents d3ed7c3 + e308bdb commit 2a01860
Show file tree
Hide file tree
Showing 15 changed files with 1,397 additions and 556 deletions.
46 changes: 23 additions & 23 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ jobs:
rust: [stable, nightly]

steps:
- uses: rui314/setup-mold@v1
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
run: cargo check --verbose
- uses: rui314/setup-mold@v1
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
run: cargo check --verbose

test:
if: "!contains(github.event.head_commit.message, '[SKIP CI]')"
Expand All @@ -27,13 +27,13 @@ jobs:
rust: [stable, nightly]

steps:
- uses: rui314/setup-mold@v1
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
run: cargo test --verbose
- uses: rui314/setup-mold@v1
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
run: cargo test --verbose

test-fastfloat:
if: "!contains(github.event.head_commit.message, '[SKIP CI]')"
Expand All @@ -44,19 +44,18 @@ jobs:
rust: [stable, nightly]

steps:
- uses: rui314/setup-mold@v1
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
run: cargo test --verbose --features fastfloat
- uses: rui314/setup-mold@v1
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
run: cargo test --verbose --features fastfloat

rustdoc:
runs-on: ubuntu-latest

needs: [check, test, test-fastfloat]
steps:
- uses: rui314/setup-mold@v1
- name: Checkout repository
uses: actions/checkout@v2

Expand All @@ -65,6 +64,7 @@ jobs:

- name: Deploy Docs
uses: peaceiris/actions-gh-pages@364c31d33bb99327c77b3a5438a83a357a6729ad # v3.4.0
if: success() && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[SKIP CI]')
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
Expand Down
16 changes: 9 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "lta_models"
version = "0.5.0"
authors = ["budinverse <[email protected]>"]
version = "0.6.0"
authors = ["zeon256 <[email protected]>"]
edition = "2021"
license = "MIT"
description = "🚍Models for lta-rs"
Expand All @@ -13,22 +13,24 @@ exclude = [
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0.159", features = ["derive"] }
serde = { version = "1.0.195", features = ["derive"] }
serde_repr = "0.1.12"
serde_json = "1.0.95"
regex = "1.7.3"
time = { version = "0.3.20", features = ["serde-human-readable"]}
time = { version = "0.3.20", features = ["serde-human-readable", "macros"]}
lazy_static = "1.4.0"
fast-float = { version = "0.2", optional = true }
serde_json = "1.0.40"

[dev-dependencies]
serde_json = "1.0.40"
bincode = "1.3.3"
criterion = "0.3"
mimalloc = "0.1.25"
rmp-serde = "1.1.2"
flexbuffers = "2.0.0"

[features]
fastfloat = ["fast-float"]

[[bench]]
name = "benchmark"
harness = false
harness = false
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<a href="https://crates.io/crates/lta_models">
<img src="https://img.shields.io/crates/v/lta-models"/>
</a>
<a href="https://crates.io/crates/lta_models">
<img src="https://img.shields.io/badge/forbid_unsafe-yes-blue"/>
</a>
</p>

This repository contains the data structures required to interact with LTA's datamall APIs. All data structures implements `Serialize` and `Deserialize`.
Expand All @@ -23,9 +26,19 @@ This repository contains the data structures required to interact with LTA's dat
## `Cargo.toml` setup
```toml
# extra features available: fastfloat
lta-models = { version = "0.5.0" }
lta-models = { version = "0.6.0" }
```

## Supported formats

| Format | Supported? | Tested? |
| ----------- | ---------- | ------- |
| JSON |||
| Bincode |||
| Flexbuffer |||
| MessagePack |||


## Performance & `fast-float` implementation
Some of the deserialization code _may_ benefit from using the `fastfloat` feature, but during testing the biggest performance improvement can be seen when you swap out the system allocator to something faster like [`mimalloc`](https://github.com/microsoft/mimalloc) or [`jemalloc`](https://github.com/jemalloc/jemalloc)

Expand Down
146 changes: 86 additions & 60 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use lta_models::{bus::bus_arrival::NextBusRaw, prelude::*};

use mimalloc::MiMalloc;
use time::macros::datetime;

#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

#[rustfmt::skip]
mod de {
use lta_models::{prelude::*, crowd::crowd_density::{CrowdDensityForecast, CrowdDensityForecastRawResp}};
use std::fmt::Debug;

use lta_models::prelude::*;
use lta_models::bus::bus_arrival::NextBusRaw;
use serde::{Deserialize, Serialize};

pub fn generate_bench<'de, I, S, F>(input_fn: F) -> S
where
F: FnOnce() -> &'de str,
I: Deserialize<'de> + Into<S>,
S: Serialize,
S: Serialize + Debug
{
let str_data = input_fn();
serde_json::from_str(str_data).map(|v: I| v.into()).unwrap()
Expand All @@ -31,7 +36,7 @@ mod de {
}

pub fn bus_arrival() -> BusArrivalResp {
gen!(RawBusArrivalResp, _, "../dumped_data/bus_arrival.json")
gen!(BusArrivalRespRaw, _, "../dumped_data/bus_arrival.json")
}

pub fn bus_routes() -> Vec<BusRoute> {
Expand Down Expand Up @@ -94,69 +99,90 @@ mod de {
gen!(StationCrowdLevelRawResp, _, "../dumped_data/crowd_density_rt.json")
}

pub fn crowd_density_forecast() -> CrowdDensityForecast {
pub fn crowd_density_forecast() -> CrowdDensityForecast {
gen!(CrowdDensityForecastRawResp, _, "../dumped_data/crowd_density_forecast.json")
}

pub fn transmute_nextbus(data: NextBusRaw) -> NextBus {
let nx = unsafe {
std::mem::transmute::<_, NextBus>(data)
};
nx
}
}

#[rustfmt::skip]
pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("de::bike_parking.json", |b| b.iter(|| de::bike_parking()));
c.bench_function("de::bus_arrival.json", |b| b.iter(|| de::bus_arrival()));
c.bench_function("de::bus_route.json", |b| b.iter(|| de::bus_routes()));
c.bench_function("de::bus_services.json", |b| b.iter(|| de::bus_service()));
c.bench_function("de::bus_stops.json", |b| b.iter(|| de::bus_stops()));
c.bench_function("de::carpark_avail.json", |b| b.iter(|| de::carpark_avail()));
c.bench_function("de::erp_rates.json", |b| b.iter(|| de::erp_rates()));
c.bench_function("de::est_travel_time.json", |b| b.iter(|| de::est_travel_time()));
c.bench_function("de::faulty_traffic_lights.json", |b| b.iter(|| de::faulty_traffic_lights()));
c.bench_function("de::passenger_vol_bus_stops.json", |b| b.iter(|| de::passenger_vol_bus_stops()));
c.bench_function("de::passenger_od_bus_stops.json", |b| b.iter(|| de::passenger_vol_od_bus_stops()));
c.bench_function("de::passenger_vol_od_train.json", |b| b.iter(|| de::passenger_vol_od_train()));
c.bench_function("de::passenger_vol_train.json", |b| b.iter(|| de::passenger_vol_train()));
c.bench_function("de::taxi_avail.json", |b| b.iter(|| de::taxi_avail()));
c.bench_function("de::taxi_stands.json", |b| b.iter(|| de::taxi_stands()));
c.bench_function("de::train_service_alert.json", |b| b.iter(|| de::train_service_alert()));
c.bench_function("de::crowd_density_rt.json", |b| b.iter(|| de::crowd_density_rt()));
c.bench_function("de::crowd_density_forecast.json", |b| b.iter(|| de::crowd_density_forecast()));

let bike_parking = de::bike_parking();
let bus_arrival = de::bus_arrival();
let bus_routes = de::bus_routes();
let bus_service = de::bus_service();
let bus_stops = de::bus_stops();
let carpark_avail = de::carpark_avail();
let erp_rates = de::erp_rates();
let est_travel_time = de::est_travel_time();
let faulty_traffic_lights = de::faulty_traffic_lights();
let passenger_vol_bus_stops = de::passenger_vol_bus_stops();
let passenger_vol_od_bus_stops = de::passenger_vol_od_bus_stops();
let passenger_vol_train = de::passenger_vol_train();
let passenger_vol_od_train = de::passenger_vol_od_train();
let taxi_avail = de::taxi_avail();
let taxi_stands = de::taxi_stands();
let train_service_alert = de::train_service_alert();
let crowd_density_rt = de::crowd_density_rt();
let crowd_density_forecast = de::crowd_density_forecast();

c.bench_function("ser::bike_parking.json", |b| b.iter(|| serde_json::to_string(black_box(&bike_parking))));
c.bench_function("ser::bus_arrival.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_arrival))));
c.bench_function("ser::bus_route.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_routes))));
c.bench_function("ser::bus_services.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_service))));
c.bench_function("ser::bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_stops))));
c.bench_function("ser::carpark_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&carpark_avail))));
c.bench_function("ser::erp_rates.json", |b| b.iter(|| serde_json::to_string(black_box(&erp_rates))));
c.bench_function("ser::est_travel_time.json", |b| b.iter(|| serde_json::to_string(black_box(&est_travel_time))));
c.bench_function("ser::faulty_traffic_lights.json", |b| b.iter(|| serde_json::to_string(black_box(&faulty_traffic_lights))));
c.bench_function("ser::passenger_vol_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_bus_stops))));
c.bench_function("ser::passenger_od_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_bus_stops))));
c.bench_function("ser::passenger_vol_od_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_train))));
c.bench_function("ser::passenger_vol_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_train))));
c.bench_function("ser::taxi_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_avail))));
c.bench_function("ser::taxi_stands.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_stands))));
c.bench_function("ser::train_service_alert.json", |b| b.iter(|| serde_json::to_string(black_box(&train_service_alert))));
c.bench_function("ser::crowd_density_rt.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_rt))));
c.bench_function("ser::crowd_density_forecast.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_forecast))));
let sample_data = NextBusRaw {
origin_code: 77009,
dest_code: 77009,
est_arrival: datetime!(2023-04-06 14:47:57 +8),
lat: 1.314452,
long: 103.910009,
visit_no: 1,
load: BusLoad::SeatsAvailable,
feature: BusFeature::WheelChairAccessible,
bus_type: BusType::SingleDecker,
};

c.bench_function("transmute_nextbus", |b| b.iter(|| de::transmute_nextbus(black_box(sample_data.clone()))));
c.bench_function("into_nextbus", |b| b.iter(|| NextBus::from(black_box(sample_data.clone()))));
c.bench_function("de::bike_parking.json", |b| b.iter(|| de::bike_parking()));
c.bench_function("de::bus_arrival.json", |b| b.iter(|| de::bus_arrival()));
c.bench_function("de::bus_route.json", |b| b.iter(|| de::bus_routes()));
c.bench_function("de::bus_services.json", |b| b.iter(|| de::bus_service()));
c.bench_function("de::bus_stops.json", |b| b.iter(|| de::bus_stops()));
c.bench_function("de::carpark_avail.json", |b| b.iter(|| de::carpark_avail()));
c.bench_function("de::erp_rates.json", |b| b.iter(|| de::erp_rates()));
c.bench_function("de::est_travel_time.json", |b| b.iter(|| de::est_travel_time()));
c.bench_function("de::faulty_traffic_lights.json", |b| b.iter(|| de::faulty_traffic_lights()));
c.bench_function("de::passenger_vol_bus_stops.json", |b| b.iter(|| de::passenger_vol_bus_stops()));
c.bench_function("de::passenger_od_bus_stops.json", |b| b.iter(|| de::passenger_vol_od_bus_stops()));
c.bench_function("de::passenger_vol_od_train.json", |b| b.iter(|| de::passenger_vol_od_train()));
c.bench_function("de::passenger_vol_train.json", |b| b.iter(|| de::passenger_vol_train()));
c.bench_function("de::taxi_avail.json", |b| b.iter(|| de::taxi_avail()));
c.bench_function("de::taxi_stands.json", |b| b.iter(|| de::taxi_stands()));
c.bench_function("de::train_service_alert.json", |b| b.iter(|| de::train_service_alert()));
c.bench_function("de::crowd_density_rt.json", |b| b.iter(|| de::crowd_density_rt()));
c.bench_function("de::crowd_density_forecast.json", |b| b.iter(|| de::crowd_density_forecast()));

let bike_parking = de::bike_parking();
let bus_arrival = de::bus_arrival();
let bus_routes = de::bus_routes();
let bus_service = de::bus_service();
let bus_stops = de::bus_stops();
let carpark_avail = de::carpark_avail();
let erp_rates = de::erp_rates();
let est_travel_time = de::est_travel_time();
let faulty_traffic_lights = de::faulty_traffic_lights();
let passenger_vol_bus_stops = de::passenger_vol_bus_stops();
let passenger_vol_od_bus_stops = de::passenger_vol_od_bus_stops();
let passenger_vol_train = de::passenger_vol_train();
let passenger_vol_od_train = de::passenger_vol_od_train();
let taxi_avail = de::taxi_avail();
let taxi_stands = de::taxi_stands();
let train_service_alert = de::train_service_alert();
let crowd_density_rt = de::crowd_density_rt();
let crowd_density_forecast = de::crowd_density_forecast();

c.bench_function("ser::bike_parking.json", |b| b.iter(|| serde_json::to_string(black_box(&bike_parking))));
c.bench_function("ser::bus_arrival.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_arrival))));
c.bench_function("ser::bus_route.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_routes))));
c.bench_function("ser::bus_services.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_service))));
c.bench_function("ser::bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_stops))));
c.bench_function("ser::carpark_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&carpark_avail))));
c.bench_function("ser::erp_rates.json", |b| b.iter(|| serde_json::to_string(black_box(&erp_rates))));
c.bench_function("ser::est_travel_time.json", |b| b.iter(|| serde_json::to_string(black_box(&est_travel_time))));
c.bench_function("ser::faulty_traffic_lights.json", |b| b.iter(|| serde_json::to_string(black_box(&faulty_traffic_lights))));
c.bench_function("ser::passenger_vol_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_bus_stops))));
c.bench_function("ser::passenger_od_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_bus_stops))));
c.bench_function("ser::passenger_vol_od_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_train))));
c.bench_function("ser::passenger_vol_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_train))));
c.bench_function("ser::taxi_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_avail))));
c.bench_function("ser::taxi_stands.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_stands))));
c.bench_function("ser::train_service_alert.json", |b| b.iter(|| serde_json::to_string(black_box(&train_service_alert))));
c.bench_function("ser::crowd_density_rt.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_rt))));
c.bench_function("ser::crowd_density_forecast.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_forecast))));
}

criterion_group!(benches, criterion_benchmark);
Expand Down
Loading

0 comments on commit 2a01860

Please sign in to comment.