Initial commit
This commit is contained in:
182
.gitignore
vendored
Normal file
182
.gitignore
vendored
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/rust,jetbrains+all,macos,linux,windows
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=rust,jetbrains+all,macos,linux,windows
|
||||||
|
|
||||||
|
### JetBrains+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### JetBrains+all Patch ###
|
||||||
|
# Ignore everything but code style settings and run configurations
|
||||||
|
# that are supposed to be shared within teams.
|
||||||
|
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
!.idea/codeStyles
|
||||||
|
!.idea/runConfigurations
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### macOS Patch ###
|
||||||
|
# iCloud generated files
|
||||||
|
*.icloud
|
||||||
|
|
||||||
|
### Rust ###
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/rust,jetbrains+all,macos,linux,windows
|
||||||
28
Cargo.toml
Normal file
28
Cargo.toml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
[package]
|
||||||
|
name = "ecs_dt_benchmark"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "ECS Digital Twin runtime benchmark — TRANSIT lab / UQAC"
|
||||||
|
|
||||||
|
# No default features: we do NOT want a window, renderer, audio, or anything
|
||||||
|
# that requires a display. Pure headless ECS.
|
||||||
|
[dependencies]
|
||||||
|
bevy_ecs = { version = "0.18", default-features = false }
|
||||||
|
rand = { version = "0.8", features = ["small_rng"] }
|
||||||
|
rand_chacha = "0.3"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = 3
|
||||||
|
lto = "thin" # thin LTO: good balance between link time and perf
|
||||||
|
codegen-units = 1 # single CGU for max inlining across crate boundary
|
||||||
|
panic = "abort" # smaller binary, no unwinding overhead
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
inherits = "release"
|
||||||
|
debug = true # keep symbols so perf/flamegraph works on RPi
|
||||||
|
|
||||||
|
# On aarch64 (RPi 5 Cortex-A76) the compiler can use NEON by default.
|
||||||
|
# Uncomment the line below for the RPi 5 build to also enable SVE if your
|
||||||
|
# toolchain supports it (most don't yet for aarch64-unknown-linux-gnu):
|
||||||
|
# [target.aarch64-unknown-linux-gnu]
|
||||||
|
# rustflags = ["-C", "target-cpu=cortex-a76"]
|
||||||
35
results/csv/entities_10000.txt
Normal file
35
results/csv/entities_10000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=10000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=7000 EventAsset=2000 ActuatorAsset=1000 total=10000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 10000 (sensor_active= 8817, alerts= 0, act= 1000) | faults= 183 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 94.0 sim= 20.0 export= 11.0 diag= 0.0 µs | exported=0.08 MB acks=1000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 10000 (sensor_active= 4488, alerts= 23, act= 1000) | faults= 92482 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.8 sim= 6.0 export= 3.9 diag= 0.0 µs | exported=40.70 MB acks=501000
|
||||||
|
tick= 2000 | entities= 10000 (sensor_active= 4425, alerts= 23, act= 1000) | faults=182979 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.6 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=121.92 MB acks=1501000
|
||||||
|
tick= 3000 | entities= 10000 (sensor_active= 4507, alerts= 27, act= 1000) | faults=273085 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.2 µs | ingest= 48.6 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=203.15 MB acks=2501000
|
||||||
|
tick= 4000 | entities= 10000 (sensor_active= 4502, alerts= 15, act= 1000) | faults=363376 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.8 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=284.37 MB acks=3501000
|
||||||
|
tick= 5000 | entities= 10000 (sensor_active= 4527, alerts= 24, act= 1000) | faults=453183 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.8 µs | ingest= 48.9 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=365.59 MB acks=4501000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 0.531 s
|
||||||
|
Sustained tick rate: 9424.5 Hz
|
||||||
|
Per-tick mean (wall): 10.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 48.8
|
||||||
|
SimulationSystem: 5.9
|
||||||
|
ExportSystem: 3.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 498016
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 406.11 MB
|
||||||
|
Acks processed: 5000000
|
||||||
|
Alerts seen: 104943
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/csv/entities_100000.txt
Normal file
35
results/csv/entities_100000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=100000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=70000 EventAsset=20000 ActuatorAsset=10000 total=100000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 100000 (sensor_active= 88228, alerts= 0, act=10000) | faults= 1772 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 202.0 sim= 75.0 export= 41.0 diag= 0.0 µs | exported=0.81 MB acks=10000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 100000 (sensor_active= 45396, alerts= 218, act=10000) | faults=924085 lockouts= 0 | rss= 0.0 MB | tick_mean= 1101.8 µs | ingest= 500.9 sim= 61.2 export= 40.6 diag= 0.0 µs | exported=406.92 MB acks=5010000
|
||||||
|
tick= 2000 | entities= 100000 (sensor_active= 44998, alerts= 212, act=10000) | faults=1823730 lockouts= 0 | rss= 0.0 MB | tick_mean= 1105.1 µs | ingest= 501.0 sim= 61.1 export= 40.6 diag= 0.0 µs | exported=1219.14 MB acks=15010000
|
||||||
|
tick= 3000 | entities= 100000 (sensor_active= 45132, alerts= 187, act=10000) | faults=2723608 lockouts= 0 | rss= 0.0 MB | tick_mean= 1114.2 µs | ingest= 504.7 sim= 61.5 export= 40.8 diag= 0.0 µs | exported=2031.31 MB acks=25010000
|
||||||
|
tick= 4000 | entities= 100000 (sensor_active= 45039, alerts= 226, act=10000) | faults=3624295 lockouts= 0 | rss= 0.0 MB | tick_mean= 1112.0 µs | ingest= 505.0 sim= 61.7 export= 40.9 diag= 0.0 µs | exported=2843.48 MB acks=35010000
|
||||||
|
tick= 5000 | entities= 100000 (sensor_active= 45069, alerts= 206, act=10000) | faults=4525217 lockouts= 0 | rss= 0.0 MB | tick_mean= 1112.9 µs | ingest= 504.7 sim= 61.8 export= 40.9 diag= 0.0 µs | exported=3655.68 MB acks=45010000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 5.555 s
|
||||||
|
Sustained tick rate: 900.2 Hz
|
||||||
|
Per-tick mean (wall): 111.2 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 504.2
|
||||||
|
SimulationSystem: 61.8
|
||||||
|
ExportSystem: 41.0
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 4974449
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 4060.96 MB
|
||||||
|
Acks processed: 50000000
|
||||||
|
Alerts seen: 1028407
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/csv/entities_150000.txt
Normal file
35
results/csv/entities_150000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=150000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=105000 EventAsset=30000 ActuatorAsset=15000 total=150000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 150000 (sensor_active=132379, alerts= 0, act=15000) | faults= 2621 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 306.0 sim= 113.0 export= 61.0 diag= 0.0 µs | exported=1.22 MB acks=15000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 150000 (sensor_active= 67721, alerts= 326, act=15000) | faults=1385323 lockouts= 0 | rss= 0.0 MB | tick_mean= 1717.3 µs | ingest= 755.7 sim= 92.9 export= 61.8 diag= 0.0 µs | exported=610.34 MB acks=7515000
|
||||||
|
tick= 2000 | entities= 150000 (sensor_active= 67238, alerts= 278, act=15000) | faults=2736064 lockouts= 0 | rss= 0.0 MB | tick_mean= 1721.7 µs | ingest= 755.2 sim= 93.0 export= 61.8 diag= 0.0 µs | exported=1828.59 MB acks=22515000
|
||||||
|
tick= 3000 | entities= 150000 (sensor_active= 67728, alerts= 330, act=15000) | faults=4087020 lockouts= 0 | rss= 0.0 MB | tick_mean= 1719.6 µs | ingest= 753.9 sim= 93.0 export= 61.5 diag= 0.0 µs | exported=3046.89 MB acks=37515000
|
||||||
|
tick= 4000 | entities= 150000 (sensor_active= 67533, alerts= 323, act=15000) | faults=5437256 lockouts= 0 | rss= 0.0 MB | tick_mean= 1715.2 µs | ingest= 753.4 sim= 92.6 export= 61.5 diag= 0.0 µs | exported=4265.19 MB acks=52515000
|
||||||
|
tick= 5000 | entities= 150000 (sensor_active= 67700, alerts= 334, act=15000) | faults=6786973 lockouts= 0 | rss= 0.0 MB | tick_mean= 1726.7 µs | ingest= 755.2 sim= 93.0 export= 61.8 diag= 0.0 µs | exported=5483.51 MB acks=67515000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 8.604 s
|
||||||
|
Sustained tick rate: 581.1 Hz
|
||||||
|
Per-tick mean (wall): 171.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 754.2
|
||||||
|
SimulationSystem: 92.5
|
||||||
|
ExportSystem: 61.7
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 7460636
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 6091.45 MB
|
||||||
|
Acks processed: 75000000
|
||||||
|
Alerts seen: 1543036
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/csv/entities_200000.txt
Normal file
35
results/csv/entities_200000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=200000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=140000 EventAsset=40000 ActuatorAsset=20000 total=200000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 200000 (sensor_active=176493, alerts= 0, act=20000) | faults= 3507 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 415.0 sim= 160.0 export= 84.0 diag= 0.0 µs | exported=1.62 MB acks=20000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 200000 (sensor_active= 90145, alerts= 390, act=20000) | faults=1847083 lockouts= 0 | rss= 0.0 MB | tick_mean= 2413.0 µs | ingest=1003.2 sim= 125.4 export= 83.3 diag= 0.0 µs | exported=813.81 MB acks=10020000
|
||||||
|
tick= 2000 | entities= 200000 (sensor_active= 90392, alerts= 385, act=20000) | faults=3647521 lockouts= 0 | rss= 0.0 MB | tick_mean= 2409.9 µs | ingest=1003.2 sim= 125.4 export= 83.1 diag= 0.0 µs | exported=2438.20 MB acks=30020000
|
||||||
|
tick= 3000 | entities= 200000 (sensor_active= 90372, alerts= 391, act=20000) | faults=5447700 lockouts= 0 | rss= 0.0 MB | tick_mean= 2380.4 µs | ingest= 998.3 sim= 124.5 export= 82.8 diag= 0.0 µs | exported=4062.57 MB acks=50020000
|
||||||
|
tick= 4000 | entities= 200000 (sensor_active= 89452, alerts= 451, act=20000) | faults=7247668 lockouts= 0 | rss= 0.0 MB | tick_mean= 2380.1 µs | ingest= 998.7 sim= 124.7 export= 82.5 diag= 0.0 µs | exported=5686.95 MB acks=70020000
|
||||||
|
tick= 5000 | entities= 200000 (sensor_active= 89914, alerts= 424, act=20000) | faults=9047286 lockouts= 0 | rss= 0.0 MB | tick_mean= 2386.7 µs | ingest= 999.0 sim= 124.7 export= 82.8 diag= 0.0 µs | exported=7311.35 MB acks=90020000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 11.966 s
|
||||||
|
Sustained tick rate: 417.9 Hz
|
||||||
|
Per-tick mean (wall): 239.4 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 1001.3
|
||||||
|
SimulationSystem: 125.2
|
||||||
|
ExportSystem: 83.1
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 9946420
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 8121.92 MB
|
||||||
|
Acks processed: 100000000
|
||||||
|
Alerts seen: 2056796
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/csv/entities_25000.txt
Normal file
35
results/csv/entities_25000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=25000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=17500 EventAsset=5000 ActuatorAsset=2500 total=25000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 25000 (sensor_active= 22049, alerts= 0, act= 2500) | faults= 451 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 67.0 sim= 19.0 export= 11.0 diag= 0.0 µs | exported=0.20 MB acks=2500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 25000 (sensor_active= 11440, alerts= 49, act= 2500) | faults=231419 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.4 µs | ingest= 125.7 sim= 15.0 export= 9.9 diag= 0.0 µs | exported=101.74 MB acks=1252500
|
||||||
|
tick= 2000 | entities= 25000 (sensor_active= 11301, alerts= 43, act= 2500) | faults=456552 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.6 µs | ingest= 125.8 sim= 15.1 export= 9.9 diag= 0.0 µs | exported=304.78 MB acks=3752500
|
||||||
|
tick= 3000 | entities= 25000 (sensor_active= 11421, alerts= 58, act= 2500) | faults=681247 lockouts= 0 | rss= 0.0 MB | tick_mean= 276.1 µs | ingest= 126.4 sim= 15.1 export= 10.0 diag= 0.0 µs | exported=507.82 MB acks=6252500
|
||||||
|
tick= 4000 | entities= 25000 (sensor_active= 11157, alerts= 48, act= 2500) | faults=906865 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.5 µs | ingest= 125.7 sim= 15.1 export= 9.9 diag= 0.0 µs | exported=710.88 MB acks=8752500
|
||||||
|
tick= 5000 | entities= 25000 (sensor_active= 11216, alerts= 49, act= 2500) | faults=1131163 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.9 µs | ingest= 125.9 sim= 15.0 export= 9.9 diag= 0.0 µs | exported=913.91 MB acks=11252500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 1.378 s
|
||||||
|
Sustained tick rate: 3629.5 Hz
|
||||||
|
Per-tick mean (wall): 27.5 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 125.6
|
||||||
|
SimulationSystem: 15.0
|
||||||
|
ExportSystem: 9.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 1243639
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 1015.22 MB
|
||||||
|
Acks processed: 12500000
|
||||||
|
Alerts seen: 254654
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/csv/entities_50000.txt
Normal file
35
results/csv/entities_50000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=50000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=35000 EventAsset=10000 ActuatorAsset=5000 total=50000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 50000 (sensor_active= 44082, alerts= 0, act= 5000) | faults= 918 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 104.0 sim= 34.0 export= 18.0 diag= 0.0 µs | exported=0.41 MB acks=5000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 50000 (sensor_active= 22364, alerts= 118, act= 5000) | faults=462345 lockouts= 0 | rss= 0.0 MB | tick_mean= 548.8 µs | ingest= 254.6 sim= 30.7 export= 20.0 diag= 0.0 µs | exported=203.46 MB acks=2505000
|
||||||
|
tick= 2000 | entities= 50000 (sensor_active= 22510, alerts= 97, act= 5000) | faults=912440 lockouts= 0 | rss= 0.0 MB | tick_mean= 546.7 µs | ingest= 253.0 sim= 30.3 export= 19.9 diag= 0.0 µs | exported=609.56 MB acks=7505000
|
||||||
|
tick= 3000 | entities= 50000 (sensor_active= 22512, alerts= 90, act= 5000) | faults=1361728 lockouts= 0 | rss= 0.0 MB | tick_mean= 549.3 µs | ingest= 254.3 sim= 30.6 export= 20.1 diag= 0.0 µs | exported=1015.66 MB acks=12505000
|
||||||
|
tick= 4000 | entities= 50000 (sensor_active= 22519, alerts= 98, act= 5000) | faults=1812084 lockouts= 0 | rss= 0.0 MB | tick_mean= 549.2 µs | ingest= 254.1 sim= 30.5 export= 20.0 diag= 0.0 µs | exported=1421.74 MB acks=17505000
|
||||||
|
tick= 5000 | entities= 50000 (sensor_active= 22355, alerts= 101, act= 5000) | faults=2261407 lockouts= 0 | rss= 0.0 MB | tick_mean= 545.8 µs | ingest= 252.6 sim= 30.4 export= 19.9 diag= 0.0 µs | exported=1827.82 MB acks=22505000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 2.743 s
|
||||||
|
Sustained tick rate: 1822.8 Hz
|
||||||
|
Per-tick mean (wall): 54.9 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 254.0
|
||||||
|
SimulationSystem: 30.5
|
||||||
|
ExportSystem: 19.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 2486121
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 2030.46 MB
|
||||||
|
Acks processed: 25000000
|
||||||
|
Alerts seen: 511654
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/csv/entities_75000.txt
Normal file
35
results/csv/entities_75000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=75000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=52500 EventAsset=15000 ActuatorAsset=7500 total=75000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 75000 (sensor_active= 66146, alerts= 0, act= 7500) | faults= 1354 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 188.0 sim= 62.0 export= 32.0 diag= 0.0 µs | exported=0.61 MB acks=7500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 75000 (sensor_active= 33877, alerts= 133, act= 7500) | faults=693165 lockouts= 0 | rss= 0.0 MB | tick_mean= 818.6 µs | ingest= 378.8 sim= 45.8 export= 30.8 diag= 0.0 µs | exported=305.18 MB acks=3757500
|
||||||
|
tick= 2000 | entities= 75000 (sensor_active= 33696, alerts= 163, act= 7500) | faults=1367793 lockouts= 0 | rss= 0.0 MB | tick_mean= 817.4 µs | ingest= 377.4 sim= 45.7 export= 30.6 diag= 0.0 µs | exported=914.34 MB acks=11257500
|
||||||
|
tick= 3000 | entities= 75000 (sensor_active= 33889, alerts= 145, act= 7500) | faults=2042643 lockouts= 0 | rss= 0.0 MB | tick_mean= 817.6 µs | ingest= 377.7 sim= 45.8 export= 30.6 diag= 0.0 µs | exported=1523.51 MB acks=18757500
|
||||||
|
tick= 4000 | entities= 75000 (sensor_active= 33657, alerts= 169, act= 7500) | faults=2717674 lockouts= 0 | rss= 0.0 MB | tick_mean= 815.9 µs | ingest= 376.7 sim= 45.6 export= 30.5 diag= 0.0 µs | exported=2132.66 MB acks=26257500
|
||||||
|
tick= 5000 | entities= 75000 (sensor_active= 33573, alerts= 162, act= 7500) | faults=3393495 lockouts= 0 | rss= 0.0 MB | tick_mean= 820.1 µs | ingest= 377.7 sim= 45.7 export= 30.7 diag= 0.0 µs | exported=2741.78 MB acks=33757500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 4.094 s
|
||||||
|
Sustained tick rate: 1221.3 Hz
|
||||||
|
Per-tick mean (wall): 82.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 377.6
|
||||||
|
SimulationSystem: 45.7
|
||||||
|
ExportSystem: 30.6
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 3730093
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 3045.72 MB
|
||||||
|
Acks processed: 37500000
|
||||||
|
Alerts seen: 771425
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
8
results/final_table.csv
Normal file
8
results/final_table.csv
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
entities,ticks,wall_s,hz,per_tick_us,ingest_us,sim_us,export_us,diag_us,sensor_faults,actuator_lockouts,exported_mb,acks,alerts,rss_mb
|
||||||
|
10000,5000,,,,48.8,5.9,3.9,0.0,498016,0,,5000000,104943,
|
||||||
|
25000,5000,,,,125.6,15.0,9.9,0.0,1243639,0,,12500000,254654,
|
||||||
|
50000,5000,,,,254.0,30.5,19.9,0.0,2486121,0,,25000000,511654,
|
||||||
|
75000,5000,,,,377.6,45.7,30.6,0.0,3730093,0,,37500000,771425,
|
||||||
|
100000,5000,,,,504.2,61.8,41.0,0.0,4974449,0,,50000000,1028407,
|
||||||
|
150000,5000,,,,754.2,92.5,61.7,0.0,7460636,0,,75000000,1543036,
|
||||||
|
200000,5000,,,,1001.3,125.2,83.1,0.0,9946420,0,,100000000,2056796,
|
||||||
|
35
results/raw_10000.txt
Normal file
35
results/raw_10000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=10000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=7000 EventAsset=2000 ActuatorAsset=1000 total=10000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 10000 (sensor_active= 8817, alerts= 0, act= 1000) | faults= 183 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 94.0 sim= 20.0 export= 11.0 diag= 0.0 µs | exported=0.08 MB acks=1000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 10000 (sensor_active= 4488, alerts= 23, act= 1000) | faults= 92482 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.8 sim= 6.0 export= 3.9 diag= 0.0 µs | exported=40.70 MB acks=501000
|
||||||
|
tick= 2000 | entities= 10000 (sensor_active= 4425, alerts= 23, act= 1000) | faults=182979 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.6 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=121.92 MB acks=1501000
|
||||||
|
tick= 3000 | entities= 10000 (sensor_active= 4507, alerts= 27, act= 1000) | faults=273085 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.2 µs | ingest= 48.6 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=203.15 MB acks=2501000
|
||||||
|
tick= 4000 | entities= 10000 (sensor_active= 4502, alerts= 15, act= 1000) | faults=363376 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.8 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=284.37 MB acks=3501000
|
||||||
|
tick= 5000 | entities= 10000 (sensor_active= 4527, alerts= 24, act= 1000) | faults=453183 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.8 µs | ingest= 48.9 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=365.59 MB acks=4501000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 0.531 s
|
||||||
|
Sustained tick rate: 9424.5 Hz
|
||||||
|
Per-tick mean (wall): 10.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 48.8
|
||||||
|
SimulationSystem: 5.9
|
||||||
|
ExportSystem: 3.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 498016
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 406.11 MB
|
||||||
|
Acks processed: 5000000
|
||||||
|
Alerts seen: 104943
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/raw_100000.txt
Normal file
35
results/raw_100000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=100000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=70000 EventAsset=20000 ActuatorAsset=10000 total=100000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 100000 (sensor_active= 88228, alerts= 0, act=10000) | faults= 1772 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 202.0 sim= 75.0 export= 41.0 diag= 0.0 µs | exported=0.81 MB acks=10000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 100000 (sensor_active= 45396, alerts= 218, act=10000) | faults=924085 lockouts= 0 | rss= 0.0 MB | tick_mean= 1101.8 µs | ingest= 500.9 sim= 61.2 export= 40.6 diag= 0.0 µs | exported=406.92 MB acks=5010000
|
||||||
|
tick= 2000 | entities= 100000 (sensor_active= 44998, alerts= 212, act=10000) | faults=1823730 lockouts= 0 | rss= 0.0 MB | tick_mean= 1105.1 µs | ingest= 501.0 sim= 61.1 export= 40.6 diag= 0.0 µs | exported=1219.14 MB acks=15010000
|
||||||
|
tick= 3000 | entities= 100000 (sensor_active= 45132, alerts= 187, act=10000) | faults=2723608 lockouts= 0 | rss= 0.0 MB | tick_mean= 1114.2 µs | ingest= 504.7 sim= 61.5 export= 40.8 diag= 0.0 µs | exported=2031.31 MB acks=25010000
|
||||||
|
tick= 4000 | entities= 100000 (sensor_active= 45039, alerts= 226, act=10000) | faults=3624295 lockouts= 0 | rss= 0.0 MB | tick_mean= 1112.0 µs | ingest= 505.0 sim= 61.7 export= 40.9 diag= 0.0 µs | exported=2843.48 MB acks=35010000
|
||||||
|
tick= 5000 | entities= 100000 (sensor_active= 45069, alerts= 206, act=10000) | faults=4525217 lockouts= 0 | rss= 0.0 MB | tick_mean= 1112.9 µs | ingest= 504.7 sim= 61.8 export= 40.9 diag= 0.0 µs | exported=3655.68 MB acks=45010000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 5.555 s
|
||||||
|
Sustained tick rate: 900.2 Hz
|
||||||
|
Per-tick mean (wall): 111.2 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 504.2
|
||||||
|
SimulationSystem: 61.8
|
||||||
|
ExportSystem: 41.0
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 4974449
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 4060.96 MB
|
||||||
|
Acks processed: 50000000
|
||||||
|
Alerts seen: 1028407
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/raw_150000.txt
Normal file
35
results/raw_150000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=150000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=105000 EventAsset=30000 ActuatorAsset=15000 total=150000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 150000 (sensor_active=132379, alerts= 0, act=15000) | faults= 2621 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 306.0 sim= 113.0 export= 61.0 diag= 0.0 µs | exported=1.22 MB acks=15000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 150000 (sensor_active= 67721, alerts= 326, act=15000) | faults=1385323 lockouts= 0 | rss= 0.0 MB | tick_mean= 1717.3 µs | ingest= 755.7 sim= 92.9 export= 61.8 diag= 0.0 µs | exported=610.34 MB acks=7515000
|
||||||
|
tick= 2000 | entities= 150000 (sensor_active= 67238, alerts= 278, act=15000) | faults=2736064 lockouts= 0 | rss= 0.0 MB | tick_mean= 1721.7 µs | ingest= 755.2 sim= 93.0 export= 61.8 diag= 0.0 µs | exported=1828.59 MB acks=22515000
|
||||||
|
tick= 3000 | entities= 150000 (sensor_active= 67728, alerts= 330, act=15000) | faults=4087020 lockouts= 0 | rss= 0.0 MB | tick_mean= 1719.6 µs | ingest= 753.9 sim= 93.0 export= 61.5 diag= 0.0 µs | exported=3046.89 MB acks=37515000
|
||||||
|
tick= 4000 | entities= 150000 (sensor_active= 67533, alerts= 323, act=15000) | faults=5437256 lockouts= 0 | rss= 0.0 MB | tick_mean= 1715.2 µs | ingest= 753.4 sim= 92.6 export= 61.5 diag= 0.0 µs | exported=4265.19 MB acks=52515000
|
||||||
|
tick= 5000 | entities= 150000 (sensor_active= 67700, alerts= 334, act=15000) | faults=6786973 lockouts= 0 | rss= 0.0 MB | tick_mean= 1726.7 µs | ingest= 755.2 sim= 93.0 export= 61.8 diag= 0.0 µs | exported=5483.51 MB acks=67515000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 8.604 s
|
||||||
|
Sustained tick rate: 581.1 Hz
|
||||||
|
Per-tick mean (wall): 171.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 754.2
|
||||||
|
SimulationSystem: 92.5
|
||||||
|
ExportSystem: 61.7
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 7460636
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 6091.45 MB
|
||||||
|
Acks processed: 75000000
|
||||||
|
Alerts seen: 1543036
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/raw_200000.txt
Normal file
35
results/raw_200000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=200000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=140000 EventAsset=40000 ActuatorAsset=20000 total=200000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 200000 (sensor_active=176493, alerts= 0, act=20000) | faults= 3507 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 415.0 sim= 160.0 export= 84.0 diag= 0.0 µs | exported=1.62 MB acks=20000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 200000 (sensor_active= 90145, alerts= 390, act=20000) | faults=1847083 lockouts= 0 | rss= 0.0 MB | tick_mean= 2413.0 µs | ingest=1003.2 sim= 125.4 export= 83.3 diag= 0.0 µs | exported=813.81 MB acks=10020000
|
||||||
|
tick= 2000 | entities= 200000 (sensor_active= 90392, alerts= 385, act=20000) | faults=3647521 lockouts= 0 | rss= 0.0 MB | tick_mean= 2409.9 µs | ingest=1003.2 sim= 125.4 export= 83.1 diag= 0.0 µs | exported=2438.20 MB acks=30020000
|
||||||
|
tick= 3000 | entities= 200000 (sensor_active= 90372, alerts= 391, act=20000) | faults=5447700 lockouts= 0 | rss= 0.0 MB | tick_mean= 2380.4 µs | ingest= 998.3 sim= 124.5 export= 82.8 diag= 0.0 µs | exported=4062.57 MB acks=50020000
|
||||||
|
tick= 4000 | entities= 200000 (sensor_active= 89452, alerts= 451, act=20000) | faults=7247668 lockouts= 0 | rss= 0.0 MB | tick_mean= 2380.1 µs | ingest= 998.7 sim= 124.7 export= 82.5 diag= 0.0 µs | exported=5686.95 MB acks=70020000
|
||||||
|
tick= 5000 | entities= 200000 (sensor_active= 89914, alerts= 424, act=20000) | faults=9047286 lockouts= 0 | rss= 0.0 MB | tick_mean= 2386.7 µs | ingest= 999.0 sim= 124.7 export= 82.8 diag= 0.0 µs | exported=7311.35 MB acks=90020000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 11.966 s
|
||||||
|
Sustained tick rate: 417.9 Hz
|
||||||
|
Per-tick mean (wall): 239.4 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 1001.3
|
||||||
|
SimulationSystem: 125.2
|
||||||
|
ExportSystem: 83.1
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 9946420
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 8121.92 MB
|
||||||
|
Acks processed: 100000000
|
||||||
|
Alerts seen: 2056796
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/raw_25000.txt
Normal file
35
results/raw_25000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=25000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=17500 EventAsset=5000 ActuatorAsset=2500 total=25000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 25000 (sensor_active= 22049, alerts= 0, act= 2500) | faults= 451 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 67.0 sim= 19.0 export= 11.0 diag= 0.0 µs | exported=0.20 MB acks=2500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 25000 (sensor_active= 11440, alerts= 49, act= 2500) | faults=231419 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.4 µs | ingest= 125.7 sim= 15.0 export= 9.9 diag= 0.0 µs | exported=101.74 MB acks=1252500
|
||||||
|
tick= 2000 | entities= 25000 (sensor_active= 11301, alerts= 43, act= 2500) | faults=456552 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.6 µs | ingest= 125.8 sim= 15.1 export= 9.9 diag= 0.0 µs | exported=304.78 MB acks=3752500
|
||||||
|
tick= 3000 | entities= 25000 (sensor_active= 11421, alerts= 58, act= 2500) | faults=681247 lockouts= 0 | rss= 0.0 MB | tick_mean= 276.1 µs | ingest= 126.4 sim= 15.1 export= 10.0 diag= 0.0 µs | exported=507.82 MB acks=6252500
|
||||||
|
tick= 4000 | entities= 25000 (sensor_active= 11157, alerts= 48, act= 2500) | faults=906865 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.5 µs | ingest= 125.7 sim= 15.1 export= 9.9 diag= 0.0 µs | exported=710.88 MB acks=8752500
|
||||||
|
tick= 5000 | entities= 25000 (sensor_active= 11216, alerts= 49, act= 2500) | faults=1131163 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.9 µs | ingest= 125.9 sim= 15.0 export= 9.9 diag= 0.0 µs | exported=913.91 MB acks=11252500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 1.378 s
|
||||||
|
Sustained tick rate: 3629.5 Hz
|
||||||
|
Per-tick mean (wall): 27.5 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 125.6
|
||||||
|
SimulationSystem: 15.0
|
||||||
|
ExportSystem: 9.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 1243639
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 1015.22 MB
|
||||||
|
Acks processed: 12500000
|
||||||
|
Alerts seen: 254654
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/raw_50000.txt
Normal file
35
results/raw_50000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=50000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=35000 EventAsset=10000 ActuatorAsset=5000 total=50000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 50000 (sensor_active= 44082, alerts= 0, act= 5000) | faults= 918 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 104.0 sim= 34.0 export= 18.0 diag= 0.0 µs | exported=0.41 MB acks=5000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 50000 (sensor_active= 22364, alerts= 118, act= 5000) | faults=462345 lockouts= 0 | rss= 0.0 MB | tick_mean= 548.8 µs | ingest= 254.6 sim= 30.7 export= 20.0 diag= 0.0 µs | exported=203.46 MB acks=2505000
|
||||||
|
tick= 2000 | entities= 50000 (sensor_active= 22510, alerts= 97, act= 5000) | faults=912440 lockouts= 0 | rss= 0.0 MB | tick_mean= 546.7 µs | ingest= 253.0 sim= 30.3 export= 19.9 diag= 0.0 µs | exported=609.56 MB acks=7505000
|
||||||
|
tick= 3000 | entities= 50000 (sensor_active= 22512, alerts= 90, act= 5000) | faults=1361728 lockouts= 0 | rss= 0.0 MB | tick_mean= 549.3 µs | ingest= 254.3 sim= 30.6 export= 20.1 diag= 0.0 µs | exported=1015.66 MB acks=12505000
|
||||||
|
tick= 4000 | entities= 50000 (sensor_active= 22519, alerts= 98, act= 5000) | faults=1812084 lockouts= 0 | rss= 0.0 MB | tick_mean= 549.2 µs | ingest= 254.1 sim= 30.5 export= 20.0 diag= 0.0 µs | exported=1421.74 MB acks=17505000
|
||||||
|
tick= 5000 | entities= 50000 (sensor_active= 22355, alerts= 101, act= 5000) | faults=2261407 lockouts= 0 | rss= 0.0 MB | tick_mean= 545.8 µs | ingest= 252.6 sim= 30.4 export= 19.9 diag= 0.0 µs | exported=1827.82 MB acks=22505000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 2.743 s
|
||||||
|
Sustained tick rate: 1822.8 Hz
|
||||||
|
Per-tick mean (wall): 54.9 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 254.0
|
||||||
|
SimulationSystem: 30.5
|
||||||
|
ExportSystem: 19.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 2486121
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 2030.46 MB
|
||||||
|
Acks processed: 25000000
|
||||||
|
Alerts seen: 511654
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results/raw_75000.txt
Normal file
35
results/raw_75000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=75000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=52500 EventAsset=15000 ActuatorAsset=7500 total=75000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 75000 (sensor_active= 66146, alerts= 0, act= 7500) | faults= 1354 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 188.0 sim= 62.0 export= 32.0 diag= 0.0 µs | exported=0.61 MB acks=7500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 75000 (sensor_active= 33877, alerts= 133, act= 7500) | faults=693165 lockouts= 0 | rss= 0.0 MB | tick_mean= 818.6 µs | ingest= 378.8 sim= 45.8 export= 30.8 diag= 0.0 µs | exported=305.18 MB acks=3757500
|
||||||
|
tick= 2000 | entities= 75000 (sensor_active= 33696, alerts= 163, act= 7500) | faults=1367793 lockouts= 0 | rss= 0.0 MB | tick_mean= 817.4 µs | ingest= 377.4 sim= 45.7 export= 30.6 diag= 0.0 µs | exported=914.34 MB acks=11257500
|
||||||
|
tick= 3000 | entities= 75000 (sensor_active= 33889, alerts= 145, act= 7500) | faults=2042643 lockouts= 0 | rss= 0.0 MB | tick_mean= 817.6 µs | ingest= 377.7 sim= 45.8 export= 30.6 diag= 0.0 µs | exported=1523.51 MB acks=18757500
|
||||||
|
tick= 4000 | entities= 75000 (sensor_active= 33657, alerts= 169, act= 7500) | faults=2717674 lockouts= 0 | rss= 0.0 MB | tick_mean= 815.9 µs | ingest= 376.7 sim= 45.6 export= 30.5 diag= 0.0 µs | exported=2132.66 MB acks=26257500
|
||||||
|
tick= 5000 | entities= 75000 (sensor_active= 33573, alerts= 162, act= 7500) | faults=3393495 lockouts= 0 | rss= 0.0 MB | tick_mean= 820.1 µs | ingest= 377.7 sim= 45.7 export= 30.7 diag= 0.0 µs | exported=2741.78 MB acks=33757500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 4.094 s
|
||||||
|
Sustained tick rate: 1221.3 Hz
|
||||||
|
Per-tick mean (wall): 82.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 377.6
|
||||||
|
SimulationSystem: 45.7
|
||||||
|
ExportSystem: 30.6
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 3730093
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 3045.72 MB
|
||||||
|
Acks processed: 37500000
|
||||||
|
Alerts seen: 771425
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
271
results/summary.txt
Normal file
271
results/summary.txt
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
ECS DT Benchmark Sweep — Mon Apr 20 21:17:09 UTC 2026
|
||||||
|
=== System Information ===
|
||||||
|
Date: 2026-04-20 21:17:09 UTC
|
||||||
|
OS: Darwin 25.4.0
|
||||||
|
Arch: arm64
|
||||||
|
Target CPU: apple-m1
|
||||||
|
Rust: rustc 1.94.0 (4a4ef493e 2026-03-02)
|
||||||
|
Cargo: cargo 1.94.0 (85eff7c80 2026-01-15)
|
||||||
|
|
||||||
|
Apple M4 Max
|
||||||
|
Memory: 128.0 GB
|
||||||
|
|
||||||
|
|
||||||
|
=== entities=10000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=10000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=7000 EventAsset=2000 ActuatorAsset=1000 total=10000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 10000 (sensor_active= 8817, alerts= 0, act= 1000) | faults= 183 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 94.0 sim= 20.0 export= 11.0 diag= 0.0 µs | exported=0.08 MB acks=1000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 10000 (sensor_active= 4488, alerts= 23, act= 1000) | faults= 92482 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.8 sim= 6.0 export= 3.9 diag= 0.0 µs | exported=40.70 MB acks=501000
|
||||||
|
tick= 2000 | entities= 10000 (sensor_active= 4425, alerts= 23, act= 1000) | faults=182979 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.6 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=121.92 MB acks=1501000
|
||||||
|
tick= 3000 | entities= 10000 (sensor_active= 4507, alerts= 27, act= 1000) | faults=273085 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.2 µs | ingest= 48.6 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=203.15 MB acks=2501000
|
||||||
|
tick= 4000 | entities= 10000 (sensor_active= 4502, alerts= 15, act= 1000) | faults=363376 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.6 µs | ingest= 48.8 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=284.37 MB acks=3501000
|
||||||
|
tick= 5000 | entities= 10000 (sensor_active= 4527, alerts= 24, act= 1000) | faults=453183 lockouts= 0 | rss= 0.0 MB | tick_mean= 105.8 µs | ingest= 48.9 sim= 5.9 export= 3.9 diag= 0.0 µs | exported=365.59 MB acks=4501000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 0.531 s
|
||||||
|
Sustained tick rate: 9424.5 Hz
|
||||||
|
Per-tick mean (wall): 10.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 48.8
|
||||||
|
SimulationSystem: 5.9
|
||||||
|
ExportSystem: 3.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 498016
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 406.11 MB
|
||||||
|
Acks processed: 5000000
|
||||||
|
Alerts seen: 104943
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=25000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=25000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=17500 EventAsset=5000 ActuatorAsset=2500 total=25000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 25000 (sensor_active= 22049, alerts= 0, act= 2500) | faults= 451 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 67.0 sim= 19.0 export= 11.0 diag= 0.0 µs | exported=0.20 MB acks=2500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 25000 (sensor_active= 11440, alerts= 49, act= 2500) | faults=231419 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.4 µs | ingest= 125.7 sim= 15.0 export= 9.9 diag= 0.0 µs | exported=101.74 MB acks=1252500
|
||||||
|
tick= 2000 | entities= 25000 (sensor_active= 11301, alerts= 43, act= 2500) | faults=456552 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.6 µs | ingest= 125.8 sim= 15.1 export= 9.9 diag= 0.0 µs | exported=304.78 MB acks=3752500
|
||||||
|
tick= 3000 | entities= 25000 (sensor_active= 11421, alerts= 58, act= 2500) | faults=681247 lockouts= 0 | rss= 0.0 MB | tick_mean= 276.1 µs | ingest= 126.4 sim= 15.1 export= 10.0 diag= 0.0 µs | exported=507.82 MB acks=6252500
|
||||||
|
tick= 4000 | entities= 25000 (sensor_active= 11157, alerts= 48, act= 2500) | faults=906865 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.5 µs | ingest= 125.7 sim= 15.1 export= 9.9 diag= 0.0 µs | exported=710.88 MB acks=8752500
|
||||||
|
tick= 5000 | entities= 25000 (sensor_active= 11216, alerts= 49, act= 2500) | faults=1131163 lockouts= 0 | rss= 0.0 MB | tick_mean= 274.9 µs | ingest= 125.9 sim= 15.0 export= 9.9 diag= 0.0 µs | exported=913.91 MB acks=11252500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 1.378 s
|
||||||
|
Sustained tick rate: 3629.5 Hz
|
||||||
|
Per-tick mean (wall): 27.5 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 125.6
|
||||||
|
SimulationSystem: 15.0
|
||||||
|
ExportSystem: 9.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 1243639
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 1015.22 MB
|
||||||
|
Acks processed: 12500000
|
||||||
|
Alerts seen: 254654
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=50000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=50000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=35000 EventAsset=10000 ActuatorAsset=5000 total=50000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 50000 (sensor_active= 44082, alerts= 0, act= 5000) | faults= 918 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 104.0 sim= 34.0 export= 18.0 diag= 0.0 µs | exported=0.41 MB acks=5000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 50000 (sensor_active= 22364, alerts= 118, act= 5000) | faults=462345 lockouts= 0 | rss= 0.0 MB | tick_mean= 548.8 µs | ingest= 254.6 sim= 30.7 export= 20.0 diag= 0.0 µs | exported=203.46 MB acks=2505000
|
||||||
|
tick= 2000 | entities= 50000 (sensor_active= 22510, alerts= 97, act= 5000) | faults=912440 lockouts= 0 | rss= 0.0 MB | tick_mean= 546.7 µs | ingest= 253.0 sim= 30.3 export= 19.9 diag= 0.0 µs | exported=609.56 MB acks=7505000
|
||||||
|
tick= 3000 | entities= 50000 (sensor_active= 22512, alerts= 90, act= 5000) | faults=1361728 lockouts= 0 | rss= 0.0 MB | tick_mean= 549.3 µs | ingest= 254.3 sim= 30.6 export= 20.1 diag= 0.0 µs | exported=1015.66 MB acks=12505000
|
||||||
|
tick= 4000 | entities= 50000 (sensor_active= 22519, alerts= 98, act= 5000) | faults=1812084 lockouts= 0 | rss= 0.0 MB | tick_mean= 549.2 µs | ingest= 254.1 sim= 30.5 export= 20.0 diag= 0.0 µs | exported=1421.74 MB acks=17505000
|
||||||
|
tick= 5000 | entities= 50000 (sensor_active= 22355, alerts= 101, act= 5000) | faults=2261407 lockouts= 0 | rss= 0.0 MB | tick_mean= 545.8 µs | ingest= 252.6 sim= 30.4 export= 19.9 diag= 0.0 µs | exported=1827.82 MB acks=22505000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 2.743 s
|
||||||
|
Sustained tick rate: 1822.8 Hz
|
||||||
|
Per-tick mean (wall): 54.9 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 254.0
|
||||||
|
SimulationSystem: 30.5
|
||||||
|
ExportSystem: 19.9
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 2486121
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 2030.46 MB
|
||||||
|
Acks processed: 25000000
|
||||||
|
Alerts seen: 511654
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=75000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=75000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=52500 EventAsset=15000 ActuatorAsset=7500 total=75000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 75000 (sensor_active= 66146, alerts= 0, act= 7500) | faults= 1354 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 188.0 sim= 62.0 export= 32.0 diag= 0.0 µs | exported=0.61 MB acks=7500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 75000 (sensor_active= 33877, alerts= 133, act= 7500) | faults=693165 lockouts= 0 | rss= 0.0 MB | tick_mean= 818.6 µs | ingest= 378.8 sim= 45.8 export= 30.8 diag= 0.0 µs | exported=305.18 MB acks=3757500
|
||||||
|
tick= 2000 | entities= 75000 (sensor_active= 33696, alerts= 163, act= 7500) | faults=1367793 lockouts= 0 | rss= 0.0 MB | tick_mean= 817.4 µs | ingest= 377.4 sim= 45.7 export= 30.6 diag= 0.0 µs | exported=914.34 MB acks=11257500
|
||||||
|
tick= 3000 | entities= 75000 (sensor_active= 33889, alerts= 145, act= 7500) | faults=2042643 lockouts= 0 | rss= 0.0 MB | tick_mean= 817.6 µs | ingest= 377.7 sim= 45.8 export= 30.6 diag= 0.0 µs | exported=1523.51 MB acks=18757500
|
||||||
|
tick= 4000 | entities= 75000 (sensor_active= 33657, alerts= 169, act= 7500) | faults=2717674 lockouts= 0 | rss= 0.0 MB | tick_mean= 815.9 µs | ingest= 376.7 sim= 45.6 export= 30.5 diag= 0.0 µs | exported=2132.66 MB acks=26257500
|
||||||
|
tick= 5000 | entities= 75000 (sensor_active= 33573, alerts= 162, act= 7500) | faults=3393495 lockouts= 0 | rss= 0.0 MB | tick_mean= 820.1 µs | ingest= 377.7 sim= 45.7 export= 30.7 diag= 0.0 µs | exported=2741.78 MB acks=33757500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 4.094 s
|
||||||
|
Sustained tick rate: 1221.3 Hz
|
||||||
|
Per-tick mean (wall): 82.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 377.6
|
||||||
|
SimulationSystem: 45.7
|
||||||
|
ExportSystem: 30.6
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 3730093
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 3045.72 MB
|
||||||
|
Acks processed: 37500000
|
||||||
|
Alerts seen: 771425
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=100000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=100000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=70000 EventAsset=20000 ActuatorAsset=10000 total=100000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 100000 (sensor_active= 88228, alerts= 0, act=10000) | faults= 1772 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 202.0 sim= 75.0 export= 41.0 diag= 0.0 µs | exported=0.81 MB acks=10000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 100000 (sensor_active= 45396, alerts= 218, act=10000) | faults=924085 lockouts= 0 | rss= 0.0 MB | tick_mean= 1101.8 µs | ingest= 500.9 sim= 61.2 export= 40.6 diag= 0.0 µs | exported=406.92 MB acks=5010000
|
||||||
|
tick= 2000 | entities= 100000 (sensor_active= 44998, alerts= 212, act=10000) | faults=1823730 lockouts= 0 | rss= 0.0 MB | tick_mean= 1105.1 µs | ingest= 501.0 sim= 61.1 export= 40.6 diag= 0.0 µs | exported=1219.14 MB acks=15010000
|
||||||
|
tick= 3000 | entities= 100000 (sensor_active= 45132, alerts= 187, act=10000) | faults=2723608 lockouts= 0 | rss= 0.0 MB | tick_mean= 1114.2 µs | ingest= 504.7 sim= 61.5 export= 40.8 diag= 0.0 µs | exported=2031.31 MB acks=25010000
|
||||||
|
tick= 4000 | entities= 100000 (sensor_active= 45039, alerts= 226, act=10000) | faults=3624295 lockouts= 0 | rss= 0.0 MB | tick_mean= 1112.0 µs | ingest= 505.0 sim= 61.7 export= 40.9 diag= 0.0 µs | exported=2843.48 MB acks=35010000
|
||||||
|
tick= 5000 | entities= 100000 (sensor_active= 45069, alerts= 206, act=10000) | faults=4525217 lockouts= 0 | rss= 0.0 MB | tick_mean= 1112.9 µs | ingest= 504.7 sim= 61.8 export= 40.9 diag= 0.0 µs | exported=3655.68 MB acks=45010000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 5.555 s
|
||||||
|
Sustained tick rate: 900.2 Hz
|
||||||
|
Per-tick mean (wall): 111.2 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 504.2
|
||||||
|
SimulationSystem: 61.8
|
||||||
|
ExportSystem: 41.0
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 4974449
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 4060.96 MB
|
||||||
|
Acks processed: 50000000
|
||||||
|
Alerts seen: 1028407
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=150000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=150000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=105000 EventAsset=30000 ActuatorAsset=15000 total=150000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 150000 (sensor_active=132379, alerts= 0, act=15000) | faults= 2621 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 306.0 sim= 113.0 export= 61.0 diag= 0.0 µs | exported=1.22 MB acks=15000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 150000 (sensor_active= 67721, alerts= 326, act=15000) | faults=1385323 lockouts= 0 | rss= 0.0 MB | tick_mean= 1717.3 µs | ingest= 755.7 sim= 92.9 export= 61.8 diag= 0.0 µs | exported=610.34 MB acks=7515000
|
||||||
|
tick= 2000 | entities= 150000 (sensor_active= 67238, alerts= 278, act=15000) | faults=2736064 lockouts= 0 | rss= 0.0 MB | tick_mean= 1721.7 µs | ingest= 755.2 sim= 93.0 export= 61.8 diag= 0.0 µs | exported=1828.59 MB acks=22515000
|
||||||
|
tick= 3000 | entities= 150000 (sensor_active= 67728, alerts= 330, act=15000) | faults=4087020 lockouts= 0 | rss= 0.0 MB | tick_mean= 1719.6 µs | ingest= 753.9 sim= 93.0 export= 61.5 diag= 0.0 µs | exported=3046.89 MB acks=37515000
|
||||||
|
tick= 4000 | entities= 150000 (sensor_active= 67533, alerts= 323, act=15000) | faults=5437256 lockouts= 0 | rss= 0.0 MB | tick_mean= 1715.2 µs | ingest= 753.4 sim= 92.6 export= 61.5 diag= 0.0 µs | exported=4265.19 MB acks=52515000
|
||||||
|
tick= 5000 | entities= 150000 (sensor_active= 67700, alerts= 334, act=15000) | faults=6786973 lockouts= 0 | rss= 0.0 MB | tick_mean= 1726.7 µs | ingest= 755.2 sim= 93.0 export= 61.8 diag= 0.0 µs | exported=5483.51 MB acks=67515000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 8.604 s
|
||||||
|
Sustained tick rate: 581.1 Hz
|
||||||
|
Per-tick mean (wall): 171.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 754.2
|
||||||
|
SimulationSystem: 92.5
|
||||||
|
ExportSystem: 61.7
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 7460636
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 6091.45 MB
|
||||||
|
Acks processed: 75000000
|
||||||
|
Alerts seen: 1543036
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=200000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=200000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=140000 EventAsset=40000 ActuatorAsset=20000 total=200000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 200000 (sensor_active=176493, alerts= 0, act=20000) | faults= 3507 lockouts= 0 | rss= 0.0 MB | tick_mean= 0.0 µs | ingest= 415.0 sim= 160.0 export= 84.0 diag= 0.0 µs | exported=1.62 MB acks=20000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 200000 (sensor_active= 90145, alerts= 390, act=20000) | faults=1847083 lockouts= 0 | rss= 0.0 MB | tick_mean= 2413.0 µs | ingest=1003.2 sim= 125.4 export= 83.3 diag= 0.0 µs | exported=813.81 MB acks=10020000
|
||||||
|
tick= 2000 | entities= 200000 (sensor_active= 90392, alerts= 385, act=20000) | faults=3647521 lockouts= 0 | rss= 0.0 MB | tick_mean= 2409.9 µs | ingest=1003.2 sim= 125.4 export= 83.1 diag= 0.0 µs | exported=2438.20 MB acks=30020000
|
||||||
|
tick= 3000 | entities= 200000 (sensor_active= 90372, alerts= 391, act=20000) | faults=5447700 lockouts= 0 | rss= 0.0 MB | tick_mean= 2380.4 µs | ingest= 998.3 sim= 124.5 export= 82.8 diag= 0.0 µs | exported=4062.57 MB acks=50020000
|
||||||
|
tick= 4000 | entities= 200000 (sensor_active= 89452, alerts= 451, act=20000) | faults=7247668 lockouts= 0 | rss= 0.0 MB | tick_mean= 2380.1 µs | ingest= 998.7 sim= 124.7 export= 82.5 diag= 0.0 µs | exported=5686.95 MB acks=70020000
|
||||||
|
tick= 5000 | entities= 200000 (sensor_active= 89914, alerts= 424, act=20000) | faults=9047286 lockouts= 0 | rss= 0.0 MB | tick_mean= 2386.7 µs | ingest= 999.0 sim= 124.7 export= 82.8 diag= 0.0 µs | exported=7311.35 MB acks=90020000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 11.966 s
|
||||||
|
Sustained tick rate: 417.9 Hz
|
||||||
|
Per-tick mean (wall): 239.4 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 1001.3
|
||||||
|
SimulationSystem: 125.2
|
||||||
|
ExportSystem: 83.1
|
||||||
|
DiagnosticsSystem: 0.0
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 9946420
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 8121.92 MB
|
||||||
|
Acks processed: 100000000
|
||||||
|
Alerts seen: 2056796
|
||||||
|
|
||||||
|
Memory (RSS at end): 0.0 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
10
results/sysinfo.txt
Normal file
10
results/sysinfo.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
=== System Information ===
|
||||||
|
Date: 2026-04-20 21:17:09 UTC
|
||||||
|
OS: Darwin 25.4.0
|
||||||
|
Arch: arm64
|
||||||
|
Target CPU: apple-m1
|
||||||
|
Rust: rustc 1.94.0 (4a4ef493e 2026-03-02)
|
||||||
|
Cargo: cargo 1.94.0 (85eff7c80 2026-01-15)
|
||||||
|
|
||||||
|
Apple M4 Max
|
||||||
|
Memory: 128.0 GB
|
||||||
35
results_rpi/csv/entities_10000.txt
Normal file
35
results_rpi/csv/entities_10000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=10000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=7000 EventAsset=2000 ActuatorAsset=1000 total=10000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 10000 (sensor_active= 8817, alerts= 0, act= 1000) | faults= 183 lockouts= 0 | rss= 4.0 MB | tick_mean= 0.0 µs | ingest= 97.0 sim= 27.0 export= 14.0 diag= 0.0 µs | exported=0.08 MB acks=1000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 10000 (sensor_active= 4488, alerts= 23, act= 1000) | faults= 92482 lockouts= 0 | rss= 6.3 MB | tick_mean= 284.8 µs | ingest= 97.1 sim= 17.1 export= 14.0 diag= 0.0 µs | exported=40.70 MB acks=501000
|
||||||
|
tick= 2000 | entities= 10000 (sensor_active= 4425, alerts= 23, act= 1000) | faults=182979 lockouts= 0 | rss= 7.8 MB | tick_mean= 286.0 µs | ingest= 97.1 sim= 17.2 export= 14.1 diag= 0.1 µs | exported=121.92 MB acks=1501000
|
||||||
|
tick= 3000 | entities= 10000 (sensor_active= 4507, alerts= 27, act= 1000) | faults=273085 lockouts= 0 | rss= 9.3 MB | tick_mean= 286.1 µs | ingest= 97.3 sim= 17.3 export= 14.1 diag= 0.1 µs | exported=203.15 MB acks=2501000
|
||||||
|
tick= 4000 | entities= 10000 (sensor_active= 4502, alerts= 15, act= 1000) | faults=363376 lockouts= 0 | rss= 10.9 MB | tick_mean= 284.8 µs | ingest= 97.0 sim= 17.2 export= 14.0 diag= 0.1 µs | exported=284.37 MB acks=3501000
|
||||||
|
tick= 5000 | entities= 10000 (sensor_active= 4527, alerts= 24, act= 1000) | faults=453183 lockouts= 0 | rss= 12.4 MB | tick_mean= 284.6 µs | ingest= 97.1 sim= 17.2 export= 14.0 diag= 0.1 µs | exported=365.59 MB acks=4501000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 1.430 s
|
||||||
|
Sustained tick rate: 3497.7 Hz
|
||||||
|
Per-tick mean (wall): 28.5 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 97.2
|
||||||
|
SimulationSystem: 17.2
|
||||||
|
ExportSystem: 14.0
|
||||||
|
DiagnosticsSystem: 0.1
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 498016
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 406.11 MB
|
||||||
|
Acks processed: 5000000
|
||||||
|
Alerts seen: 104943
|
||||||
|
|
||||||
|
Memory (RSS at end): 13.1 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/csv/entities_100000.txt
Normal file
35
results_rpi/csv/entities_100000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=100000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=70000 EventAsset=20000 ActuatorAsset=10000 total=100000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 100000 (sensor_active= 88228, alerts= 0, act=10000) | faults= 1772 lockouts= 0 | rss= 16.3 MB | tick_mean= 0.0 µs | ingest= 948.0 sim= 607.0 export= 157.0 diag= 0.0 µs | exported=0.81 MB acks=10000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 100000 (sensor_active= 45396, alerts= 218, act=10000) | faults=924085 lockouts= 0 | rss= 36.7 MB | tick_mean= 4126.0 µs | ingest= 986.9 sim= 218.2 export= 150.2 diag= 0.0 µs | exported=406.92 MB acks=5010000
|
||||||
|
tick= 2000 | entities= 100000 (sensor_active= 44998, alerts= 212, act=10000) | faults=1823730 lockouts= 0 | rss= 51.9 MB | tick_mean= 4197.8 µs | ingest= 987.7 sim= 236.6 export= 152.8 diag= 0.1 µs | exported=1219.14 MB acks=15010000
|
||||||
|
tick= 3000 | entities= 100000 (sensor_active= 45132, alerts= 187, act=10000) | faults=2723608 lockouts= 0 | rss= 67.2 MB | tick_mean= 4132.4 µs | ingest= 986.1 sim= 217.8 export= 150.1 diag= 0.1 µs | exported=2031.31 MB acks=25010000
|
||||||
|
tick= 4000 | entities= 100000 (sensor_active= 45039, alerts= 209, act=10000) | faults=3624295 lockouts= 0 | rss= 82.4 MB | tick_mean= 4132.1 µs | ingest= 986.5 sim= 217.8 export= 150.1 diag= 0.1 µs | exported=2843.48 MB acks=35010000
|
||||||
|
tick= 5000 | entities= 100000 (sensor_active= 45069, alerts= 187, act=10000) | faults=4525217 lockouts= 0 | rss= 97.7 MB | tick_mean= 4132.9 µs | ingest= 985.3 sim= 217.1 export= 150.0 diag= 0.1 µs | exported=3655.69 MB acks=45010000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 20.732 s
|
||||||
|
Sustained tick rate: 241.2 Hz
|
||||||
|
Per-tick mean (wall): 413.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 985.7
|
||||||
|
SimulationSystem: 217.2
|
||||||
|
ExportSystem: 150.1
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 4974449
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 4060.97 MB
|
||||||
|
Acks processed: 50000000
|
||||||
|
Alerts seen: 1029861
|
||||||
|
|
||||||
|
Memory (RSS at end): 105.3 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/csv/entities_150000.txt
Normal file
35
results_rpi/csv/entities_150000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=150000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=105000 EventAsset=30000 ActuatorAsset=15000 total=150000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 150000 (sensor_active=132379, alerts= 0, act=15000) | faults= 2621 lockouts= 0 | rss= 24.5 MB | tick_mean= 0.0 µs | ingest=1444.0 sim= 884.0 export= 251.0 diag= 0.0 µs | exported=1.22 MB acks=15000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 150000 (sensor_active= 67721, alerts= 306, act=15000) | faults=1385323 lockouts= 0 | rss= 54.3 MB | tick_mean= 6453.6 µs | ingest=1517.1 sim= 381.6 export= 226.7 diag= 0.0 µs | exported=610.34 MB acks=7515000
|
||||||
|
tick= 2000 | entities= 150000 (sensor_active= 67238, alerts= 279, act=15000) | faults=2736064 lockouts= 0 | rss= 77.2 MB | tick_mean= 6469.3 µs | ingest=1517.2 sim= 381.6 export= 226.8 diag= 0.1 µs | exported=1828.57 MB acks=22515000
|
||||||
|
tick= 3000 | entities= 150000 (sensor_active= 67728, alerts= 317, act=15000) | faults=4087020 lockouts= 0 | rss= 100.1 MB | tick_mean= 6473.9 µs | ingest=1519.6 sim= 382.4 export= 227.0 diag= 0.1 µs | exported=3046.87 MB acks=37515000
|
||||||
|
tick= 4000 | entities= 150000 (sensor_active= 67533, alerts= 320, act=15000) | faults=5437256 lockouts= 0 | rss= 123.0 MB | tick_mean= 6470.4 µs | ingest=1518.3 sim= 381.8 export= 226.7 diag= 0.1 µs | exported=4265.17 MB acks=52515000
|
||||||
|
tick= 5000 | entities= 150000 (sensor_active= 67700, alerts= 323, act=15000) | faults=6786973 lockouts= 0 | rss= 145.8 MB | tick_mean= 6470.2 µs | ingest=1518.6 sim= 382.0 export= 226.7 diag= 0.1 µs | exported=5483.48 MB acks=67515000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 32.355 s
|
||||||
|
Sustained tick rate: 154.5 Hz
|
||||||
|
Per-tick mean (wall): 646.7 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 1517.3
|
||||||
|
SimulationSystem: 381.4
|
||||||
|
ExportSystem: 226.6
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 7460636
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 6091.41 MB
|
||||||
|
Acks processed: 75000000
|
||||||
|
Alerts seen: 1538845
|
||||||
|
|
||||||
|
Memory (RSS at end): 157.2 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/csv/entities_200000.txt
Normal file
35
results_rpi/csv/entities_200000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=200000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=140000 EventAsset=40000 ActuatorAsset=20000 total=200000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 200000 (sensor_active=176493, alerts= 0, act=20000) | faults= 3507 lockouts= 0 | rss= 30.0 MB | tick_mean= 0.0 µs | ingest=1907.0 sim=1336.0 export= 349.0 diag= 0.0 µs | exported=1.62 MB acks=20000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 200000 (sensor_active= 90145, alerts= 405, act=20000) | faults=1847083 lockouts= 0 | rss= 69.5 MB | tick_mean= 8788.2 µs | ingest=2023.3 sim= 582.9 export= 300.9 diag= 0.0 µs | exported=813.81 MB acks=10020000
|
||||||
|
tick= 2000 | entities= 200000 (sensor_active= 90392, alerts= 396, act=20000) | faults=3647521 lockouts= 0 | rss= 100.0 MB | tick_mean= 8805.3 µs | ingest=2023.3 sim= 582.9 export= 300.5 diag= 0.1 µs | exported=2438.20 MB acks=30020000
|
||||||
|
tick= 3000 | entities= 200000 (sensor_active= 90372, alerts= 408, act=20000) | faults=5447700 lockouts= 0 | rss= 130.5 MB | tick_mean= 8805.5 µs | ingest=2023.7 sim= 582.7 export= 300.4 diag= 0.1 µs | exported=4062.57 MB acks=50020000
|
||||||
|
tick= 4000 | entities= 200000 (sensor_active= 89452, alerts= 444, act=20000) | faults=7247668 lockouts= 0 | rss= 161.1 MB | tick_mean= 8808.2 µs | ingest=2024.8 sim= 583.4 export= 300.7 diag= 0.2 µs | exported=5686.94 MB acks=70020000
|
||||||
|
tick= 5000 | entities= 200000 (sensor_active= 89914, alerts= 429, act=20000) | faults=9047286 lockouts= 0 | rss= 191.6 MB | tick_mean= 8804.6 µs | ingest=2022.3 sim= 582.4 export= 300.7 diag= 0.1 µs | exported=7311.36 MB acks=90020000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 44.034 s
|
||||||
|
Sustained tick rate: 113.5 Hz
|
||||||
|
Per-tick mean (wall): 880.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 2022.7
|
||||||
|
SimulationSystem: 582.0
|
||||||
|
ExportSystem: 300.7
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 9946420
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 8121.94 MB
|
||||||
|
Acks processed: 100000000
|
||||||
|
Alerts seen: 2059136
|
||||||
|
|
||||||
|
Memory (RSS at end): 206.8 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/csv/entities_25000.txt
Normal file
35
results_rpi/csv/entities_25000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=25000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=17500 EventAsset=5000 ActuatorAsset=2500 total=25000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 25000 (sensor_active= 22049, alerts= 0, act= 2500) | faults= 451 lockouts= 0 | rss= 6.0 MB | tick_mean= 0.0 µs | ingest= 236.0 sim= 81.0 export= 36.0 diag= 0.0 µs | exported=0.20 MB acks=2500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 25000 (sensor_active= 11440, alerts= 49, act= 2500) | faults=231419 lockouts= 0 | rss= 11.6 MB | tick_mean= 812.9 µs | ingest= 243.3 sim= 43.2 export= 35.1 diag= 0.0 µs | exported=101.74 MB acks=1252500
|
||||||
|
tick= 2000 | entities= 25000 (sensor_active= 11301, alerts= 43, act= 2500) | faults=456552 lockouts= 0 | rss= 15.5 MB | tick_mean= 812.1 µs | ingest= 244.1 sim= 43.2 export= 35.1 diag= 0.1 µs | exported=304.78 MB acks=3752500
|
||||||
|
tick= 3000 | entities= 25000 (sensor_active= 11421, alerts= 58, act= 2500) | faults=681247 lockouts= 0 | rss= 19.2 MB | tick_mean= 811.6 µs | ingest= 243.6 sim= 43.0 export= 35.1 diag= 0.1 µs | exported=507.82 MB acks=6252500
|
||||||
|
tick= 4000 | entities= 25000 (sensor_active= 11157, alerts= 48, act= 2500) | faults=906865 lockouts= 0 | rss= 23.1 MB | tick_mean= 814.2 µs | ingest= 244.0 sim= 43.3 export= 35.1 diag= 0.1 µs | exported=710.88 MB acks=8752500
|
||||||
|
tick= 5000 | entities= 25000 (sensor_active= 11216, alerts= 49, act= 2500) | faults=1131163 lockouts= 0 | rss= 26.9 MB | tick_mean= 811.4 µs | ingest= 243.6 sim= 43.2 export= 35.1 diag= 0.1 µs | exported=913.91 MB acks=11252500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 4.066 s
|
||||||
|
Sustained tick rate: 1229.7 Hz
|
||||||
|
Per-tick mean (wall): 81.3 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 244.0
|
||||||
|
SimulationSystem: 43.2
|
||||||
|
ExportSystem: 35.1
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 1243639
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 1015.22 MB
|
||||||
|
Acks processed: 12500000
|
||||||
|
Alerts seen: 254654
|
||||||
|
|
||||||
|
Memory (RSS at end): 28.8 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/csv/entities_50000.txt
Normal file
35
results_rpi/csv/entities_50000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=50000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=35000 EventAsset=10000 ActuatorAsset=5000 total=50000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 50000 (sensor_active= 44082, alerts= 0, act= 5000) | faults= 918 lockouts= 0 | rss= 9.4 MB | tick_mean= 0.0 µs | ingest= 528.0 sim= 211.0 export= 73.0 diag= 0.0 µs | exported=0.41 MB acks=5000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 50000 (sensor_active= 22364, alerts= 118, act= 5000) | faults=462345 lockouts= 0 | rss= 20.1 MB | tick_mean= 1918.9 µs | ingest= 497.0 sim= 94.6 export= 70.9 diag= 0.0 µs | exported=203.46 MB acks=2505000
|
||||||
|
tick= 2000 | entities= 50000 (sensor_active= 22510, alerts= 97, act= 5000) | faults=912440 lockouts= 0 | rss= 27.7 MB | tick_mean= 1922.8 µs | ingest= 496.6 sim= 94.4 export= 71.0 diag= 0.1 µs | exported=609.56 MB acks=7505000
|
||||||
|
tick= 3000 | entities= 50000 (sensor_active= 22512, alerts= 90, act= 5000) | faults=1361728 lockouts= 0 | rss= 35.3 MB | tick_mean= 1924.0 µs | ingest= 497.0 sim= 94.7 export= 71.0 diag= 0.1 µs | exported=1015.66 MB acks=12505000
|
||||||
|
tick= 4000 | entities= 50000 (sensor_active= 22519, alerts= 98, act= 5000) | faults=1812084 lockouts= 0 | rss= 43.0 MB | tick_mean= 1922.6 µs | ingest= 496.6 sim= 94.5 export= 70.8 diag= 0.1 µs | exported=1421.74 MB acks=17505000
|
||||||
|
tick= 5000 | entities= 50000 (sensor_active= 22355, alerts= 101, act= 5000) | faults=2261407 lockouts= 0 | rss= 50.6 MB | tick_mean= 1921.7 µs | ingest= 496.7 sim= 94.5 export= 70.9 diag= 0.1 µs | exported=1827.82 MB acks=22505000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 9.617 s
|
||||||
|
Sustained tick rate: 519.9 Hz
|
||||||
|
Per-tick mean (wall): 192.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 496.0
|
||||||
|
SimulationSystem: 94.5
|
||||||
|
ExportSystem: 70.8
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 2486121
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 2030.46 MB
|
||||||
|
Acks processed: 25000000
|
||||||
|
Alerts seen: 511654
|
||||||
|
|
||||||
|
Memory (RSS at end): 54.3 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/csv/entities_75000.txt
Normal file
35
results_rpi/csv/entities_75000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=75000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=52500 EventAsset=15000 ActuatorAsset=7500 total=75000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 75000 (sensor_active= 66146, alerts= 0, act= 7500) | faults= 1354 lockouts= 0 | rss= 13.6 MB | tick_mean= 0.0 µs | ingest= 713.0 sim= 383.0 export= 112.0 diag= 0.0 µs | exported=0.61 MB acks=7500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 75000 (sensor_active= 33877, alerts= 142, act= 7500) | faults=693165 lockouts= 0 | rss= 28.7 MB | tick_mean= 3016.1 µs | ingest= 735.8 sim= 156.6 export= 110.8 diag= 0.0 µs | exported=305.18 MB acks=3757500
|
||||||
|
tick= 2000 | entities= 75000 (sensor_active= 33696, alerts= 166, act= 7500) | faults=1367793 lockouts= 0 | rss= 40.1 MB | tick_mean= 3021.4 µs | ingest= 735.8 sim= 156.7 export= 110.8 diag= 0.1 µs | exported=914.34 MB acks=11257500
|
||||||
|
tick= 3000 | entities= 75000 (sensor_active= 33889, alerts= 159, act= 7500) | faults=2042643 lockouts= 0 | rss= 51.5 MB | tick_mean= 3024.8 µs | ingest= 736.4 sim= 156.9 export= 110.8 diag= 0.1 µs | exported=1523.51 MB acks=18757500
|
||||||
|
tick= 4000 | entities= 75000 (sensor_active= 33657, alerts= 166, act= 7500) | faults=2717674 lockouts= 0 | rss= 63.0 MB | tick_mean= 3022.6 µs | ingest= 735.3 sim= 156.9 export= 110.8 diag= 0.2 µs | exported=2132.66 MB acks=26257500
|
||||||
|
tick= 5000 | entities= 75000 (sensor_active= 33573, alerts= 155, act= 7500) | faults=3393495 lockouts= 0 | rss= 74.4 MB | tick_mean= 3021.8 µs | ingest= 735.2 sim= 156.5 export= 110.8 diag= 0.2 µs | exported=2741.79 MB acks=33757500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 15.118 s
|
||||||
|
Sustained tick rate: 330.7 Hz
|
||||||
|
Per-tick mean (wall): 302.3 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 736.2
|
||||||
|
SimulationSystem: 156.6
|
||||||
|
ExportSystem: 110.7
|
||||||
|
DiagnosticsSystem: 0.3
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 3730093
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 3045.74 MB
|
||||||
|
Acks processed: 37500000
|
||||||
|
Alerts seen: 773395
|
||||||
|
|
||||||
|
Memory (RSS at end): 80.1 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
8
results_rpi/final_table.csv
Normal file
8
results_rpi/final_table.csv
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
entities,ticks,wall_s,hz,per_tick_us,ingest_us,sim_us,export_us,diag_us,sensor_faults,actuator_lockouts,exported_mb,acks,alerts,rss_mb
|
||||||
|
10000,5000,,,,97.2,17.2,14.0,0.1,498016,0,,5000000,104943,
|
||||||
|
25000,5000,,,,244.0,43.2,35.1,0.2,1243639,0,,12500000,254654,
|
||||||
|
50000,5000,,,,496.0,94.5,70.8,0.2,2486121,0,,25000000,511654,
|
||||||
|
75000,5000,,,,736.2,156.6,110.7,0.3,3730093,0,,37500000,773395,
|
||||||
|
100000,5000,,,,985.7,217.2,150.1,0.2,4974449,0,,50000000,1029861,
|
||||||
|
150000,5000,,,,1517.3,381.4,226.6,0.2,7460636,0,,75000000,1538845,
|
||||||
|
200000,5000,,,,2022.7,582.0,300.7,0.2,9946420,0,,100000000,2059136,
|
||||||
|
35
results_rpi/raw_10000.txt
Normal file
35
results_rpi/raw_10000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=10000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=7000 EventAsset=2000 ActuatorAsset=1000 total=10000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 10000 (sensor_active= 8817, alerts= 0, act= 1000) | faults= 183 lockouts= 0 | rss= 4.0 MB | tick_mean= 0.0 µs | ingest= 97.0 sim= 27.0 export= 14.0 diag= 0.0 µs | exported=0.08 MB acks=1000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 10000 (sensor_active= 4488, alerts= 23, act= 1000) | faults= 92482 lockouts= 0 | rss= 6.3 MB | tick_mean= 284.8 µs | ingest= 97.1 sim= 17.1 export= 14.0 diag= 0.0 µs | exported=40.70 MB acks=501000
|
||||||
|
tick= 2000 | entities= 10000 (sensor_active= 4425, alerts= 23, act= 1000) | faults=182979 lockouts= 0 | rss= 7.8 MB | tick_mean= 286.0 µs | ingest= 97.1 sim= 17.2 export= 14.1 diag= 0.1 µs | exported=121.92 MB acks=1501000
|
||||||
|
tick= 3000 | entities= 10000 (sensor_active= 4507, alerts= 27, act= 1000) | faults=273085 lockouts= 0 | rss= 9.3 MB | tick_mean= 286.1 µs | ingest= 97.3 sim= 17.3 export= 14.1 diag= 0.1 µs | exported=203.15 MB acks=2501000
|
||||||
|
tick= 4000 | entities= 10000 (sensor_active= 4502, alerts= 15, act= 1000) | faults=363376 lockouts= 0 | rss= 10.9 MB | tick_mean= 284.8 µs | ingest= 97.0 sim= 17.2 export= 14.0 diag= 0.1 µs | exported=284.37 MB acks=3501000
|
||||||
|
tick= 5000 | entities= 10000 (sensor_active= 4527, alerts= 24, act= 1000) | faults=453183 lockouts= 0 | rss= 12.4 MB | tick_mean= 284.6 µs | ingest= 97.1 sim= 17.2 export= 14.0 diag= 0.1 µs | exported=365.59 MB acks=4501000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 1.430 s
|
||||||
|
Sustained tick rate: 3497.7 Hz
|
||||||
|
Per-tick mean (wall): 28.5 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 97.2
|
||||||
|
SimulationSystem: 17.2
|
||||||
|
ExportSystem: 14.0
|
||||||
|
DiagnosticsSystem: 0.1
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 498016
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 406.11 MB
|
||||||
|
Acks processed: 5000000
|
||||||
|
Alerts seen: 104943
|
||||||
|
|
||||||
|
Memory (RSS at end): 13.1 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/raw_100000.txt
Normal file
35
results_rpi/raw_100000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=100000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=70000 EventAsset=20000 ActuatorAsset=10000 total=100000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 100000 (sensor_active= 88228, alerts= 0, act=10000) | faults= 1772 lockouts= 0 | rss= 16.3 MB | tick_mean= 0.0 µs | ingest= 948.0 sim= 607.0 export= 157.0 diag= 0.0 µs | exported=0.81 MB acks=10000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 100000 (sensor_active= 45396, alerts= 218, act=10000) | faults=924085 lockouts= 0 | rss= 36.7 MB | tick_mean= 4126.0 µs | ingest= 986.9 sim= 218.2 export= 150.2 diag= 0.0 µs | exported=406.92 MB acks=5010000
|
||||||
|
tick= 2000 | entities= 100000 (sensor_active= 44998, alerts= 212, act=10000) | faults=1823730 lockouts= 0 | rss= 51.9 MB | tick_mean= 4197.8 µs | ingest= 987.7 sim= 236.6 export= 152.8 diag= 0.1 µs | exported=1219.14 MB acks=15010000
|
||||||
|
tick= 3000 | entities= 100000 (sensor_active= 45132, alerts= 187, act=10000) | faults=2723608 lockouts= 0 | rss= 67.2 MB | tick_mean= 4132.4 µs | ingest= 986.1 sim= 217.8 export= 150.1 diag= 0.1 µs | exported=2031.31 MB acks=25010000
|
||||||
|
tick= 4000 | entities= 100000 (sensor_active= 45039, alerts= 209, act=10000) | faults=3624295 lockouts= 0 | rss= 82.4 MB | tick_mean= 4132.1 µs | ingest= 986.5 sim= 217.8 export= 150.1 diag= 0.1 µs | exported=2843.48 MB acks=35010000
|
||||||
|
tick= 5000 | entities= 100000 (sensor_active= 45069, alerts= 187, act=10000) | faults=4525217 lockouts= 0 | rss= 97.7 MB | tick_mean= 4132.9 µs | ingest= 985.3 sim= 217.1 export= 150.0 diag= 0.1 µs | exported=3655.69 MB acks=45010000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 20.732 s
|
||||||
|
Sustained tick rate: 241.2 Hz
|
||||||
|
Per-tick mean (wall): 413.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 985.7
|
||||||
|
SimulationSystem: 217.2
|
||||||
|
ExportSystem: 150.1
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 4974449
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 4060.97 MB
|
||||||
|
Acks processed: 50000000
|
||||||
|
Alerts seen: 1029861
|
||||||
|
|
||||||
|
Memory (RSS at end): 105.3 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/raw_150000.txt
Normal file
35
results_rpi/raw_150000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=150000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=105000 EventAsset=30000 ActuatorAsset=15000 total=150000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 150000 (sensor_active=132379, alerts= 0, act=15000) | faults= 2621 lockouts= 0 | rss= 24.5 MB | tick_mean= 0.0 µs | ingest=1444.0 sim= 884.0 export= 251.0 diag= 0.0 µs | exported=1.22 MB acks=15000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 150000 (sensor_active= 67721, alerts= 306, act=15000) | faults=1385323 lockouts= 0 | rss= 54.3 MB | tick_mean= 6453.6 µs | ingest=1517.1 sim= 381.6 export= 226.7 diag= 0.0 µs | exported=610.34 MB acks=7515000
|
||||||
|
tick= 2000 | entities= 150000 (sensor_active= 67238, alerts= 279, act=15000) | faults=2736064 lockouts= 0 | rss= 77.2 MB | tick_mean= 6469.3 µs | ingest=1517.2 sim= 381.6 export= 226.8 diag= 0.1 µs | exported=1828.57 MB acks=22515000
|
||||||
|
tick= 3000 | entities= 150000 (sensor_active= 67728, alerts= 317, act=15000) | faults=4087020 lockouts= 0 | rss= 100.1 MB | tick_mean= 6473.9 µs | ingest=1519.6 sim= 382.4 export= 227.0 diag= 0.1 µs | exported=3046.87 MB acks=37515000
|
||||||
|
tick= 4000 | entities= 150000 (sensor_active= 67533, alerts= 320, act=15000) | faults=5437256 lockouts= 0 | rss= 123.0 MB | tick_mean= 6470.4 µs | ingest=1518.3 sim= 381.8 export= 226.7 diag= 0.1 µs | exported=4265.17 MB acks=52515000
|
||||||
|
tick= 5000 | entities= 150000 (sensor_active= 67700, alerts= 323, act=15000) | faults=6786973 lockouts= 0 | rss= 145.8 MB | tick_mean= 6470.2 µs | ingest=1518.6 sim= 382.0 export= 226.7 diag= 0.1 µs | exported=5483.48 MB acks=67515000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 32.355 s
|
||||||
|
Sustained tick rate: 154.5 Hz
|
||||||
|
Per-tick mean (wall): 646.7 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 1517.3
|
||||||
|
SimulationSystem: 381.4
|
||||||
|
ExportSystem: 226.6
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 7460636
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 6091.41 MB
|
||||||
|
Acks processed: 75000000
|
||||||
|
Alerts seen: 1538845
|
||||||
|
|
||||||
|
Memory (RSS at end): 157.2 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/raw_200000.txt
Normal file
35
results_rpi/raw_200000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=200000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=140000 EventAsset=40000 ActuatorAsset=20000 total=200000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 200000 (sensor_active=176493, alerts= 0, act=20000) | faults= 3507 lockouts= 0 | rss= 30.0 MB | tick_mean= 0.0 µs | ingest=1907.0 sim=1336.0 export= 349.0 diag= 0.0 µs | exported=1.62 MB acks=20000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 200000 (sensor_active= 90145, alerts= 405, act=20000) | faults=1847083 lockouts= 0 | rss= 69.5 MB | tick_mean= 8788.2 µs | ingest=2023.3 sim= 582.9 export= 300.9 diag= 0.0 µs | exported=813.81 MB acks=10020000
|
||||||
|
tick= 2000 | entities= 200000 (sensor_active= 90392, alerts= 396, act=20000) | faults=3647521 lockouts= 0 | rss= 100.0 MB | tick_mean= 8805.3 µs | ingest=2023.3 sim= 582.9 export= 300.5 diag= 0.1 µs | exported=2438.20 MB acks=30020000
|
||||||
|
tick= 3000 | entities= 200000 (sensor_active= 90372, alerts= 408, act=20000) | faults=5447700 lockouts= 0 | rss= 130.5 MB | tick_mean= 8805.5 µs | ingest=2023.7 sim= 582.7 export= 300.4 diag= 0.1 µs | exported=4062.57 MB acks=50020000
|
||||||
|
tick= 4000 | entities= 200000 (sensor_active= 89452, alerts= 444, act=20000) | faults=7247668 lockouts= 0 | rss= 161.1 MB | tick_mean= 8808.2 µs | ingest=2024.8 sim= 583.4 export= 300.7 diag= 0.2 µs | exported=5686.94 MB acks=70020000
|
||||||
|
tick= 5000 | entities= 200000 (sensor_active= 89914, alerts= 429, act=20000) | faults=9047286 lockouts= 0 | rss= 191.6 MB | tick_mean= 8804.6 µs | ingest=2022.3 sim= 582.4 export= 300.7 diag= 0.1 µs | exported=7311.36 MB acks=90020000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 44.034 s
|
||||||
|
Sustained tick rate: 113.5 Hz
|
||||||
|
Per-tick mean (wall): 880.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 2022.7
|
||||||
|
SimulationSystem: 582.0
|
||||||
|
ExportSystem: 300.7
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 9946420
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 8121.94 MB
|
||||||
|
Acks processed: 100000000
|
||||||
|
Alerts seen: 2059136
|
||||||
|
|
||||||
|
Memory (RSS at end): 206.8 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/raw_25000.txt
Normal file
35
results_rpi/raw_25000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=25000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=17500 EventAsset=5000 ActuatorAsset=2500 total=25000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 25000 (sensor_active= 22049, alerts= 0, act= 2500) | faults= 451 lockouts= 0 | rss= 6.0 MB | tick_mean= 0.0 µs | ingest= 236.0 sim= 81.0 export= 36.0 diag= 0.0 µs | exported=0.20 MB acks=2500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 25000 (sensor_active= 11440, alerts= 49, act= 2500) | faults=231419 lockouts= 0 | rss= 11.6 MB | tick_mean= 812.9 µs | ingest= 243.3 sim= 43.2 export= 35.1 diag= 0.0 µs | exported=101.74 MB acks=1252500
|
||||||
|
tick= 2000 | entities= 25000 (sensor_active= 11301, alerts= 43, act= 2500) | faults=456552 lockouts= 0 | rss= 15.5 MB | tick_mean= 812.1 µs | ingest= 244.1 sim= 43.2 export= 35.1 diag= 0.1 µs | exported=304.78 MB acks=3752500
|
||||||
|
tick= 3000 | entities= 25000 (sensor_active= 11421, alerts= 58, act= 2500) | faults=681247 lockouts= 0 | rss= 19.2 MB | tick_mean= 811.6 µs | ingest= 243.6 sim= 43.0 export= 35.1 diag= 0.1 µs | exported=507.82 MB acks=6252500
|
||||||
|
tick= 4000 | entities= 25000 (sensor_active= 11157, alerts= 48, act= 2500) | faults=906865 lockouts= 0 | rss= 23.1 MB | tick_mean= 814.2 µs | ingest= 244.0 sim= 43.3 export= 35.1 diag= 0.1 µs | exported=710.88 MB acks=8752500
|
||||||
|
tick= 5000 | entities= 25000 (sensor_active= 11216, alerts= 49, act= 2500) | faults=1131163 lockouts= 0 | rss= 26.9 MB | tick_mean= 811.4 µs | ingest= 243.6 sim= 43.2 export= 35.1 diag= 0.1 µs | exported=913.91 MB acks=11252500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 4.066 s
|
||||||
|
Sustained tick rate: 1229.7 Hz
|
||||||
|
Per-tick mean (wall): 81.3 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 244.0
|
||||||
|
SimulationSystem: 43.2
|
||||||
|
ExportSystem: 35.1
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 1243639
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 1015.22 MB
|
||||||
|
Acks processed: 12500000
|
||||||
|
Alerts seen: 254654
|
||||||
|
|
||||||
|
Memory (RSS at end): 28.8 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/raw_50000.txt
Normal file
35
results_rpi/raw_50000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=50000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=35000 EventAsset=10000 ActuatorAsset=5000 total=50000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 50000 (sensor_active= 44082, alerts= 0, act= 5000) | faults= 918 lockouts= 0 | rss= 9.4 MB | tick_mean= 0.0 µs | ingest= 528.0 sim= 211.0 export= 73.0 diag= 0.0 µs | exported=0.41 MB acks=5000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 50000 (sensor_active= 22364, alerts= 118, act= 5000) | faults=462345 lockouts= 0 | rss= 20.1 MB | tick_mean= 1918.9 µs | ingest= 497.0 sim= 94.6 export= 70.9 diag= 0.0 µs | exported=203.46 MB acks=2505000
|
||||||
|
tick= 2000 | entities= 50000 (sensor_active= 22510, alerts= 97, act= 5000) | faults=912440 lockouts= 0 | rss= 27.7 MB | tick_mean= 1922.8 µs | ingest= 496.6 sim= 94.4 export= 71.0 diag= 0.1 µs | exported=609.56 MB acks=7505000
|
||||||
|
tick= 3000 | entities= 50000 (sensor_active= 22512, alerts= 90, act= 5000) | faults=1361728 lockouts= 0 | rss= 35.3 MB | tick_mean= 1924.0 µs | ingest= 497.0 sim= 94.7 export= 71.0 diag= 0.1 µs | exported=1015.66 MB acks=12505000
|
||||||
|
tick= 4000 | entities= 50000 (sensor_active= 22519, alerts= 98, act= 5000) | faults=1812084 lockouts= 0 | rss= 43.0 MB | tick_mean= 1922.6 µs | ingest= 496.6 sim= 94.5 export= 70.8 diag= 0.1 µs | exported=1421.74 MB acks=17505000
|
||||||
|
tick= 5000 | entities= 50000 (sensor_active= 22355, alerts= 101, act= 5000) | faults=2261407 lockouts= 0 | rss= 50.6 MB | tick_mean= 1921.7 µs | ingest= 496.7 sim= 94.5 export= 70.9 diag= 0.1 µs | exported=1827.82 MB acks=22505000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 9.617 s
|
||||||
|
Sustained tick rate: 519.9 Hz
|
||||||
|
Per-tick mean (wall): 192.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 496.0
|
||||||
|
SimulationSystem: 94.5
|
||||||
|
ExportSystem: 70.8
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 2486121
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 2030.46 MB
|
||||||
|
Acks processed: 25000000
|
||||||
|
Alerts seen: 511654
|
||||||
|
|
||||||
|
Memory (RSS at end): 54.3 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
35
results_rpi/raw_75000.txt
Normal file
35
results_rpi/raw_75000.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=75000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=52500 EventAsset=15000 ActuatorAsset=7500 total=75000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 75000 (sensor_active= 66146, alerts= 0, act= 7500) | faults= 1354 lockouts= 0 | rss= 13.6 MB | tick_mean= 0.0 µs | ingest= 713.0 sim= 383.0 export= 112.0 diag= 0.0 µs | exported=0.61 MB acks=7500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 75000 (sensor_active= 33877, alerts= 142, act= 7500) | faults=693165 lockouts= 0 | rss= 28.7 MB | tick_mean= 3016.1 µs | ingest= 735.8 sim= 156.6 export= 110.8 diag= 0.0 µs | exported=305.18 MB acks=3757500
|
||||||
|
tick= 2000 | entities= 75000 (sensor_active= 33696, alerts= 166, act= 7500) | faults=1367793 lockouts= 0 | rss= 40.1 MB | tick_mean= 3021.4 µs | ingest= 735.8 sim= 156.7 export= 110.8 diag= 0.1 µs | exported=914.34 MB acks=11257500
|
||||||
|
tick= 3000 | entities= 75000 (sensor_active= 33889, alerts= 159, act= 7500) | faults=2042643 lockouts= 0 | rss= 51.5 MB | tick_mean= 3024.8 µs | ingest= 736.4 sim= 156.9 export= 110.8 diag= 0.1 µs | exported=1523.51 MB acks=18757500
|
||||||
|
tick= 4000 | entities= 75000 (sensor_active= 33657, alerts= 166, act= 7500) | faults=2717674 lockouts= 0 | rss= 63.0 MB | tick_mean= 3022.6 µs | ingest= 735.3 sim= 156.9 export= 110.8 diag= 0.2 µs | exported=2132.66 MB acks=26257500
|
||||||
|
tick= 5000 | entities= 75000 (sensor_active= 33573, alerts= 155, act= 7500) | faults=3393495 lockouts= 0 | rss= 74.4 MB | tick_mean= 3021.8 µs | ingest= 735.2 sim= 156.5 export= 110.8 diag= 0.2 µs | exported=2741.79 MB acks=33757500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 15.118 s
|
||||||
|
Sustained tick rate: 330.7 Hz
|
||||||
|
Per-tick mean (wall): 302.3 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 736.2
|
||||||
|
SimulationSystem: 156.6
|
||||||
|
ExportSystem: 110.7
|
||||||
|
DiagnosticsSystem: 0.3
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 3730093
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 3045.74 MB
|
||||||
|
Acks processed: 37500000
|
||||||
|
Alerts seen: 773395
|
||||||
|
|
||||||
|
Memory (RSS at end): 80.1 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
283
results_rpi/summary.txt
Normal file
283
results_rpi/summary.txt
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
ECS DT Benchmark Sweep — Tue 21 Apr 01:12:15 UTC 2026
|
||||||
|
=== System Information ===
|
||||||
|
Date: 2026-04-21 01:12:15 UTC
|
||||||
|
OS: Linux 6.12.75+rpt-rpi-2712
|
||||||
|
Arch: aarch64
|
||||||
|
Target CPU: cortex-a76
|
||||||
|
Rust: rustc 1.95.0 (59807616e 2026-04-14)
|
||||||
|
Cargo: cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||||
|
|
||||||
|
=== CPU Info ===
|
||||||
|
CPU implementer : 0x41
|
||||||
|
CPU part : 0xd0b
|
||||||
|
Revision : c04180
|
||||||
|
|
||||||
|
=== Memory ===
|
||||||
|
MemTotal: 4146896 kB
|
||||||
|
MemAvailable: 3883072 kB
|
||||||
|
|
||||||
|
=== CPU Governor ===
|
||||||
|
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor: performance
|
||||||
|
|
||||||
|
=== Isolated cores ===
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== entities=10000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=10000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=7000 EventAsset=2000 ActuatorAsset=1000 total=10000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 10000 (sensor_active= 8817, alerts= 0, act= 1000) | faults= 183 lockouts= 0 | rss= 4.0 MB | tick_mean= 0.0 µs | ingest= 97.0 sim= 27.0 export= 14.0 diag= 0.0 µs | exported=0.08 MB acks=1000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 10000 (sensor_active= 4488, alerts= 23, act= 1000) | faults= 92482 lockouts= 0 | rss= 6.3 MB | tick_mean= 284.8 µs | ingest= 97.1 sim= 17.1 export= 14.0 diag= 0.0 µs | exported=40.70 MB acks=501000
|
||||||
|
tick= 2000 | entities= 10000 (sensor_active= 4425, alerts= 23, act= 1000) | faults=182979 lockouts= 0 | rss= 7.8 MB | tick_mean= 286.0 µs | ingest= 97.1 sim= 17.2 export= 14.1 diag= 0.1 µs | exported=121.92 MB acks=1501000
|
||||||
|
tick= 3000 | entities= 10000 (sensor_active= 4507, alerts= 27, act= 1000) | faults=273085 lockouts= 0 | rss= 9.3 MB | tick_mean= 286.1 µs | ingest= 97.3 sim= 17.3 export= 14.1 diag= 0.1 µs | exported=203.15 MB acks=2501000
|
||||||
|
tick= 4000 | entities= 10000 (sensor_active= 4502, alerts= 15, act= 1000) | faults=363376 lockouts= 0 | rss= 10.9 MB | tick_mean= 284.8 µs | ingest= 97.0 sim= 17.2 export= 14.0 diag= 0.1 µs | exported=284.37 MB acks=3501000
|
||||||
|
tick= 5000 | entities= 10000 (sensor_active= 4527, alerts= 24, act= 1000) | faults=453183 lockouts= 0 | rss= 12.4 MB | tick_mean= 284.6 µs | ingest= 97.1 sim= 17.2 export= 14.0 diag= 0.1 µs | exported=365.59 MB acks=4501000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 1.430 s
|
||||||
|
Sustained tick rate: 3497.7 Hz
|
||||||
|
Per-tick mean (wall): 28.5 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 97.2
|
||||||
|
SimulationSystem: 17.2
|
||||||
|
ExportSystem: 14.0
|
||||||
|
DiagnosticsSystem: 0.1
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 498016
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 406.11 MB
|
||||||
|
Acks processed: 5000000
|
||||||
|
Alerts seen: 104943
|
||||||
|
|
||||||
|
Memory (RSS at end): 13.1 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=25000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=25000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=17500 EventAsset=5000 ActuatorAsset=2500 total=25000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 25000 (sensor_active= 22049, alerts= 0, act= 2500) | faults= 451 lockouts= 0 | rss= 6.0 MB | tick_mean= 0.0 µs | ingest= 236.0 sim= 81.0 export= 36.0 diag= 0.0 µs | exported=0.20 MB acks=2500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 25000 (sensor_active= 11440, alerts= 49, act= 2500) | faults=231419 lockouts= 0 | rss= 11.6 MB | tick_mean= 812.9 µs | ingest= 243.3 sim= 43.2 export= 35.1 diag= 0.0 µs | exported=101.74 MB acks=1252500
|
||||||
|
tick= 2000 | entities= 25000 (sensor_active= 11301, alerts= 43, act= 2500) | faults=456552 lockouts= 0 | rss= 15.5 MB | tick_mean= 812.1 µs | ingest= 244.1 sim= 43.2 export= 35.1 diag= 0.1 µs | exported=304.78 MB acks=3752500
|
||||||
|
tick= 3000 | entities= 25000 (sensor_active= 11421, alerts= 58, act= 2500) | faults=681247 lockouts= 0 | rss= 19.2 MB | tick_mean= 811.6 µs | ingest= 243.6 sim= 43.0 export= 35.1 diag= 0.1 µs | exported=507.82 MB acks=6252500
|
||||||
|
tick= 4000 | entities= 25000 (sensor_active= 11157, alerts= 48, act= 2500) | faults=906865 lockouts= 0 | rss= 23.1 MB | tick_mean= 814.2 µs | ingest= 244.0 sim= 43.3 export= 35.1 diag= 0.1 µs | exported=710.88 MB acks=8752500
|
||||||
|
tick= 5000 | entities= 25000 (sensor_active= 11216, alerts= 49, act= 2500) | faults=1131163 lockouts= 0 | rss= 26.9 MB | tick_mean= 811.4 µs | ingest= 243.6 sim= 43.2 export= 35.1 diag= 0.1 µs | exported=913.91 MB acks=11252500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 4.066 s
|
||||||
|
Sustained tick rate: 1229.7 Hz
|
||||||
|
Per-tick mean (wall): 81.3 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 244.0
|
||||||
|
SimulationSystem: 43.2
|
||||||
|
ExportSystem: 35.1
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 1243639
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 1015.22 MB
|
||||||
|
Acks processed: 12500000
|
||||||
|
Alerts seen: 254654
|
||||||
|
|
||||||
|
Memory (RSS at end): 28.8 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=50000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=50000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=35000 EventAsset=10000 ActuatorAsset=5000 total=50000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 50000 (sensor_active= 44082, alerts= 0, act= 5000) | faults= 918 lockouts= 0 | rss= 9.4 MB | tick_mean= 0.0 µs | ingest= 528.0 sim= 211.0 export= 73.0 diag= 0.0 µs | exported=0.41 MB acks=5000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 50000 (sensor_active= 22364, alerts= 118, act= 5000) | faults=462345 lockouts= 0 | rss= 20.1 MB | tick_mean= 1918.9 µs | ingest= 497.0 sim= 94.6 export= 70.9 diag= 0.0 µs | exported=203.46 MB acks=2505000
|
||||||
|
tick= 2000 | entities= 50000 (sensor_active= 22510, alerts= 97, act= 5000) | faults=912440 lockouts= 0 | rss= 27.7 MB | tick_mean= 1922.8 µs | ingest= 496.6 sim= 94.4 export= 71.0 diag= 0.1 µs | exported=609.56 MB acks=7505000
|
||||||
|
tick= 3000 | entities= 50000 (sensor_active= 22512, alerts= 90, act= 5000) | faults=1361728 lockouts= 0 | rss= 35.3 MB | tick_mean= 1924.0 µs | ingest= 497.0 sim= 94.7 export= 71.0 diag= 0.1 µs | exported=1015.66 MB acks=12505000
|
||||||
|
tick= 4000 | entities= 50000 (sensor_active= 22519, alerts= 98, act= 5000) | faults=1812084 lockouts= 0 | rss= 43.0 MB | tick_mean= 1922.6 µs | ingest= 496.6 sim= 94.5 export= 70.8 diag= 0.1 µs | exported=1421.74 MB acks=17505000
|
||||||
|
tick= 5000 | entities= 50000 (sensor_active= 22355, alerts= 101, act= 5000) | faults=2261407 lockouts= 0 | rss= 50.6 MB | tick_mean= 1921.7 µs | ingest= 496.7 sim= 94.5 export= 70.9 diag= 0.1 µs | exported=1827.82 MB acks=22505000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 9.617 s
|
||||||
|
Sustained tick rate: 519.9 Hz
|
||||||
|
Per-tick mean (wall): 192.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 496.0
|
||||||
|
SimulationSystem: 94.5
|
||||||
|
ExportSystem: 70.8
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 2486121
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 2030.46 MB
|
||||||
|
Acks processed: 25000000
|
||||||
|
Alerts seen: 511654
|
||||||
|
|
||||||
|
Memory (RSS at end): 54.3 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=75000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=75000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=52500 EventAsset=15000 ActuatorAsset=7500 total=75000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 75000 (sensor_active= 66146, alerts= 0, act= 7500) | faults= 1354 lockouts= 0 | rss= 13.6 MB | tick_mean= 0.0 µs | ingest= 713.0 sim= 383.0 export= 112.0 diag= 0.0 µs | exported=0.61 MB acks=7500
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 75000 (sensor_active= 33877, alerts= 142, act= 7500) | faults=693165 lockouts= 0 | rss= 28.7 MB | tick_mean= 3016.1 µs | ingest= 735.8 sim= 156.6 export= 110.8 diag= 0.0 µs | exported=305.18 MB acks=3757500
|
||||||
|
tick= 2000 | entities= 75000 (sensor_active= 33696, alerts= 166, act= 7500) | faults=1367793 lockouts= 0 | rss= 40.1 MB | tick_mean= 3021.4 µs | ingest= 735.8 sim= 156.7 export= 110.8 diag= 0.1 µs | exported=914.34 MB acks=11257500
|
||||||
|
tick= 3000 | entities= 75000 (sensor_active= 33889, alerts= 159, act= 7500) | faults=2042643 lockouts= 0 | rss= 51.5 MB | tick_mean= 3024.8 µs | ingest= 736.4 sim= 156.9 export= 110.8 diag= 0.1 µs | exported=1523.51 MB acks=18757500
|
||||||
|
tick= 4000 | entities= 75000 (sensor_active= 33657, alerts= 166, act= 7500) | faults=2717674 lockouts= 0 | rss= 63.0 MB | tick_mean= 3022.6 µs | ingest= 735.3 sim= 156.9 export= 110.8 diag= 0.2 µs | exported=2132.66 MB acks=26257500
|
||||||
|
tick= 5000 | entities= 75000 (sensor_active= 33573, alerts= 155, act= 7500) | faults=3393495 lockouts= 0 | rss= 74.4 MB | tick_mean= 3021.8 µs | ingest= 735.2 sim= 156.5 export= 110.8 diag= 0.2 µs | exported=2741.79 MB acks=33757500
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 15.118 s
|
||||||
|
Sustained tick rate: 330.7 Hz
|
||||||
|
Per-tick mean (wall): 302.3 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 736.2
|
||||||
|
SimulationSystem: 156.6
|
||||||
|
ExportSystem: 110.7
|
||||||
|
DiagnosticsSystem: 0.3
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 3730093
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 3045.74 MB
|
||||||
|
Acks processed: 37500000
|
||||||
|
Alerts seen: 773395
|
||||||
|
|
||||||
|
Memory (RSS at end): 80.1 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=100000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=100000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=70000 EventAsset=20000 ActuatorAsset=10000 total=100000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 100000 (sensor_active= 88228, alerts= 0, act=10000) | faults= 1772 lockouts= 0 | rss= 16.3 MB | tick_mean= 0.0 µs | ingest= 948.0 sim= 607.0 export= 157.0 diag= 0.0 µs | exported=0.81 MB acks=10000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 100000 (sensor_active= 45396, alerts= 218, act=10000) | faults=924085 lockouts= 0 | rss= 36.7 MB | tick_mean= 4126.0 µs | ingest= 986.9 sim= 218.2 export= 150.2 diag= 0.0 µs | exported=406.92 MB acks=5010000
|
||||||
|
tick= 2000 | entities= 100000 (sensor_active= 44998, alerts= 212, act=10000) | faults=1823730 lockouts= 0 | rss= 51.9 MB | tick_mean= 4197.8 µs | ingest= 987.7 sim= 236.6 export= 152.8 diag= 0.1 µs | exported=1219.14 MB acks=15010000
|
||||||
|
tick= 3000 | entities= 100000 (sensor_active= 45132, alerts= 187, act=10000) | faults=2723608 lockouts= 0 | rss= 67.2 MB | tick_mean= 4132.4 µs | ingest= 986.1 sim= 217.8 export= 150.1 diag= 0.1 µs | exported=2031.31 MB acks=25010000
|
||||||
|
tick= 4000 | entities= 100000 (sensor_active= 45039, alerts= 209, act=10000) | faults=3624295 lockouts= 0 | rss= 82.4 MB | tick_mean= 4132.1 µs | ingest= 986.5 sim= 217.8 export= 150.1 diag= 0.1 µs | exported=2843.48 MB acks=35010000
|
||||||
|
tick= 5000 | entities= 100000 (sensor_active= 45069, alerts= 187, act=10000) | faults=4525217 lockouts= 0 | rss= 97.7 MB | tick_mean= 4132.9 µs | ingest= 985.3 sim= 217.1 export= 150.0 diag= 0.1 µs | exported=3655.69 MB acks=45010000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 20.732 s
|
||||||
|
Sustained tick rate: 241.2 Hz
|
||||||
|
Per-tick mean (wall): 413.0 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 985.7
|
||||||
|
SimulationSystem: 217.2
|
||||||
|
ExportSystem: 150.1
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 4974449
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 4060.97 MB
|
||||||
|
Acks processed: 50000000
|
||||||
|
Alerts seen: 1029861
|
||||||
|
|
||||||
|
Memory (RSS at end): 105.3 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=150000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=150000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=105000 EventAsset=30000 ActuatorAsset=15000 total=150000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 150000 (sensor_active=132379, alerts= 0, act=15000) | faults= 2621 lockouts= 0 | rss= 24.5 MB | tick_mean= 0.0 µs | ingest=1444.0 sim= 884.0 export= 251.0 diag= 0.0 µs | exported=1.22 MB acks=15000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 150000 (sensor_active= 67721, alerts= 306, act=15000) | faults=1385323 lockouts= 0 | rss= 54.3 MB | tick_mean= 6453.6 µs | ingest=1517.1 sim= 381.6 export= 226.7 diag= 0.0 µs | exported=610.34 MB acks=7515000
|
||||||
|
tick= 2000 | entities= 150000 (sensor_active= 67238, alerts= 279, act=15000) | faults=2736064 lockouts= 0 | rss= 77.2 MB | tick_mean= 6469.3 µs | ingest=1517.2 sim= 381.6 export= 226.8 diag= 0.1 µs | exported=1828.57 MB acks=22515000
|
||||||
|
tick= 3000 | entities= 150000 (sensor_active= 67728, alerts= 317, act=15000) | faults=4087020 lockouts= 0 | rss= 100.1 MB | tick_mean= 6473.9 µs | ingest=1519.6 sim= 382.4 export= 227.0 diag= 0.1 µs | exported=3046.87 MB acks=37515000
|
||||||
|
tick= 4000 | entities= 150000 (sensor_active= 67533, alerts= 320, act=15000) | faults=5437256 lockouts= 0 | rss= 123.0 MB | tick_mean= 6470.4 µs | ingest=1518.3 sim= 381.8 export= 226.7 diag= 0.1 µs | exported=4265.17 MB acks=52515000
|
||||||
|
tick= 5000 | entities= 150000 (sensor_active= 67700, alerts= 323, act=15000) | faults=6786973 lockouts= 0 | rss= 145.8 MB | tick_mean= 6470.2 µs | ingest=1518.6 sim= 382.0 export= 226.7 diag= 0.1 µs | exported=5483.48 MB acks=67515000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 32.355 s
|
||||||
|
Sustained tick rate: 154.5 Hz
|
||||||
|
Per-tick mean (wall): 646.7 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 1517.3
|
||||||
|
SimulationSystem: 381.4
|
||||||
|
ExportSystem: 226.6
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 7460636
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 6091.41 MB
|
||||||
|
Acks processed: 75000000
|
||||||
|
Alerts seen: 1538845
|
||||||
|
|
||||||
|
Memory (RSS at end): 157.2 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
=== entities=200000 ===
|
||||||
|
ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
entities=200000 | ticks=5000 | warmup=500 | fault_prob=2.0%
|
||||||
|
[spawn] SensorAsset=140000 EventAsset=40000 ActuatorAsset=20000 total=200000
|
||||||
|
[warmup] running 500 ticks...
|
||||||
|
tick= 0 | entities= 200000 (sensor_active=176493, alerts= 0, act=20000) | faults= 3507 lockouts= 0 | rss= 30.0 MB | tick_mean= 0.0 µs | ingest=1907.0 sim=1336.0 export= 349.0 diag= 0.0 µs | exported=1.62 MB acks=20000
|
||||||
|
[warmup] done — starting measurement (5000 ticks)
|
||||||
|
tick= 1000 | entities= 200000 (sensor_active= 90145, alerts= 405, act=20000) | faults=1847083 lockouts= 0 | rss= 69.5 MB | tick_mean= 8788.2 µs | ingest=2023.3 sim= 582.9 export= 300.9 diag= 0.0 µs | exported=813.81 MB acks=10020000
|
||||||
|
tick= 2000 | entities= 200000 (sensor_active= 90392, alerts= 396, act=20000) | faults=3647521 lockouts= 0 | rss= 100.0 MB | tick_mean= 8805.3 µs | ingest=2023.3 sim= 582.9 export= 300.5 diag= 0.1 µs | exported=2438.20 MB acks=30020000
|
||||||
|
tick= 3000 | entities= 200000 (sensor_active= 90372, alerts= 408, act=20000) | faults=5447700 lockouts= 0 | rss= 130.5 MB | tick_mean= 8805.5 µs | ingest=2023.7 sim= 582.7 export= 300.4 diag= 0.1 µs | exported=4062.57 MB acks=50020000
|
||||||
|
tick= 4000 | entities= 200000 (sensor_active= 89452, alerts= 444, act=20000) | faults=7247668 lockouts= 0 | rss= 161.1 MB | tick_mean= 8808.2 µs | ingest=2024.8 sim= 583.4 export= 300.7 diag= 0.2 µs | exported=5686.94 MB acks=70020000
|
||||||
|
tick= 5000 | entities= 200000 (sensor_active= 89914, alerts= 429, act=20000) | faults=9047286 lockouts= 0 | rss= 191.6 MB | tick_mean= 8804.6 µs | ingest=2022.3 sim= 582.4 export= 300.7 diag= 0.1 µs | exported=7311.36 MB acks=90020000
|
||||||
|
|
||||||
|
── Final Summary ──────────────────────────────────────
|
||||||
|
Total ticks (measurement): 5000
|
||||||
|
Total wall time: 44.034 s
|
||||||
|
Sustained tick rate: 113.5 Hz
|
||||||
|
Per-tick mean (wall): 880.6 µs
|
||||||
|
|
||||||
|
Per-system mean (µs):
|
||||||
|
IngestSystem: 2022.7
|
||||||
|
SimulationSystem: 582.0
|
||||||
|
ExportSystem: 300.7
|
||||||
|
DiagnosticsSystem: 0.2
|
||||||
|
|
||||||
|
Fault injection:
|
||||||
|
Total sensor faults: 9946420
|
||||||
|
Total actuator lockouts: 0
|
||||||
|
|
||||||
|
Export totals:
|
||||||
|
Bytes exported: 8121.94 MB
|
||||||
|
Acks processed: 100000000
|
||||||
|
Alerts seen: 2059136
|
||||||
|
|
||||||
|
Memory (RSS at end): 206.8 MB
|
||||||
|
────────────────────────────────────────────────────────
|
||||||
22
results_rpi/sysinfo.txt
Normal file
22
results_rpi/sysinfo.txt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
=== System Information ===
|
||||||
|
Date: 2026-04-21 01:12:15 UTC
|
||||||
|
OS: Linux 6.12.75+rpt-rpi-2712
|
||||||
|
Arch: aarch64
|
||||||
|
Target CPU: cortex-a76
|
||||||
|
Rust: rustc 1.95.0 (59807616e 2026-04-14)
|
||||||
|
Cargo: cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||||
|
|
||||||
|
=== CPU Info ===
|
||||||
|
CPU implementer : 0x41
|
||||||
|
CPU part : 0xd0b
|
||||||
|
Revision : c04180
|
||||||
|
|
||||||
|
=== Memory ===
|
||||||
|
MemTotal: 4146896 kB
|
||||||
|
MemAvailable: 3883072 kB
|
||||||
|
|
||||||
|
=== CPU Governor ===
|
||||||
|
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor: performance
|
||||||
|
|
||||||
|
=== Isolated cores ===
|
||||||
|
|
||||||
265
run_benchmark.sh
Executable file
265
run_benchmark.sh
Executable file
@@ -0,0 +1,265 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================
|
||||||
|
# ECS Digital Twin Benchmark — build + full sweep
|
||||||
|
# TRANSIT lab / UQAC
|
||||||
|
#
|
||||||
|
# Detects the host CPU, builds with native hardware optimizations,
|
||||||
|
# then runs the full entity sweep for the paper tables.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# chmod +x run_benchmark.sh
|
||||||
|
# ./run_benchmark.sh
|
||||||
|
#
|
||||||
|
# Output:
|
||||||
|
# results/summary.txt — human-readable full log
|
||||||
|
# results/csv/ — one CSV per entity count (for paper tables)
|
||||||
|
# results/final_table.csv — aggregated table ready for LaTeX
|
||||||
|
# =============================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Paths ─────────────────────────────────────────────────────
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
RESULTS_DIR="${SCRIPT_DIR}/results"
|
||||||
|
CSV_DIR="${RESULTS_DIR}/csv"
|
||||||
|
BINARY="${SCRIPT_DIR}/target/release/ecs_dt_benchmark"
|
||||||
|
|
||||||
|
mkdir -p "${RESULTS_DIR}" "${CSV_DIR}"
|
||||||
|
|
||||||
|
# ── Benchmark parameters ───────────────────────────────────────
|
||||||
|
ENTITY_COUNTS=(10000 25000 50000 75000 100000 150000 200000)
|
||||||
|
TICKS=5000
|
||||||
|
WARMUP=500
|
||||||
|
FAULT_PROB=0.02 # 2 % per tick per entity
|
||||||
|
SEED=17446744073709551615
|
||||||
|
|
||||||
|
# ── Platform detection ────────────────────────────────────────
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
OS="$(uname -s)"
|
||||||
|
|
||||||
|
echo "============================================================"
|
||||||
|
echo " ECS Digital Twin Benchmark — TRANSIT lab / UQAC"
|
||||||
|
echo " Platform: ${OS} / ${ARCH}"
|
||||||
|
echo "============================================================"
|
||||||
|
|
||||||
|
# Detect the best target-cpu flag for this machine.
|
||||||
|
detect_target_cpu() {
|
||||||
|
case "${ARCH}" in
|
||||||
|
aarch64)
|
||||||
|
# On RPi 5 (Cortex-A76) /proc/cpuinfo lists "CPU part : 0xd0b"
|
||||||
|
# On Apple M-series (native aarch64 via Rosetta or native build)
|
||||||
|
# uname gives arm64 on macOS, aarch64 on Linux.
|
||||||
|
if [[ "${OS}" == "Darwin" ]]; then
|
||||||
|
# Apple Silicon — the toolchain knows the exact µarch.
|
||||||
|
echo "apple-m1"
|
||||||
|
elif grep -q "Cortex-A76" /proc/cpuinfo 2>/dev/null || \
|
||||||
|
grep -q "0xd0b" /proc/cpuinfo 2>/dev/null; then
|
||||||
|
echo "cortex-a76" # RPi 5
|
||||||
|
elif grep -q "Cortex-A72" /proc/cpuinfo 2>/dev/null || \
|
||||||
|
grep -q "0xd08" /proc/cpuinfo 2>/dev/null; then
|
||||||
|
echo "cortex-a72" # RPi 4
|
||||||
|
else
|
||||||
|
echo "native" # fall back: let LLVM auto-detect
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
echo "native" # covers Ryzen, Intel, any x86-64
|
||||||
|
;;
|
||||||
|
arm64)
|
||||||
|
# macOS reports arm64
|
||||||
|
echo "apple-m1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "native"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET_CPU="$(detect_target_cpu)"
|
||||||
|
echo " Target CPU flag: -C target-cpu=${TARGET_CPU}"
|
||||||
|
|
||||||
|
# ── CPU isolation advice ───────────────────────────────────────
|
||||||
|
# On Linux, pin to an isolated core if isolcpus was set at boot.
|
||||||
|
# On the RPi 5 for the paper we recommend:
|
||||||
|
# sudo systemctl isolate multi-user.target (drop GUI)
|
||||||
|
# TASKSET="taskset -c 0"
|
||||||
|
# We auto-detect isolated cores from the kernel cmdline.
|
||||||
|
TASKSET=""
|
||||||
|
if [[ "${OS}" == "Linux" ]]; then
|
||||||
|
ISOLATED=""
|
||||||
|
if [[ -r /sys/devices/system/cpu/isolated ]]; then
|
||||||
|
ISOLATED="$(cat /sys/devices/system/cpu/isolated)"
|
||||||
|
fi
|
||||||
|
if [[ -n "${ISOLATED}" ]]; then
|
||||||
|
# Use the first isolated core.
|
||||||
|
FIRST_CORE="${ISOLATED%%[-,]*}"
|
||||||
|
TASKSET="taskset -c ${FIRST_CORE}"
|
||||||
|
echo " Isolated cores: ${ISOLATED} → pinning to core ${FIRST_CORE}"
|
||||||
|
else
|
||||||
|
echo " No isolated cores detected — running unpinned."
|
||||||
|
echo " Tip: add isolcpus=2 nohz_full=2 rcu_nocbs=2 to /boot/cmdline.txt"
|
||||||
|
echo " for more stable single-core measurements on RPi 5."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Build ──────────────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "── Building (release + native optimizations) ────────────"
|
||||||
|
|
||||||
|
RUSTFLAGS="-C target-cpu=${TARGET_CPU} -C opt-level=3" \
|
||||||
|
cargo build --release 2>&1 | tail -5
|
||||||
|
|
||||||
|
echo " Binary: ${BINARY}"
|
||||||
|
echo " Size: $(du -sh "${BINARY}" | cut -f1)"
|
||||||
|
|
||||||
|
# ── System info snapshot ───────────────────────────────────────
|
||||||
|
SYSINFO_FILE="${RESULTS_DIR}/sysinfo.txt"
|
||||||
|
{
|
||||||
|
echo "=== System Information ==="
|
||||||
|
echo "Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||||||
|
echo "OS: ${OS} $(uname -r 2>/dev/null || true)"
|
||||||
|
echo "Arch: ${ARCH}"
|
||||||
|
echo "Target CPU: ${TARGET_CPU}"
|
||||||
|
echo "Rust: $(rustc --version)"
|
||||||
|
echo "Cargo: $(cargo --version)"
|
||||||
|
echo ""
|
||||||
|
if [[ "${OS}" == "Linux" ]]; then
|
||||||
|
echo "=== CPU Info ==="
|
||||||
|
grep -E "^(model name|Hardware|CPU part|CPU implementer|Revision)" \
|
||||||
|
/proc/cpuinfo 2>/dev/null | sort -u || true
|
||||||
|
echo ""
|
||||||
|
echo "=== Memory ==="
|
||||||
|
grep -E "^(MemTotal|MemAvailable)" /proc/meminfo 2>/dev/null || true
|
||||||
|
echo ""
|
||||||
|
echo "=== CPU Governor ==="
|
||||||
|
for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
|
||||||
|
[[ -r "$f" ]] && echo " $f: $(cat "$f")" && break
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
echo "=== Isolated cores ==="
|
||||||
|
cat /sys/devices/system/cpu/isolated 2>/dev/null || echo " none"
|
||||||
|
elif [[ "${OS}" == "Darwin" ]]; then
|
||||||
|
sysctl -n machdep.cpu.brand_string 2>/dev/null || true
|
||||||
|
sysctl -n hw.memsize 2>/dev/null | \
|
||||||
|
awk '{printf "Memory: %.1f GB\n", $1/1073741824}' || true
|
||||||
|
fi
|
||||||
|
} | tee "${SYSINFO_FILE}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── CSV header ────────────────────────────────────────────────
|
||||||
|
FINAL_CSV="${RESULTS_DIR}/final_table.csv"
|
||||||
|
echo "entities,ticks,wall_s,hz,per_tick_us,ingest_us,sim_us,export_us,diag_us,\
|
||||||
|
sensor_faults,actuator_lockouts,exported_mb,acks,alerts,rss_mb" \
|
||||||
|
> "${FINAL_CSV}"
|
||||||
|
|
||||||
|
# ── Sweep ─────────────────────────────────────────────────────
|
||||||
|
echo "── Running entity sweep ─────────────────────────────────"
|
||||||
|
echo " Counts: ${ENTITY_COUNTS[*]}"
|
||||||
|
echo " Ticks: ${TICKS} Warmup: ${WARMUP} Fault: ${FAULT_PROB}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
SUMMARY_FILE="${RESULTS_DIR}/summary.txt"
|
||||||
|
echo "ECS DT Benchmark Sweep — $(date -u)" > "${SUMMARY_FILE}"
|
||||||
|
cat "${SYSINFO_FILE}" >> "${SUMMARY_FILE}"
|
||||||
|
echo "" >> "${SUMMARY_FILE}"
|
||||||
|
|
||||||
|
for N in "${ENTITY_COUNTS[@]}"; do
|
||||||
|
echo "── entities=${N} ─────────────────────────────────────"
|
||||||
|
|
||||||
|
RAW_FILE="${RESULTS_DIR}/raw_${N}.txt"
|
||||||
|
|
||||||
|
# Run benchmark, tee to file and stdout.
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
${TASKSET} "${BINARY}" \
|
||||||
|
--entities "${N}" \
|
||||||
|
--ticks "${TICKS}" \
|
||||||
|
--seed "${SEED}" \
|
||||||
|
--fault-prob "${FAULT_PROB}" \
|
||||||
|
2>&1 | tee "${RAW_FILE}"
|
||||||
|
|
||||||
|
echo "" >> "${SUMMARY_FILE}"
|
||||||
|
echo "=== entities=${N} ===" >> "${SUMMARY_FILE}"
|
||||||
|
cat "${RAW_FILE}" >> "${SUMMARY_FILE}"
|
||||||
|
|
||||||
|
# ── Parse the Final Summary block from the binary output ──
|
||||||
|
# Extract values using grep + awk on the known output format.
|
||||||
|
parse() {
|
||||||
|
grep -m1 "$1" "${RAW_FILE}" | awk '{print $NF}'
|
||||||
|
}
|
||||||
|
|
||||||
|
WALL_S=$(grep "Total wall time" "${RAW_FILE}" | awk '{print $NF}' | tr -d 's')
|
||||||
|
HZ=$(grep "Sustained tick rate" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
PTW=$(grep "Per-tick mean" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
INGEST=$(grep "IngestSystem:" "${RAW_FILE}" | tail -1 | awk '{print $NF}')
|
||||||
|
SIM=$(grep "SimulationSystem:" "${RAW_FILE}" | tail -1 | awk '{print $NF}')
|
||||||
|
EXPORT=$(grep "ExportSystem:" "${RAW_FILE}" | tail -1 | awk '{print $NF}')
|
||||||
|
DIAGSYS=$(grep "DiagnosticsSystem:" "${RAW_FILE}" | tail -1 | awk '{print $NF}')
|
||||||
|
FAULTS=$(grep "Total sensor faults:" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
LOCKOUTS=$(grep "Total actuator lockouts" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
EXPMT=$(grep "Bytes exported:" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
ACKS=$(grep "Acks processed:" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
ALTS=$(grep "Alerts seen:" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
RSS=$(grep "Memory (RSS" "${RAW_FILE}" | awk '{print $NF}')
|
||||||
|
|
||||||
|
# Remove trailing units that awk picked up (MB, Hz, µs, s).
|
||||||
|
strip() { echo "$1" | tr -d 'MBHzµs '; }
|
||||||
|
|
||||||
|
echo "${N},${TICKS},$(strip "$WALL_S"),$(strip "$HZ"),$(strip "$PTW"),\
|
||||||
|
$(strip "$INGEST"),$(strip "$SIM"),$(strip "$EXPORT"),$(strip "$DIAGSYS"),\
|
||||||
|
$(strip "$FAULTS"),$(strip "$LOCKOUTS"),$(strip "$EXPMT"),\
|
||||||
|
$(strip "$ACKS"),$(strip "$ALTS"),$(strip "$RSS")" \
|
||||||
|
>> "${FINAL_CSV}"
|
||||||
|
|
||||||
|
# Per-entity CSV for detailed analysis.
|
||||||
|
cat "${RAW_FILE}" > "${CSV_DIR}/entities_${N}.txt"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
# ── Pretty-print final table ──────────────────────────────────
|
||||||
|
echo "============================================================"
|
||||||
|
echo " Final Results Table"
|
||||||
|
echo "============================================================"
|
||||||
|
echo ""
|
||||||
|
printf "%-10s %-8s %-10s %-12s %-12s %-10s %-10s\n" \
|
||||||
|
"Entities" "Hz" "Tick(µs)" "Ingest(µs)" "Sim(µs)" "Export(µs)" "RSS(MB)"
|
||||||
|
printf "%-10s %-8s %-10s %-12s %-12s %-10s %-10s\n" \
|
||||||
|
"--------" "------" "---------" "----------" "--------" "----------" "-------"
|
||||||
|
|
||||||
|
tail -n +2 "${FINAL_CSV}" | while IFS=',' read -r \
|
||||||
|
entities ticks wall hz ptw ingest sim export diag \
|
||||||
|
faults lockouts expmt acks alts rss; do
|
||||||
|
printf "%-10s %-8s %-10s %-12s %-12s %-10s %-10s\n" \
|
||||||
|
"${entities}" "${hz}" "${ptw}" "${ingest}" "${sim}" "${export}" "${rss}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "── Output files ─────────────────────────────────────────"
|
||||||
|
echo " ${SUMMARY_FILE}"
|
||||||
|
echo " ${FINAL_CSV}"
|
||||||
|
echo " ${CSV_DIR}/"
|
||||||
|
echo ""
|
||||||
|
echo "── LaTeX snippet for paper Table 2 ─────────────────────"
|
||||||
|
echo '\begin{table}[h]'
|
||||||
|
echo '\caption{ECS DT Runtime: Memory and Throughput Scaling (RPi~5, single core)}'
|
||||||
|
echo '\centering\renewcommand{\arraystretch}{1.25}'
|
||||||
|
echo '\begin{tabular}{@{}rrrrr@{}}'
|
||||||
|
echo '\toprule'
|
||||||
|
echo '\textbf{Entities} & \textbf{RSS (MB)} & \textbf{Tick rate (Hz)} &'
|
||||||
|
echo '\textbf{Per-tick ($\mu$s)} & \textbf{Sim system ($\mu$s)} \\'
|
||||||
|
echo '\midrule'
|
||||||
|
|
||||||
|
tail -n +2 "${FINAL_CSV}" | while IFS=',' read -r \
|
||||||
|
entities ticks wall hz ptw ingest sim export diag \
|
||||||
|
faults lockouts expmt acks alts rss; do
|
||||||
|
printf '%s & %s & %s & %s & %s \\\\\n' \
|
||||||
|
"$(printf '%s' "${entities}" | sed 's/000$/k/' | sed 's/00k$/00k/')" \
|
||||||
|
"${rss}" "${hz}" "${ptw}" "${sim}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo '\bottomrule'
|
||||||
|
echo '\end{tabular}'
|
||||||
|
echo '\end{table}'
|
||||||
|
echo ""
|
||||||
|
echo "Done. $(date -u)"
|
||||||
935
src/main.rs
Normal file
935
src/main.rs
Normal file
@@ -0,0 +1,935 @@
|
|||||||
|
/// ============================================================
|
||||||
|
/// ECS Digital Twin Benchmark — TRANSIT lab / UQAC
|
||||||
|
/// Target paper: "ECS as a Natural Runtime Substrate for
|
||||||
|
/// Industrial Digital Twins" (IEEE SWC 2026)
|
||||||
|
///
|
||||||
|
/// Three asset archetypes mirror the three DT data tiers:
|
||||||
|
/// Tier 1 — SensorAsset (70 %): ephemeral high-frequency readings
|
||||||
|
/// Tier 2 — EventAsset (20 %): threshold / fault events
|
||||||
|
/// Tier 3 — ActuatorAsset (10 %): commanded state with ack tracking
|
||||||
|
///
|
||||||
|
/// Five systems run per tick in a fixed schedule:
|
||||||
|
/// 1. FaultInjectionSystem — drives archetype mutations
|
||||||
|
/// 2. IngestSystem — writes fresh sensor / command data
|
||||||
|
/// 3. SimulationSystem — processes state (heaviest, par_iter)
|
||||||
|
/// 4. ExportSystem — read-only shadow-model pass
|
||||||
|
/// 5. DiagnosticsSystem — per-system timing + RSS sampling
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
/// cargo run --release -- --entities 100000 --ticks 5000
|
||||||
|
/// cargo run --release -- --entities 200000 --ticks 2000
|
||||||
|
/// ============================================================
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fs,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
|
use bevy_ecs::prelude::*;
|
||||||
|
use rand::{Rng, SeedableRng};
|
||||||
|
use rand_chacha::ChaCha8Rng;
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// CLI args (no clap dependency — keep compile times short)
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
struct Config {
|
||||||
|
total_entities: usize,
|
||||||
|
ticks: u32,
|
||||||
|
warmup_ticks: u32,
|
||||||
|
rng_seed: u64,
|
||||||
|
fault_probability: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
total_entities: 100_000,
|
||||||
|
ticks: 5_000,
|
||||||
|
warmup_ticks: 500,
|
||||||
|
rng_seed: 0xDEAD_BEEF_CAFE_BABE,
|
||||||
|
fault_probability: 0.02,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_args() -> Config {
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
let mut i = 1;
|
||||||
|
while i < args.len() {
|
||||||
|
match args[i].as_str() {
|
||||||
|
"--entities" => {
|
||||||
|
cfg.total_entities = args[i + 1].parse().expect("bad --entities");
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--ticks" => {
|
||||||
|
cfg.ticks = args[i + 1].parse().expect("bad --ticks");
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--seed" => {
|
||||||
|
cfg.rng_seed = args[i + 1].parse().expect("bad --seed");
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--fault-prob" => {
|
||||||
|
cfg.fault_probability = args[i + 1].parse().expect("bad --fault-prob");
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Enums
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum AssetClass {
|
||||||
|
Sensor,
|
||||||
|
Event,
|
||||||
|
Actuator,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum SensorUnit {
|
||||||
|
Temperature,
|
||||||
|
Vibration,
|
||||||
|
Position,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum AlertSeverity {
|
||||||
|
Warning,
|
||||||
|
Critical,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Components — shared
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Pure identity — every entity carries this, no behaviour.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct AssetId {
|
||||||
|
id: u32,
|
||||||
|
class: AssetClass,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Components — Tier 1 SensorAsset
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Written by IngestSystem, read by SimulationSystem.
|
||||||
|
/// Removed / re-added by FaultInjectionSystem to model sensor dropout.
|
||||||
|
/// Its *absence* is the fault representation — no null fields, no enums.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct RawSensorData {
|
||||||
|
value: f32,
|
||||||
|
timestamp_us: u64,
|
||||||
|
sequence_number: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Written by SimulationSystem, read by ExportSystem.
|
||||||
|
/// Never removed — persists as the last-known-good state even during dropout.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct ProcessedState {
|
||||||
|
filtered_value: f32,
|
||||||
|
last_updated_tick: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Static config — written once at spawn, never mutated.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct SensorMetadata {
|
||||||
|
sample_rate_hz: f32,
|
||||||
|
unit: SensorUnit,
|
||||||
|
calibration_offset: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Components — Tier 2 EventAsset
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Static threshold config — written once at spawn.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct ThresholdConfig {
|
||||||
|
upper_bound: f32,
|
||||||
|
lower_bound: f32,
|
||||||
|
consecutive_violations_required: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutable per-tick state tracked by SimulationSystem.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct ThresholdState {
|
||||||
|
current_violation_count: u8,
|
||||||
|
last_violation_tick: u32,
|
||||||
|
is_alerting: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Added by SimulationSystem when threshold is breached.
|
||||||
|
/// Removed when condition clears. Presence = active alert.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct AlertEvent {
|
||||||
|
severity: AlertSeverity,
|
||||||
|
triggered_at_tick: u32,
|
||||||
|
asset_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Components — Tier 3 ActuatorAsset
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Written by SimulationSystem each tick (lerp toward setpoint).
|
||||||
|
#[derive(Component)]
|
||||||
|
struct ActuatorState {
|
||||||
|
current_setpoint: f32,
|
||||||
|
actual_position: f32,
|
||||||
|
last_command_tick: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Written by IngestSystem (new command arrives).
|
||||||
|
/// Cleared by ExportSystem after ack is read.
|
||||||
|
/// Removed by FaultInjectionSystem when consecutive_failures >= 5.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct CommandBuffer {
|
||||||
|
pending_setpoint: Option<f32>,
|
||||||
|
acknowledged: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Written by SimulationSystem when actuator fails to converge.
|
||||||
|
#[derive(Component)]
|
||||||
|
struct ActuatorHealth {
|
||||||
|
fault_code: Option<u8>,
|
||||||
|
consecutive_failures: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Resources
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Current tick counter — its own resource so systems can take
|
||||||
|
/// Res<CurrentTick> without conflicting with ResMut<TickDiagnostics>.
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
struct CurrentTick(u32);
|
||||||
|
|
||||||
|
/// Per-system timing accumulated across the measurement window.
|
||||||
|
/// Written exclusively by each system that records its own elapsed time,
|
||||||
|
/// and by DiagnosticsSystem which resets and prints the window.
|
||||||
|
/// No system takes both Res<TickDiagnostics> and ResMut<TickDiagnostics>.
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
struct TickDiagnostics {
|
||||||
|
system_elapsed_us: HashMap<&'static str, u64>,
|
||||||
|
accumulated_elapsed_us: HashMap<&'static str, u64>,
|
||||||
|
ticks_in_window: u32,
|
||||||
|
total_tick_elapsed_us: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TickDiagnostics {
|
||||||
|
fn record(&mut self, name: &'static str, elapsed: Duration) {
|
||||||
|
let us = elapsed.as_micros() as u64;
|
||||||
|
self.system_elapsed_us.insert(name, us);
|
||||||
|
*self.accumulated_elapsed_us.entry(name).or_insert(0) += us;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fault injection configuration and deterministic RNG.
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct FaultProfile {
|
||||||
|
fault_probability_per_tick: f32,
|
||||||
|
rng: ChaCha8Rng,
|
||||||
|
total_faults_injected: u32,
|
||||||
|
total_actuator_lockouts: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FaultProfile {
|
||||||
|
fn new(seed: u64, probability: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
fault_probability_per_tick: probability,
|
||||||
|
rng: ChaCha8Rng::seed_from_u64(seed),
|
||||||
|
total_faults_injected: 0,
|
||||||
|
total_actuator_lockouts: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Monotonically increasing simulated clock in microseconds.
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
struct SimClock {
|
||||||
|
current_us: u64,
|
||||||
|
step_us: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accumulates total "exported" bytes for throughput reporting.
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
struct ExportCounter {
|
||||||
|
total_bytes: u64,
|
||||||
|
total_alerts_seen: u32,
|
||||||
|
total_acks_processed: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// System labels
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
enum DtSystemSet {
|
||||||
|
Fault,
|
||||||
|
Ingest,
|
||||||
|
Simulate,
|
||||||
|
Export,
|
||||||
|
Diagnostics,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// System 1 — FaultInjectionSystem
|
||||||
|
//
|
||||||
|
// Drives all archetype mutations.
|
||||||
|
// Runs BEFORE Ingest and Simulate so they see the updated archetypes.
|
||||||
|
//
|
||||||
|
// SensorAsset with RawSensorData → roll to REMOVE it (dropout)
|
||||||
|
// SensorAsset without RawSensorData → roll to RE-ADD it (recovery)
|
||||||
|
// ActuatorAsset with consecutive_failures >= 5 → remove CommandBuffer
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn fault_injection_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut profile: ResMut<FaultProfile>,
|
||||||
|
active_sensors: Query<
|
||||||
|
Entity,
|
||||||
|
(With<RawSensorData>, With<SensorMetadata>),
|
||||||
|
>,
|
||||||
|
inactive_sensors: Query<
|
||||||
|
(Entity, &SensorMetadata),
|
||||||
|
(Without<RawSensorData>, With<ProcessedState>),
|
||||||
|
>,
|
||||||
|
actuators: Query<(Entity, &ActuatorHealth), With<CommandBuffer>>,
|
||||||
|
) {
|
||||||
|
let p = profile.fault_probability_per_tick;
|
||||||
|
|
||||||
|
for entity in active_sensors.iter() {
|
||||||
|
if profile.rng.gen::<f32>() < p {
|
||||||
|
commands.entity(entity).remove::<RawSensorData>();
|
||||||
|
profile.total_faults_injected += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, meta) in inactive_sensors.iter() {
|
||||||
|
if profile.rng.gen::<f32>() < p {
|
||||||
|
commands.entity(entity).insert(RawSensorData {
|
||||||
|
value: meta.calibration_offset,
|
||||||
|
timestamp_us: 0,
|
||||||
|
sequence_number: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, health) in actuators.iter() {
|
||||||
|
if health.consecutive_failures >= 5 {
|
||||||
|
commands.entity(entity).remove::<CommandBuffer>();
|
||||||
|
profile.total_actuator_lockouts += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// System 2 — IngestSystem
|
||||||
|
//
|
||||||
|
// Write set : RawSensorData, CommandBuffer
|
||||||
|
// Read set : SensorMetadata, SimClock, CurrentTick
|
||||||
|
// Disjoint from ExportSystem write set → Bevy can schedule in parallel.
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn ingest_system(
|
||||||
|
mut sensors: Query<(&SensorMetadata, &mut RawSensorData)>,
|
||||||
|
mut actuators: Query<&mut CommandBuffer>,
|
||||||
|
clock: Res<SimClock>,
|
||||||
|
mut profile: ResMut<FaultProfile>,
|
||||||
|
mut diag: ResMut<TickDiagnostics>,
|
||||||
|
) {
|
||||||
|
let t0 = Instant::now();
|
||||||
|
|
||||||
|
for (meta, mut raw) in sensors.iter_mut() {
|
||||||
|
raw.sequence_number = raw.sequence_number.wrapping_add(1);
|
||||||
|
let phase = raw.sequence_number as f32 / meta.sample_rate_hz;
|
||||||
|
raw.value = (phase * std::f32::consts::TAU).sin() + meta.calibration_offset;
|
||||||
|
raw.timestamp_us = clock.current_us;
|
||||||
|
}
|
||||||
|
|
||||||
|
let command_probability: f32 = 0.05;
|
||||||
|
for mut buf in actuators.iter_mut() {
|
||||||
|
if profile.rng.gen::<f32>() < command_probability {
|
||||||
|
buf.pending_setpoint = Some(profile.rng.gen_range(-1.0_f32..1.0_f32));
|
||||||
|
buf.acknowledged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diag.record("IngestSystem", t0.elapsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// System 3 — SimulationSystem
|
||||||
|
//
|
||||||
|
// Write set : ProcessedState, ThresholdState, ActuatorState,
|
||||||
|
// ActuatorHealth, Commands (AlertEvent inserts/removes)
|
||||||
|
// Read set : RawSensorData, SensorMetadata, ThresholdConfig,
|
||||||
|
// CommandBuffer, CurrentTick
|
||||||
|
//
|
||||||
|
// Takes Res<CurrentTick> (not TickDiagnostics) to read the tick number,
|
||||||
|
// then ResMut<TickDiagnostics> only to record its elapsed time.
|
||||||
|
// No Res/ResMut conflict.
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn simulation_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
tick_res: Res<CurrentTick>,
|
||||||
|
// Pass (a): only entities WITH RawSensorData are matched.
|
||||||
|
// Dropout entities are skipped automatically by the query filter.
|
||||||
|
mut sensors: Query<(
|
||||||
|
&RawSensorData,
|
||||||
|
&SensorMetadata,
|
||||||
|
&mut ProcessedState,
|
||||||
|
)>,
|
||||||
|
// Pass (b): threshold evaluation — also requires RawSensorData.
|
||||||
|
mut events: Query<(
|
||||||
|
Entity,
|
||||||
|
&AssetId,
|
||||||
|
&RawSensorData,
|
||||||
|
&ThresholdConfig,
|
||||||
|
&mut ThresholdState,
|
||||||
|
Option<&AlertEvent>,
|
||||||
|
)>,
|
||||||
|
// Pass (c): actuator convergence.
|
||||||
|
mut actuators: Query<(
|
||||||
|
&mut ActuatorState,
|
||||||
|
&mut ActuatorHealth,
|
||||||
|
Option<&mut CommandBuffer>,
|
||||||
|
)>,
|
||||||
|
mut diag: ResMut<TickDiagnostics>,
|
||||||
|
) {
|
||||||
|
let t0 = Instant::now();
|
||||||
|
let tick = tick_res.0;
|
||||||
|
let alpha = 0.1_f32;
|
||||||
|
|
||||||
|
// ── (a) Sensor EMA — par_iter_mut, independent per entity ────
|
||||||
|
sensors.par_iter_mut().for_each(|(raw, _meta, mut ps)| {
|
||||||
|
ps.filtered_value =
|
||||||
|
alpha * raw.value + (1.0 - alpha) * ps.filtered_value;
|
||||||
|
ps.last_updated_tick = tick;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── (b) Threshold evaluation ──────────────────────────────────
|
||||||
|
for (entity, id, raw, cfg, mut state, maybe_alert) in events.iter_mut() {
|
||||||
|
let out_of_bounds =
|
||||||
|
raw.value > cfg.upper_bound || raw.value < cfg.lower_bound;
|
||||||
|
|
||||||
|
if out_of_bounds {
|
||||||
|
state.current_violation_count =
|
||||||
|
state.current_violation_count.saturating_add(1);
|
||||||
|
state.last_violation_tick = tick;
|
||||||
|
|
||||||
|
if state.current_violation_count >= cfg.consecutive_violations_required
|
||||||
|
&& maybe_alert.is_none()
|
||||||
|
{
|
||||||
|
let severity = if state.current_violation_count >= 10 {
|
||||||
|
AlertSeverity::Critical
|
||||||
|
} else {
|
||||||
|
AlertSeverity::Warning
|
||||||
|
};
|
||||||
|
commands.entity(entity).insert(AlertEvent {
|
||||||
|
severity,
|
||||||
|
triggered_at_tick: tick,
|
||||||
|
asset_id: id.id,
|
||||||
|
});
|
||||||
|
state.is_alerting = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.current_violation_count = 0;
|
||||||
|
if maybe_alert.is_some() {
|
||||||
|
commands.entity(entity).remove::<AlertEvent>();
|
||||||
|
state.is_alerting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── (c) Actuator convergence ──────────────────────────────────
|
||||||
|
let lerp_rate = 0.1_f32;
|
||||||
|
let tolerance = 0.001_f32;
|
||||||
|
let failure_thresh = 200_u32;
|
||||||
|
|
||||||
|
for (mut state, mut health, maybe_buf) in actuators.iter_mut() {
|
||||||
|
if let Some(mut buf) = maybe_buf {
|
||||||
|
if let Some(setpoint) = buf.pending_setpoint {
|
||||||
|
state.current_setpoint = setpoint;
|
||||||
|
state.last_command_tick = tick;
|
||||||
|
}
|
||||||
|
buf.acknowledged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let delta = state.current_setpoint - state.actual_position;
|
||||||
|
state.actual_position += delta * lerp_rate;
|
||||||
|
|
||||||
|
if delta.abs() < tolerance {
|
||||||
|
health.consecutive_failures = 0;
|
||||||
|
health.fault_code = None;
|
||||||
|
} else if tick.wrapping_sub(state.last_command_tick) > failure_thresh {
|
||||||
|
health.consecutive_failures =
|
||||||
|
health.consecutive_failures.saturating_add(1);
|
||||||
|
health.fault_code = Some(0x01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diag.record("SimulationSystem", t0.elapsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// System 4 — ExportSystem
|
||||||
|
//
|
||||||
|
// Read set : ProcessedState, AlertEvent, ActuatorState, CommandBuffer
|
||||||
|
// Write set : CommandBuffer (ack clear), ExportCounter
|
||||||
|
//
|
||||||
|
// Entity data writes are limited to CommandBuffer.acknowledged/pending_setpoint.
|
||||||
|
// ProcessedState and ActuatorState are read-only, so Bevy can overlap
|
||||||
|
// this system with IngestSystem (which writes RawSensorData only).
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn export_system(
|
||||||
|
processed: Query<&ProcessedState>,
|
||||||
|
alerts: Query<&AlertEvent>,
|
||||||
|
// Single query covering all actuator data — avoids the B0001 conflict
|
||||||
|
// that arises from having separate Res<CommandBuffer> and
|
||||||
|
// ResMut<CommandBuffer> queries in the same system.
|
||||||
|
mut actuators: Query<(&ActuatorState, &mut CommandBuffer)>,
|
||||||
|
// Actuator entities that have lost their CommandBuffer (locked out).
|
||||||
|
locked_actuators: Query<&ActuatorState, Without<CommandBuffer>>,
|
||||||
|
mut counter: ResMut<ExportCounter>,
|
||||||
|
mut diag: ResMut<TickDiagnostics>,
|
||||||
|
) {
|
||||||
|
let t0 = Instant::now();
|
||||||
|
let mut exported: u64 = 0;
|
||||||
|
|
||||||
|
// Shadow export for all entities with ProcessedState.
|
||||||
|
for ps in processed.iter() {
|
||||||
|
let _ = std::hint::black_box((ps.filtered_value, ps.last_updated_tick));
|
||||||
|
exported += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert export.
|
||||||
|
for alert in alerts.iter() {
|
||||||
|
let _ = std::hint::black_box((alert.severity, alert.triggered_at_tick));
|
||||||
|
exported += 8;
|
||||||
|
counter.total_alerts_seen += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actuator shadow export + ack processing in a single pass.
|
||||||
|
for (state, mut buf) in actuators.iter_mut() {
|
||||||
|
let _ = std::hint::black_box(state.actual_position);
|
||||||
|
exported += 4;
|
||||||
|
if buf.acknowledged {
|
||||||
|
counter.total_acks_processed += 1;
|
||||||
|
exported += 1;
|
||||||
|
// Clear ack post-export — Tier 3 round-trip complete.
|
||||||
|
buf.pending_setpoint = None;
|
||||||
|
buf.acknowledged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locked-out actuators (no CommandBuffer) still get shadow-exported.
|
||||||
|
for state in locked_actuators.iter() {
|
||||||
|
let _ = std::hint::black_box(state.actual_position);
|
||||||
|
exported += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter.total_bytes += exported;
|
||||||
|
diag.record("ExportSystem", t0.elapsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// System 5 — DiagnosticsSystem
|
||||||
|
//
|
||||||
|
// Runs last. Every 1 000 ticks prints a structured summary line,
|
||||||
|
// then resets the accumulation window.
|
||||||
|
//
|
||||||
|
// Takes ResMut<TickDiagnostics> only — no Res<TickDiagnostics>.
|
||||||
|
// Takes Res<CurrentTick> for the tick number.
|
||||||
|
// No Res/ResMut conflict on any resource.
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn rss_bytes() -> u64 {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
if let Ok(status) = fs::read_to_string("/proc/self/status") {
|
||||||
|
for line in status.lines() {
|
||||||
|
if line.starts_with("VmRSS:") {
|
||||||
|
let kb: u64 = line
|
||||||
|
.split_whitespace()
|
||||||
|
.nth(1)
|
||||||
|
.and_then(|s| s.parse().ok())
|
||||||
|
.unwrap_or(0);
|
||||||
|
return kb * 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// macOS: use proc_info via /proc is unavailable.
|
||||||
|
// Read vm_stat or just return 0 — the paper numbers come from Linux.
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn diagnostics_system(
|
||||||
|
tick_res: Res<CurrentTick>,
|
||||||
|
mut diag: ResMut<TickDiagnostics>,
|
||||||
|
counter: Res<ExportCounter>,
|
||||||
|
profile: Res<FaultProfile>,
|
||||||
|
n_with_sensor: Query<(), With<RawSensorData>>,
|
||||||
|
n_all_processed: Query<(), With<ProcessedState>>,
|
||||||
|
n_alerts: Query<(), With<AlertEvent>>,
|
||||||
|
n_actuators: Query<(), With<ActuatorState>>,
|
||||||
|
) {
|
||||||
|
let t0 = Instant::now();
|
||||||
|
let tick = tick_res.0;
|
||||||
|
|
||||||
|
diag.ticks_in_window += 1;
|
||||||
|
|
||||||
|
if tick % 1_000 != 0 || diag.ticks_in_window == 0 {
|
||||||
|
diag.record("DiagnosticsSystem", t0.elapsed());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let n = diag.ticks_in_window as f64;
|
||||||
|
let rss = rss_bytes();
|
||||||
|
|
||||||
|
let mean = |name: &'static str| -> f64 {
|
||||||
|
diag.accumulated_elapsed_us
|
||||||
|
.get(name)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0) as f64
|
||||||
|
/ n
|
||||||
|
};
|
||||||
|
|
||||||
|
let mean_tick_us = diag.total_tick_elapsed_us as f64 / n;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"tick={tick:>7} | \
|
||||||
|
entities={ne:>7} (sensor_active={sa:>6}, alerts={al:>4}, act={ac:>5}) | \
|
||||||
|
faults={fi:>6} lockouts={lo:>3} | \
|
||||||
|
rss={rss_mb:>6.1} MB | \
|
||||||
|
tick_mean={tm:>7.1} µs | \
|
||||||
|
ingest={ig:>6.1} sim={sm:>6.1} export={ex:>6.1} diag={dg:>5.1} µs | \
|
||||||
|
exported={eb:.2} MB acks={acks}",
|
||||||
|
tick = tick,
|
||||||
|
ne = n_all_processed.iter().count(),
|
||||||
|
sa = n_with_sensor.iter().count(),
|
||||||
|
al = n_alerts.iter().count(),
|
||||||
|
ac = n_actuators.iter().count(),
|
||||||
|
fi = profile.total_faults_injected,
|
||||||
|
lo = profile.total_actuator_lockouts,
|
||||||
|
rss_mb = rss as f64 / 1_048_576.0,
|
||||||
|
tm = mean_tick_us,
|
||||||
|
ig = mean("IngestSystem"),
|
||||||
|
sm = mean("SimulationSystem"),
|
||||||
|
ex = mean("ExportSystem"),
|
||||||
|
dg = mean("DiagnosticsSystem"),
|
||||||
|
eb = counter.total_bytes as f64 / 1_048_576.0,
|
||||||
|
acks = counter.total_acks_processed,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reset window.
|
||||||
|
diag.accumulated_elapsed_us.clear();
|
||||||
|
diag.ticks_in_window = 0;
|
||||||
|
diag.total_tick_elapsed_us = 0;
|
||||||
|
|
||||||
|
diag.record("DiagnosticsSystem", t0.elapsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// World setup — entity spawning
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn spawn_entities(world: &mut World, cfg: &Config) {
|
||||||
|
let mut rng = ChaCha8Rng::seed_from_u64(cfg.rng_seed ^ 0x1234);
|
||||||
|
|
||||||
|
let n_sensor = (cfg.total_entities as f32 * 0.70).round() as usize;
|
||||||
|
let n_event = (cfg.total_entities as f32 * 0.20).round() as usize;
|
||||||
|
let n_actuator = cfg.total_entities - n_sensor - n_event;
|
||||||
|
|
||||||
|
let sensor_units = [
|
||||||
|
SensorUnit::Temperature,
|
||||||
|
SensorUnit::Vibration,
|
||||||
|
SensorUnit::Position,
|
||||||
|
];
|
||||||
|
|
||||||
|
// ── Tier 1: SensorAsset ──────────────────────────────────
|
||||||
|
// spawn_batch keeps all components for the same archetype contiguous
|
||||||
|
// in memory — exactly the cache-coherent layout claimed in the paper.
|
||||||
|
world.spawn_batch((0..n_sensor).map(|i| {
|
||||||
|
let unit = sensor_units[i % 3];
|
||||||
|
let rate = 10.0_f32 + (i % 90) as f32;
|
||||||
|
let offset = {
|
||||||
|
// Pull from rng in closure — ChaCha8Rng is not Send so we
|
||||||
|
// can't move it into par_iter; instead we precompute offsets
|
||||||
|
// sequentially here then use them in the batch.
|
||||||
|
// For the spawn batch we use a simple deterministic formula
|
||||||
|
// instead of rng to avoid borrow issues inside the closure.
|
||||||
|
((i as f32 * 0.6180339887) % 1.0) - 0.5
|
||||||
|
};
|
||||||
|
(
|
||||||
|
AssetId { id: i as u32, class: AssetClass::Sensor },
|
||||||
|
SensorMetadata {
|
||||||
|
sample_rate_hz: rate,
|
||||||
|
unit,
|
||||||
|
calibration_offset: offset,
|
||||||
|
},
|
||||||
|
RawSensorData {
|
||||||
|
value: offset,
|
||||||
|
timestamp_us: 0,
|
||||||
|
sequence_number: 0,
|
||||||
|
},
|
||||||
|
ProcessedState {
|
||||||
|
filtered_value: offset,
|
||||||
|
last_updated_tick: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// ── Tier 2: EventAsset ───────────────────────────────────
|
||||||
|
let base = n_sensor;
|
||||||
|
// Staggered thresholds — prevents all entities from triggering at once.
|
||||||
|
world.spawn_batch((0..n_event).map(|i| {
|
||||||
|
let spread = (i % 20) as f32 * 0.05;
|
||||||
|
let upper = 0.6 + spread;
|
||||||
|
let lower = -0.6 - spread;
|
||||||
|
let consec = 2 + (i % 8) as u8;
|
||||||
|
let offset = ((i as f32 * 0.7320508) % 1.0) - 0.5;
|
||||||
|
(
|
||||||
|
AssetId { id: (base + i) as u32, class: AssetClass::Event },
|
||||||
|
SensorMetadata {
|
||||||
|
sample_rate_hz: 5.0 + (i % 10) as f32,
|
||||||
|
unit: SensorUnit::Temperature,
|
||||||
|
calibration_offset: offset * 0.1,
|
||||||
|
},
|
||||||
|
RawSensorData {
|
||||||
|
value: 0.0,
|
||||||
|
timestamp_us: 0,
|
||||||
|
sequence_number: 0,
|
||||||
|
},
|
||||||
|
ProcessedState {
|
||||||
|
filtered_value: 0.0,
|
||||||
|
last_updated_tick: 0,
|
||||||
|
},
|
||||||
|
ThresholdConfig {
|
||||||
|
upper_bound: upper,
|
||||||
|
lower_bound: lower,
|
||||||
|
consecutive_violations_required: consec,
|
||||||
|
},
|
||||||
|
ThresholdState {
|
||||||
|
current_violation_count: 0,
|
||||||
|
last_violation_tick: 0,
|
||||||
|
is_alerting: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// ── Tier 3: ActuatorAsset ────────────────────────────────
|
||||||
|
let base = n_sensor + n_event;
|
||||||
|
// Use rng for actuator initial positions (small count, no closure issue).
|
||||||
|
let actuator_inits: Vec<f32> = (0..n_actuator)
|
||||||
|
.map(|_| rng.gen_range(-1.0_f32..1.0_f32))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
world.spawn_batch((0..n_actuator).map(|i| {
|
||||||
|
let init_pos = actuator_inits[i];
|
||||||
|
(
|
||||||
|
AssetId { id: (base + i) as u32, class: AssetClass::Actuator },
|
||||||
|
ActuatorState {
|
||||||
|
current_setpoint: init_pos,
|
||||||
|
actual_position: init_pos,
|
||||||
|
last_command_tick: 0,
|
||||||
|
},
|
||||||
|
CommandBuffer {
|
||||||
|
pending_setpoint: None,
|
||||||
|
acknowledged: false,
|
||||||
|
},
|
||||||
|
ActuatorHealth {
|
||||||
|
fault_code: None,
|
||||||
|
consecutive_failures: 0,
|
||||||
|
},
|
||||||
|
// ProcessedState on actuators lets ExportSystem's ProcessedState
|
||||||
|
// query count all tiers unambiguously.
|
||||||
|
ProcessedState {
|
||||||
|
filtered_value: init_pos,
|
||||||
|
last_updated_tick: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"[spawn] SensorAsset={n_sensor} EventAsset={n_event} \
|
||||||
|
ActuatorAsset={n_actuator} total={}",
|
||||||
|
n_sensor + n_event + n_actuator
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Schedule construction
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn build_schedule() -> Schedule {
|
||||||
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
|
schedule.configure_sets((
|
||||||
|
DtSystemSet::Fault,
|
||||||
|
DtSystemSet::Ingest,
|
||||||
|
DtSystemSet::Simulate,
|
||||||
|
DtSystemSet::Export,
|
||||||
|
DtSystemSet::Diagnostics,
|
||||||
|
).chain());
|
||||||
|
|
||||||
|
schedule.add_systems((
|
||||||
|
fault_injection_system.in_set(DtSystemSet::Fault),
|
||||||
|
ingest_system .in_set(DtSystemSet::Ingest),
|
||||||
|
simulation_system .in_set(DtSystemSet::Simulate),
|
||||||
|
export_system .in_set(DtSystemSet::Export),
|
||||||
|
diagnostics_system .in_set(DtSystemSet::Diagnostics),
|
||||||
|
));
|
||||||
|
|
||||||
|
schedule
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Main
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let cfg = parse_args();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"ECS Digital Twin Benchmark — TRANSIT lab / UQAC\n\
|
||||||
|
entities={} | ticks={} | warmup={} | fault_prob={:.1}%",
|
||||||
|
cfg.total_entities,
|
||||||
|
cfg.ticks,
|
||||||
|
cfg.warmup_ticks,
|
||||||
|
cfg.fault_probability * 100.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut world = World::new();
|
||||||
|
let mut schedule = build_schedule();
|
||||||
|
|
||||||
|
// Insert all resources before spawning.
|
||||||
|
world.insert_resource(CurrentTick(0));
|
||||||
|
world.insert_resource(FaultProfile::new(cfg.rng_seed, cfg.fault_probability));
|
||||||
|
world.insert_resource(SimClock { current_us: 0, step_us: 1_000 });
|
||||||
|
world.insert_resource(TickDiagnostics::default());
|
||||||
|
world.insert_resource(ExportCounter::default());
|
||||||
|
|
||||||
|
spawn_entities(&mut world, &cfg);
|
||||||
|
|
||||||
|
// ── Warmup ───────────────────────────────────────────────
|
||||||
|
println!("[warmup] running {} ticks...", cfg.warmup_ticks);
|
||||||
|
for i in 0..cfg.warmup_ticks {
|
||||||
|
world.resource_mut::<CurrentTick>().0 = i;
|
||||||
|
world.resource_mut::<SimClock>().current_us += 1_000;
|
||||||
|
schedule.run(&mut world);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset all measurement state so warmup doesn't pollute results.
|
||||||
|
{
|
||||||
|
let mut diag = world.resource_mut::<TickDiagnostics>();
|
||||||
|
diag.accumulated_elapsed_us.clear();
|
||||||
|
diag.ticks_in_window = 0;
|
||||||
|
diag.total_tick_elapsed_us = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut ctr = world.resource_mut::<ExportCounter>();
|
||||||
|
ctr.total_bytes = 0;
|
||||||
|
ctr.total_acks_processed = 0;
|
||||||
|
ctr.total_alerts_seen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("[warmup] done — starting measurement ({} ticks)", cfg.ticks);
|
||||||
|
|
||||||
|
// ── Measurement loop ─────────────────────────────────────
|
||||||
|
let run_start = Instant::now();
|
||||||
|
|
||||||
|
for i in 0..cfg.ticks {
|
||||||
|
let tick_id = cfg.warmup_ticks + i;
|
||||||
|
|
||||||
|
world.resource_mut::<CurrentTick>().0 = tick_id;
|
||||||
|
world.resource_mut::<SimClock>().current_us += 1_000;
|
||||||
|
|
||||||
|
// Time the full tick including all five systems.
|
||||||
|
let tick_wall = Instant::now();
|
||||||
|
schedule.run(&mut world);
|
||||||
|
let tick_elapsed = tick_wall.elapsed();
|
||||||
|
|
||||||
|
world.resource_mut::<TickDiagnostics>().total_tick_elapsed_us +=
|
||||||
|
tick_elapsed.as_micros() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
let total_elapsed = run_start.elapsed();
|
||||||
|
|
||||||
|
// ── Final summary ─────────────────────────────────────────
|
||||||
|
let hz = cfg.ticks as f64 / total_elapsed.as_secs_f64();
|
||||||
|
|
||||||
|
// Borrow resources for final print.
|
||||||
|
let diag = world.resource::<TickDiagnostics>();
|
||||||
|
let counter = world.resource::<ExportCounter>();
|
||||||
|
let profile = world.resource::<FaultProfile>();
|
||||||
|
|
||||||
|
let n = diag.ticks_in_window.max(1) as f64;
|
||||||
|
let mean = |name: &'static str| -> f64 {
|
||||||
|
diag.accumulated_elapsed_us
|
||||||
|
.get(name)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0) as f64
|
||||||
|
/ n
|
||||||
|
};
|
||||||
|
let mean_tick_us = diag.total_tick_elapsed_us as f64
|
||||||
|
/ cfg.ticks as f64;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"\n── Final Summary ──────────────────────────────────────\n\
|
||||||
|
Total ticks (measurement): {ticks}\n\
|
||||||
|
Total wall time: {wall:.3} s\n\
|
||||||
|
Sustained tick rate: {hz:.1} Hz\n\
|
||||||
|
Per-tick mean (wall): {ptw:.1} µs\n\
|
||||||
|
\n\
|
||||||
|
Per-system mean (µs):\n\
|
||||||
|
IngestSystem: {ig:.1}\n\
|
||||||
|
SimulationSystem: {sm:.1}\n\
|
||||||
|
ExportSystem: {ex:.1}\n\
|
||||||
|
DiagnosticsSystem: {dg:.1}\n\
|
||||||
|
\n\
|
||||||
|
Fault injection:\n\
|
||||||
|
Total sensor faults: {fi}\n\
|
||||||
|
Total actuator lockouts: {lo}\n\
|
||||||
|
\n\
|
||||||
|
Export totals:\n\
|
||||||
|
Bytes exported: {eb:.2} MB\n\
|
||||||
|
Acks processed: {acks}\n\
|
||||||
|
Alerts seen: {alts}\n\
|
||||||
|
\n\
|
||||||
|
Memory (RSS at end): {rss:.1} MB\n\
|
||||||
|
────────────────────────────────────────────────────────",
|
||||||
|
ticks = cfg.ticks,
|
||||||
|
wall = total_elapsed.as_secs_f64(),
|
||||||
|
hz = hz,
|
||||||
|
ptw = mean_tick_us,
|
||||||
|
ig = mean("IngestSystem"),
|
||||||
|
sm = mean("SimulationSystem"),
|
||||||
|
ex = mean("ExportSystem"),
|
||||||
|
dg = mean("DiagnosticsSystem"),
|
||||||
|
fi = profile.total_faults_injected,
|
||||||
|
lo = profile.total_actuator_lockouts,
|
||||||
|
eb = counter.total_bytes as f64 / 1_048_576.0,
|
||||||
|
acks = counter.total_acks_processed,
|
||||||
|
alts = counter.total_alerts_seen,
|
||||||
|
rss = rss_bytes() as f64 / 1_048_576.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user