Compare commits
No commits in common. "sync-undf" and "master" have entirely different histories.
3681 changed files with 51 additions and 108842 deletions
|
|
@ -93,9 +93,6 @@
|
||||||
"cargo-0001": "UNDF-2026-000000021",
|
"cargo-0001": "UNDF-2026-000000021",
|
||||||
"cargo-0002": "UNDF-2026-000000022",
|
"cargo-0002": "UNDF-2026-000000022",
|
||||||
"cassandra-0001": "UNDF-2026-000000023",
|
"cassandra-0001": "UNDF-2026-000000023",
|
||||||
"cassandra-0002": "UNDF-2026-000001282",
|
|
||||||
"cassandra-0003": "UNDF-2026-000001283",
|
|
||||||
"cassandra-0004": "UNDF-2026-000001284",
|
|
||||||
"cassandra-0005": "UNDF-2026-000000024",
|
"cassandra-0005": "UNDF-2026-000000024",
|
||||||
"cataclysm-0001-0001": "UNDF-2026-000000935",
|
"cataclysm-0001-0001": "UNDF-2026-000000935",
|
||||||
"cataclysm-0002-0002": "UNDF-2026-000000936",
|
"cataclysm-0002-0002": "UNDF-2026-000000936",
|
||||||
|
|
@ -113,7 +110,6 @@
|
||||||
"cfengine-0001": "UNDF-2026-000000027",
|
"cfengine-0001": "UNDF-2026-000000027",
|
||||||
"cfengine-0002": "UNDF-2026-000000028",
|
"cfengine-0002": "UNDF-2026-000000028",
|
||||||
"cfengine-0003": "UNDF-2026-000000029",
|
"cfengine-0003": "UNDF-2026-000000029",
|
||||||
"check-0001": "UNDF-2026-000001292",
|
|
||||||
"chef-0001": "UNDF-2026-000000362",
|
"chef-0001": "UNDF-2026-000000362",
|
||||||
"cilium-0001": "UNDF-2026-000000030",
|
"cilium-0001": "UNDF-2026-000000030",
|
||||||
"cilium-0002": "UNDF-2026-000000363",
|
"cilium-0002": "UNDF-2026-000000363",
|
||||||
|
|
@ -325,7 +321,6 @@
|
||||||
"frrouting-0003": "UNDF-2026-000000401",
|
"frrouting-0003": "UNDF-2026-000000401",
|
||||||
"frrouting-0004": "UNDF-2026-000000402",
|
"frrouting-0004": "UNDF-2026-000000402",
|
||||||
"fs-uae-0001-0001": "UNDF-2026-000001047",
|
"fs-uae-0001-0001": "UNDF-2026-000001047",
|
||||||
"gatsby-0001": "UNDF-2026-000001299",
|
|
||||||
"gcc-0001": "UNDF-2026-000000076",
|
"gcc-0001": "UNDF-2026-000000076",
|
||||||
"gcc-0002": "UNDF-2026-000000077",
|
"gcc-0002": "UNDF-2026-000000077",
|
||||||
"gearboy-0001-0001": "UNDF-2026-000001096",
|
"gearboy-0001-0001": "UNDF-2026-000001096",
|
||||||
|
|
@ -334,9 +329,6 @@
|
||||||
"geth-0001": "UNDF-2026-000000632",
|
"geth-0001": "UNDF-2026-000000632",
|
||||||
"ghc-0001": "UNDF-2026-000000078",
|
"ghc-0001": "UNDF-2026-000000078",
|
||||||
"ghc-0003": "UNDF-2026-000000079",
|
"ghc-0003": "UNDF-2026-000000079",
|
||||||
"ghidra-0001": "UNDF-2026-000001303",
|
|
||||||
"ghidra-0002": "UNDF-2026-000001304",
|
|
||||||
"ghost-0001": "UNDF-2026-000001302",
|
|
||||||
"gimp-0001": "UNDF-2026-000000793",
|
"gimp-0001": "UNDF-2026-000000793",
|
||||||
"gimp-0002": "UNDF-2026-000000794",
|
"gimp-0002": "UNDF-2026-000000794",
|
||||||
"gimp-0003": "UNDF-2026-000001098",
|
"gimp-0003": "UNDF-2026-000001098",
|
||||||
|
|
@ -393,7 +385,6 @@
|
||||||
"hadoop-0002": "UNDF-2026-000000097",
|
"hadoop-0002": "UNDF-2026-000000097",
|
||||||
"hadoop-0003": "UNDF-2026-000000098",
|
"hadoop-0003": "UNDF-2026-000000098",
|
||||||
"hadoop-0004": "UNDF-2026-000000099",
|
"hadoop-0004": "UNDF-2026-000000099",
|
||||||
"hadoop-rpc-0001": "UNDF-2026-000001285",
|
|
||||||
"hanami-0001": "UNDF-2026-000000100",
|
"hanami-0001": "UNDF-2026-000000100",
|
||||||
"haproxy-0001": "UNDF-2026-000000101",
|
"haproxy-0001": "UNDF-2026-000000101",
|
||||||
"haproxy-0002": "UNDF-2026-000000413",
|
"haproxy-0002": "UNDF-2026-000000413",
|
||||||
|
|
@ -468,7 +459,6 @@
|
||||||
"jami-daemon-0001": "UNDF-2026-000000115",
|
"jami-daemon-0001": "UNDF-2026-000000115",
|
||||||
"jami-daemon-0002": "UNDF-2026-000000116",
|
"jami-daemon-0002": "UNDF-2026-000000116",
|
||||||
"janusgraph-0001": "UNDF-2026-000000430",
|
"janusgraph-0001": "UNDF-2026-000000430",
|
||||||
"jasmine-0001": "UNDF-2026-000001293",
|
|
||||||
"javac-0001": "UNDF-2026-000000117",
|
"javac-0001": "UNDF-2026-000000117",
|
||||||
"javac-0002": "UNDF-2026-000000118",
|
"javac-0002": "UNDF-2026-000000118",
|
||||||
"javac-0003": "UNDF-2026-000000119",
|
"javac-0003": "UNDF-2026-000000119",
|
||||||
|
|
@ -510,7 +500,6 @@
|
||||||
"kafka-0009": "UNDF-2026-000000451",
|
"kafka-0009": "UNDF-2026-000000451",
|
||||||
"kafka-0010": "UNDF-2026-000000686",
|
"kafka-0010": "UNDF-2026-000000686",
|
||||||
"kafka-0011": "UNDF-2026-000000687",
|
"kafka-0011": "UNDF-2026-000000687",
|
||||||
"katago-0001": "UNDF-2026-000000226",
|
|
||||||
"kdenlive-0001": "UNDF-2026-000000798",
|
"kdenlive-0001": "UNDF-2026-000000798",
|
||||||
"kdenlive-0002": "UNDF-2026-000000799",
|
"kdenlive-0002": "UNDF-2026-000000799",
|
||||||
"kdenlive-0003": "UNDF-2026-000000800",
|
"kdenlive-0003": "UNDF-2026-000000800",
|
||||||
|
|
@ -527,7 +516,6 @@
|
||||||
"kicad-0001": "UNDF-2026-000000133",
|
"kicad-0001": "UNDF-2026-000000133",
|
||||||
"kicad-0002": "UNDF-2026-000000589",
|
"kicad-0002": "UNDF-2026-000000589",
|
||||||
"kicad-0003-0003": "UNDF-2026-000001113",
|
"kicad-0003-0003": "UNDF-2026-000001113",
|
||||||
"knex-0001": "UNDF-2026-000001298",
|
|
||||||
"kotlin-0001": "UNDF-2026-000000134",
|
"kotlin-0001": "UNDF-2026-000000134",
|
||||||
"kotlin-0002": "UNDF-2026-000000135",
|
"kotlin-0002": "UNDF-2026-000000135",
|
||||||
"krita-0001-0001": "UNDF-2026-000001216",
|
"krita-0001-0001": "UNDF-2026-000001216",
|
||||||
|
|
@ -600,7 +588,6 @@
|
||||||
"llvm-0006": "UNDF-2026-000000774",
|
"llvm-0006": "UNDF-2026-000000774",
|
||||||
"lmdb-0001": "UNDF-2026-000000454",
|
"lmdb-0001": "UNDF-2026-000000454",
|
||||||
"lmdb-001": "UNDF-2026-000000638",
|
"lmdb-001": "UNDF-2026-000000638",
|
||||||
"log4j2-0001": "UNDF-2026-000001308",
|
|
||||||
"loki-0001": "UNDF-2026-000000821",
|
"loki-0001": "UNDF-2026-000000821",
|
||||||
"lotus-0001-0001": "UNDF-2026-000001018",
|
"lotus-0001-0001": "UNDF-2026-000001018",
|
||||||
"love2d-0001": "UNDF-2026-000000157",
|
"love2d-0001": "UNDF-2026-000000157",
|
||||||
|
|
@ -613,7 +600,6 @@
|
||||||
"mariadb-0002": "UNDF-2026-000000161",
|
"mariadb-0002": "UNDF-2026-000000161",
|
||||||
"mastodon-0001": "UNDF-2026-000000609",
|
"mastodon-0001": "UNDF-2026-000000609",
|
||||||
"mastodon-0002": "UNDF-2026-000000610",
|
"mastodon-0002": "UNDF-2026-000000610",
|
||||||
"mastodon-0003": "UNDF-2026-000001275",
|
|
||||||
"mattermost-0001": "UNDF-2026-000000162",
|
"mattermost-0001": "UNDF-2026-000000162",
|
||||||
"maven-0001": "UNDF-2026-000000163",
|
"maven-0001": "UNDF-2026-000000163",
|
||||||
"maven-0003": "UNDF-2026-000000164",
|
"maven-0003": "UNDF-2026-000000164",
|
||||||
|
|
@ -632,10 +618,6 @@
|
||||||
"mesa-0001": "UNDF-2026-000000170",
|
"mesa-0001": "UNDF-2026-000000170",
|
||||||
"meson-0001": "UNDF-2026-000000171",
|
"meson-0001": "UNDF-2026-000000171",
|
||||||
"meson-0002": "UNDF-2026-000000412",
|
"meson-0002": "UNDF-2026-000000412",
|
||||||
"meson-0003": "UNDF-2026-000001278",
|
|
||||||
"meson-0004": "UNDF-2026-000001279",
|
|
||||||
"meson-0005": "UNDF-2026-000001280",
|
|
||||||
"meson-0006": "UNDF-2026-000001281",
|
|
||||||
"metaflow-0001": "UNDF-2026-000000460",
|
"metaflow-0001": "UNDF-2026-000000460",
|
||||||
"mgba-0001-0001": "UNDF-2026-000001126",
|
"mgba-0001-0001": "UNDF-2026-000001126",
|
||||||
"micronaut-0001": "UNDF-2026-000000461",
|
"micronaut-0001": "UNDF-2026-000000461",
|
||||||
|
|
@ -661,8 +643,6 @@
|
||||||
"minio-0003": "UNDF-2026-000000770",
|
"minio-0003": "UNDF-2026-000000770",
|
||||||
"moby-0001": "UNDF-2026-000000172",
|
"moby-0001": "UNDF-2026-000000172",
|
||||||
"moby-0002": "UNDF-2026-000000688",
|
"moby-0002": "UNDF-2026-000000688",
|
||||||
"mongo-0001": "UNDF-2026-000001286",
|
|
||||||
"mongo-0002": "UNDF-2026-000001287",
|
|
||||||
"mongodb-0001": "UNDF-2026-000000173",
|
"mongodb-0001": "UNDF-2026-000000173",
|
||||||
"mongodb-0008": "UNDF-2026-000000465",
|
"mongodb-0008": "UNDF-2026-000000465",
|
||||||
"monogame-0001-0001": "UNDF-2026-000000941",
|
"monogame-0001-0001": "UNDF-2026-000000941",
|
||||||
|
|
@ -682,7 +662,6 @@
|
||||||
"naev-0002-0002": "UNDF-2026-000001000",
|
"naev-0002-0002": "UNDF-2026-000001000",
|
||||||
"nagioscore-0001-0001": "UNDF-2026-000000879",
|
"nagioscore-0001-0001": "UNDF-2026-000000879",
|
||||||
"nagioscore-0002-0002": "UNDF-2026-000000880",
|
"nagioscore-0002-0002": "UNDF-2026-000000880",
|
||||||
"nakama-0001": "UNDF-2026-000001309",
|
|
||||||
"natron-0001": "UNDF-2026-000001129",
|
"natron-0001": "UNDF-2026-000001129",
|
||||||
"nats-0001": "UNDF-2026-000000466",
|
"nats-0001": "UNDF-2026-000000466",
|
||||||
"nats-server-0001": "UNDF-2026-000000179",
|
"nats-server-0001": "UNDF-2026-000000179",
|
||||||
|
|
@ -803,7 +782,6 @@
|
||||||
"otel-collector-0001": "UNDF-2026-000000205",
|
"otel-collector-0001": "UNDF-2026-000000205",
|
||||||
"otel-collector-0002": "UNDF-2026-000000709",
|
"otel-collector-0002": "UNDF-2026-000000709",
|
||||||
"ovs-0001": "UNDF-2026-000000206",
|
"ovs-0001": "UNDF-2026-000000206",
|
||||||
"pachi-0001": "UNDF-2026-000001274",
|
|
||||||
"panda3d-0001": "UNDF-2026-000000207",
|
"panda3d-0001": "UNDF-2026-000000207",
|
||||||
"panda3d-0002": "UNDF-2026-000000208",
|
"panda3d-0002": "UNDF-2026-000000208",
|
||||||
"pandas-0001": "UNDF-2026-000000497",
|
"pandas-0001": "UNDF-2026-000000497",
|
||||||
|
|
@ -832,7 +810,6 @@
|
||||||
"pip-0001": "UNDF-2026-000000215",
|
"pip-0001": "UNDF-2026-000000215",
|
||||||
"pitivi-0001-0001": "UNDF-2026-000001143",
|
"pitivi-0001-0001": "UNDF-2026-000001143",
|
||||||
"play-0001-0001": "UNDF-2026-000001144",
|
"play-0001-0001": "UNDF-2026-000001144",
|
||||||
"playwright-0001": "UNDF-2026-000001276",
|
|
||||||
"podman-0001": "UNDF-2026-000000501",
|
"podman-0001": "UNDF-2026-000000501",
|
||||||
"podman-0002": "UNDF-2026-000000502",
|
"podman-0002": "UNDF-2026-000000502",
|
||||||
"poetry-0001": "UNDF-2026-000000575",
|
"poetry-0001": "UNDF-2026-000000575",
|
||||||
|
|
@ -862,7 +839,6 @@
|
||||||
"prusaslicer-0002-0002": "UNDF-2026-000000911",
|
"prusaslicer-0002-0002": "UNDF-2026-000000911",
|
||||||
"prusaslicer-0003-0003": "UNDF-2026-000000912",
|
"prusaslicer-0003-0003": "UNDF-2026-000000912",
|
||||||
"prusaslicer-0004-0004": "UNDF-2026-000001207",
|
"prusaslicer-0004-0004": "UNDF-2026-000001207",
|
||||||
"psalm-0001": "UNDF-2026-000001296",
|
|
||||||
"pulsar-0001": "UNDF-2026-000000505",
|
"pulsar-0001": "UNDF-2026-000000505",
|
||||||
"pulsar-0002": "UNDF-2026-000000506",
|
"pulsar-0002": "UNDF-2026-000000506",
|
||||||
"pulsar-0003": "UNDF-2026-000000507",
|
"pulsar-0003": "UNDF-2026-000000507",
|
||||||
|
|
@ -882,8 +858,6 @@
|
||||||
"pyramid-0003": "UNDF-2026-000000233",
|
"pyramid-0003": "UNDF-2026-000000233",
|
||||||
"pyramid-0004": "UNDF-2026-000000234",
|
"pyramid-0004": "UNDF-2026-000000234",
|
||||||
"pyramid-0005": "UNDF-2026-000000235",
|
"pyramid-0005": "UNDF-2026-000000235",
|
||||||
"pyright-0001": "UNDF-2026-000001311",
|
|
||||||
"pyroscope-0001": "UNDF-2026-000001301",
|
|
||||||
"python-igraph-0001": "UNDF-2026-000000511",
|
"python-igraph-0001": "UNDF-2026-000000511",
|
||||||
"pytorch-0001": "UNDF-2026-000000512",
|
"pytorch-0001": "UNDF-2026-000000512",
|
||||||
"pytorch-0002": "UNDF-2026-000000513",
|
"pytorch-0002": "UNDF-2026-000000513",
|
||||||
|
|
@ -1025,8 +999,6 @@
|
||||||
"seaorm-0004": "UNDF-2026-000000277",
|
"seaorm-0004": "UNDF-2026-000000277",
|
||||||
"seaweedfs-0001-0001": "UNDF-2026-000001032",
|
"seaweedfs-0001-0001": "UNDF-2026-000001032",
|
||||||
"seaweedfs-0002-0002": "UNDF-2026-000001033",
|
"seaweedfs-0002-0002": "UNDF-2026-000001033",
|
||||||
"selenium-0001": "UNDF-2026-000001277",
|
|
||||||
"selenium-0002": "UNDF-2026-000001288",
|
|
||||||
"sendmail-0001-0001": "UNDF-2026-000001189",
|
"sendmail-0001-0001": "UNDF-2026-000001189",
|
||||||
"sequelize-0001": "UNDF-2026-000000278",
|
"sequelize-0001": "UNDF-2026-000000278",
|
||||||
"sequelize-0002": "UNDF-2026-000000279",
|
"sequelize-0002": "UNDF-2026-000000279",
|
||||||
|
|
@ -1127,7 +1099,6 @@
|
||||||
"suricata-0002-0002": "UNDF-2026-000001186",
|
"suricata-0002-0002": "UNDF-2026-000001186",
|
||||||
"swift-0001": "UNDF-2026-000000545",
|
"swift-0001": "UNDF-2026-000000545",
|
||||||
"swift-0002": "UNDF-2026-000000546",
|
"swift-0002": "UNDF-2026-000000546",
|
||||||
"symfony-0001": "UNDF-2026-000001310",
|
|
||||||
"synapse-0001": "UNDF-2026-000000305",
|
"synapse-0001": "UNDF-2026-000000305",
|
||||||
"synapse-0002": "UNDF-2026-000000306",
|
"synapse-0002": "UNDF-2026-000000306",
|
||||||
"syncthing-0001": "UNDF-2026-000000850",
|
"syncthing-0001": "UNDF-2026-000000850",
|
||||||
|
|
@ -1143,8 +1114,6 @@
|
||||||
"tensorflow-0001": "UNDF-2026-000000551",
|
"tensorflow-0001": "UNDF-2026-000000551",
|
||||||
"terraform-0001": "UNDF-2026-000000307",
|
"terraform-0001": "UNDF-2026-000000307",
|
||||||
"terraform-0002": "UNDF-2026-000000308",
|
"terraform-0002": "UNDF-2026-000000308",
|
||||||
"testcafe-0001": "UNDF-2026-000001290",
|
|
||||||
"testng-0001": "UNDF-2026-000001294",
|
|
||||||
"tf-0001": "UNDF-2026-000000668",
|
"tf-0001": "UNDF-2026-000000668",
|
||||||
"tf-0002": "UNDF-2026-000000669",
|
"tf-0002": "UNDF-2026-000000669",
|
||||||
"tf-aws-0001": "UNDF-2026-000000670",
|
"tf-aws-0001": "UNDF-2026-000000670",
|
||||||
|
|
@ -1209,7 +1178,6 @@
|
||||||
"v8-0002": "UNDF-2026-000000564",
|
"v8-0002": "UNDF-2026-000000564",
|
||||||
"v8-0003": "UNDF-2026-000000565",
|
"v8-0003": "UNDF-2026-000000565",
|
||||||
"v8-0004": "UNDF-2026-000000593",
|
"v8-0004": "UNDF-2026-000000593",
|
||||||
"vagrant-0001": "UNDF-2026-000001297",
|
|
||||||
"valhalla-0001": "UNDF-2026-000000566",
|
"valhalla-0001": "UNDF-2026-000000566",
|
||||||
"valkey-0001": "UNDF-2026-000000326",
|
"valkey-0001": "UNDF-2026-000000326",
|
||||||
"valkey-0002": "UNDF-2026-000000327",
|
"valkey-0002": "UNDF-2026-000000327",
|
||||||
|
|
@ -1228,7 +1196,6 @@
|
||||||
"vim-0001": "UNDF-2026-000000571",
|
"vim-0001": "UNDF-2026-000000571",
|
||||||
"vim-0002": "UNDF-2026-000000572",
|
"vim-0002": "UNDF-2026-000000572",
|
||||||
"vita3k-0001-0001": "UNDF-2026-000001173",
|
"vita3k-0001-0001": "UNDF-2026-000001173",
|
||||||
"vitest-0001": "UNDF-2026-000001295",
|
|
||||||
"vlc-0001": "UNDF-2026-000000331",
|
"vlc-0001": "UNDF-2026-000000331",
|
||||||
"vlc-0002": "UNDF-2026-000000718",
|
"vlc-0002": "UNDF-2026-000000718",
|
||||||
"vlc-0003-0003": "UNDF-2026-000001174",
|
"vlc-0003-0003": "UNDF-2026-000001174",
|
||||||
|
|
@ -1248,9 +1215,6 @@
|
||||||
"wasmer-0002": "UNDF-2026-000000335",
|
"wasmer-0002": "UNDF-2026-000000335",
|
||||||
"wasmtime-0001": "UNDF-2026-000000336",
|
"wasmtime-0001": "UNDF-2026-000000336",
|
||||||
"wasmtime-0002": "UNDF-2026-000000337",
|
"wasmtime-0002": "UNDF-2026-000000337",
|
||||||
"weaviate-0001": "UNDF-2026-000001300",
|
|
||||||
"webdriverio-0001": "UNDF-2026-000001289",
|
|
||||||
"webdriverio-0002": "UNDF-2026-000001291",
|
|
||||||
"webpack-0001": "UNDF-2026-000000338",
|
"webpack-0001": "UNDF-2026-000000338",
|
||||||
"webpack-0002": "UNDF-2026-000000339",
|
"webpack-0002": "UNDF-2026-000000339",
|
||||||
"weechat-0001": "UNDF-2026-000000340",
|
"weechat-0001": "UNDF-2026-000000340",
|
||||||
|
|
@ -1271,9 +1235,6 @@
|
||||||
"widelands-0001-0001": "UNDF-2026-000000976",
|
"widelands-0001-0001": "UNDF-2026-000000976",
|
||||||
"widelands-0002-0002": "UNDF-2026-000000977",
|
"widelands-0002-0002": "UNDF-2026-000000977",
|
||||||
"widelands-0003-0003": "UNDF-2026-000000978",
|
"widelands-0003-0003": "UNDF-2026-000000978",
|
||||||
"wildfly-0001": "UNDF-2026-000001305",
|
|
||||||
"wildfly-0002": "UNDF-2026-000001306",
|
|
||||||
"wildfly-0003": "UNDF-2026-000001307",
|
|
||||||
"wine-0001-0001": "UNDF-2026-000000886",
|
"wine-0001-0001": "UNDF-2026-000000886",
|
||||||
"wine-0002-0002": "UNDF-2026-000001193",
|
"wine-0002-0002": "UNDF-2026-000001193",
|
||||||
"wine-0003-0003": "UNDF-2026-000001194",
|
"wine-0003-0003": "UNDF-2026-000001194",
|
||||||
|
|
@ -1309,5 +1270,20 @@
|
||||||
"zookeeper-0002": "UNDF-2026-000000724",
|
"zookeeper-0002": "UNDF-2026-000000724",
|
||||||
"zulip-0001-0001": "UNDF-2026-000001190",
|
"zulip-0001-0001": "UNDF-2026-000001190",
|
||||||
"zulip-0002-0002": "UNDF-2026-000001191",
|
"zulip-0002-0002": "UNDF-2026-000001191",
|
||||||
"zulip-0003-0003": "UNDF-2026-000001192"
|
"zulip-0003-0003": "UNDF-2026-000001192",
|
||||||
}
|
"katago-0001": "UNDF-2026-000000226",
|
||||||
|
"pachi-0001": "UNDF-2026-000001274",
|
||||||
|
"mastodon-0003": "UNDF-2026-000001275",
|
||||||
|
"ktor-0001": "UNDF-2026-000001276",
|
||||||
|
"ktor-0002": "UNDF-2026-000001277",
|
||||||
|
"meson-0003": "UNDF-2026-000001278",
|
||||||
|
"meson-0004": "UNDF-2026-000001279",
|
||||||
|
"meson-0005": "UNDF-2026-000001280",
|
||||||
|
"meson-0006": "UNDF-2026-000001281",
|
||||||
|
"cassandra-0002": "UNDF-2026-000001282",
|
||||||
|
"cassandra-0003": "UNDF-2026-000001283",
|
||||||
|
"cassandra-0004": "UNDF-2026-000001284",
|
||||||
|
"hadoop-rpc-0001": "UNDF-2026-000001285",
|
||||||
|
"mongo-0001": "UNDF-2026-000001286",
|
||||||
|
"mongo-0002": "UNDF-2026-000001287"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# 0ad-0001 bench runner
|
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-0ad-0001-0001.py
|
|
||||||
# CCmpObstructionManager dirty shape tracking: std::find on std::vector for
|
|
||||||
# dedup, called per nearby shape per frame. With N nearby shapes × D dirty
|
|
||||||
# list size, cost is O(N·D) = O(N²) in large battles (200v200, hundreds of
|
|
||||||
# shapes moving per frame). Fix: std::unordered_set for O(1) membership.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n_shapes, dirty_before):
|
|
||||||
"""std::find over a growing vector, called per shape per frame."""
|
|
||||||
dirty = list(range(dirty_before)) # starts with D entries
|
|
||||||
updates = [i for i in range(n_shapes)] # N shapes to dedup-add
|
|
||||||
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for s in updates:
|
|
||||||
if s not in dirty: # list.__contains__: O(len(dirty))
|
|
||||||
dirty.append(s)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n_shapes, dirty_before):
|
|
||||||
"""unordered_set membership, O(1) per check."""
|
|
||||||
dirty = set(range(dirty_before))
|
|
||||||
updates = [i for i in range(n_shapes)]
|
|
||||||
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for s in updates:
|
|
||||||
if s not in dirty:
|
|
||||||
dirty.add(s)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (300, 300), (500, 500), (1000, 1000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== 0ad-0001-0001: CCmpObstructionManager dirty shapes std::find vs unordered_set ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, d in CASES:
|
|
||||||
df = min(bench_defective(n, d) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, d) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<4} D={d:<4}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== 0ad-0001-0001: CCmpObstructionManager dirty shapes std::find vs unordered_set ===
|
|
||||||
N=100 D=100 : defective=0.108ms fixed=0.004ms speedup=26.0x
|
|
||||||
N=300 D=300 : defective=0.963ms fixed=0.014ms speedup=70.0x
|
|
||||||
N=500 D=500 : defective=2.580ms fixed=0.025ms speedup=104.1x
|
|
||||||
N=1000 D=1000: defective=11.218ms fixed=0.187ms speedup=59.9x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-0ad-0001-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# 0ad-0002 bench runner
|
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-0ad-0002-0002.py
|
|
||||||
# CCmpSelectable modified-entity tracking: std::find on m_ModifiedEntities
|
|
||||||
# vector inside a per-entity loop. O(N²) as the set of modified entities
|
|
||||||
# grows over a frame. Fix: unordered_set for O(1) membership.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n):
|
|
||||||
modified = []
|
|
||||||
entities = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for ent in entities:
|
|
||||||
if ent not in modified: # O(|modified|)
|
|
||||||
modified.append(ent)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n):
|
|
||||||
modified = set()
|
|
||||||
entities = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for ent in entities:
|
|
||||||
if ent not in modified:
|
|
||||||
modified.add(ent)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
SIZES = [100, 500, 1000, 2000]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== 0ad-0002-0002: CCmpSelectable modified-entities std::find vs unordered_set ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n in SIZES:
|
|
||||||
df = min(bench_defective(n) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== 0ad-0002-0002: CCmpSelectable modified-entities std::find vs unordered_set ===
|
|
||||||
N=100 : defective=0.221ms fixed=0.020ms speedup=10.9x
|
|
||||||
N=500 : defective=4.980ms fixed=0.078ms speedup=63.9x
|
|
||||||
N=1000 : defective=19.368ms fixed=0.176ms speedup=110.1x
|
|
||||||
N=2000 : defective=72.550ms fixed=0.212ms speedup=341.5x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-0ad-0002-0002.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# 0ad-0003 bench runner
|
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-0ad-0003-0003.py
|
|
||||||
# Template-cache usedTemplates tracking: std::find on usedTemplates vector
|
|
||||||
# inside a per-template-instance loop. O(N²) across instances × template names.
|
|
||||||
# Fix: unordered_set of template ids for O(1) dedup.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, unique_ratio=0.5):
|
|
||||||
used = []
|
|
||||||
distinct = max(1, int(n * unique_ratio))
|
|
||||||
candidates = [f"tpl_{i % distinct}" for i in range(n)]
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for t in candidates:
|
|
||||||
if t not in used: # O(|used|)
|
|
||||||
used.append(t)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, unique_ratio=0.5):
|
|
||||||
used = set()
|
|
||||||
distinct = max(1, int(n * unique_ratio))
|
|
||||||
candidates = [f"tpl_{i % distinct}" for i in range(n)]
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for t in candidates:
|
|
||||||
if t not in used:
|
|
||||||
used.add(t)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
SIZES = [100, 500, 1000, 2000]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== 0ad-0003-0003: usedTemplates std::find vs unordered_set ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n in SIZES:
|
|
||||||
df = min(bench_defective(n) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== 0ad-0003-0003: usedTemplates std::find vs unordered_set ===
|
|
||||||
N=100 : defective=0.120ms fixed=0.018ms speedup=6.6x
|
|
||||||
N=500 : defective=2.615ms fixed=0.118ms speedup=22.1x
|
|
||||||
N=1000 : defective=8.730ms fixed=0.111ms speedup=78.4x
|
|
||||||
N=2000 : defective=37.381ms fixed=0.372ms speedup=100.6x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-0ad-0003-0003.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# 0ad-0004 bench runner
|
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-0ad-0004-0004.py
|
|
||||||
# XmppClient + NetServer: lobby auth tokens logged verbatim. CWE-312 / MOAD-0004
|
|
||||||
# A Logged Secret. Correctness metric: does log output contain the raw token?
|
|
||||||
# Fixed path replaces token with "[REDACTED]" before logging.
|
|
||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def emit_defective(username, token, logsink):
|
|
||||||
# Verbatim log of the token — the defect.
|
|
||||||
logsink.append(f"XmppClient: Received lobby auth: {token} from {username}")
|
|
||||||
|
|
||||||
|
|
||||||
def emit_fixed(username, token, logsink):
|
|
||||||
# Redacted log — the fix.
|
|
||||||
logsink.append(f"XmppClient: Received lobby auth: [REDACTED] from {username}")
|
|
||||||
|
|
||||||
|
|
||||||
def count_leaks(logsink, tokens):
|
|
||||||
"""Return the number of log lines that contain a raw token value."""
|
|
||||||
leaks = 0
|
|
||||||
for line in logsink:
|
|
||||||
for tok in tokens:
|
|
||||||
if tok in line:
|
|
||||||
leaks += 1
|
|
||||||
break
|
|
||||||
return leaks
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== 0ad-0004-0004: lobby auth token log redaction (correctness) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
|
|
||||||
# Simulate N auth events with random-looking tokens
|
|
||||||
cases = [100, 1000, 10000]
|
|
||||||
for n in cases:
|
|
||||||
tokens = [f"tok_{i:08x}" for i in range(n)]
|
|
||||||
users = [f"user{i}" for i in range(n)]
|
|
||||||
|
|
||||||
sink_def = []
|
|
||||||
sink_fix = []
|
|
||||||
for u, t in zip(users, tokens):
|
|
||||||
emit_defective(u, t, sink_def)
|
|
||||||
emit_fixed(u, t, sink_fix)
|
|
||||||
|
|
||||||
leaks_def = count_leaks(sink_def, tokens)
|
|
||||||
leaks_fix = count_leaks(sink_fix, tokens)
|
|
||||||
line = (f"N={n:<5}: defective_leaks={leaks_def:>5} fixed_leaks={leaks_fix:>5}"
|
|
||||||
f" redaction_rate={(n - leaks_fix) / n * 100:.1f}%")
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
=== 0ad-0004-0004: lobby auth token log redaction (correctness) ===
|
|
||||||
N=100 : defective_leaks= 100 fixed_leaks= 0 redaction_rate=100.0%
|
|
||||||
N=1000 : defective_leaks= 1000 fixed_leaks= 0 redaction_rate=100.0%
|
|
||||||
N=10000: defective_leaks=10000 fixed_leaks= 0 redaction_rate=100.0%
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-0ad-0004-0004.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-activemq-artemis-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in activemq-artemis-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== activemq-artemis-0001: CWE-407: list-scan inside loop in activemq-artemis-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-activemq-artemis-0002.py
|
|
||||||
# CWE-407: list-scan inside loop in activemq-artemis-0002 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== activemq-artemis-0002: CWE-407: list-scan inside loop in activemq-artemis-0002 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
=== activemq-artemis-0001: CWE-407: list-scan inside loop in activemq-artemis-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.180ms fixed=0.007ms speedup=25.8x
|
|
||||||
N=500 k=500 : defective=5.061ms fixed=0.043ms speedup=117.8x
|
|
||||||
N=1000 k=1000 : defective=19.862ms fixed=0.097ms speedup=203.8x
|
|
||||||
N=2000 k=2000 : defective=42.342ms fixed=0.100ms speedup=423.3x
|
|
||||||
|
|
||||||
=== activemq-artemis-0002: CWE-407: list-scan inside loop in activemq-artemis-0002 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.093ms fixed=0.004ms speedup=25.1x
|
|
||||||
N=500 k=500 : defective=2.294ms fixed=0.021ms speedup=107.1x
|
|
||||||
N=1000 k=1000 : defective=9.116ms fixed=0.053ms speedup=172.8x
|
|
||||||
N=2000 k=2000 : defective=43.585ms fixed=0.097ms speedup=450.4x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-activemq-artemis-0001.py", "bench-activemq-artemis-0002.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# activemq bench runner
|
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-activemq-0001.py
|
|
||||||
# ActiveMQ Queue/Topic consumer list: per-message round-robin rotation via
|
|
||||||
# remove+add on the consumers List. For C consumers and M messages, cost is
|
|
||||||
# O(M·C) per dispatch. Topic path also does linear contains() for dedup.
|
|
||||||
# Fix: rotation-index pointer + parallel Set<Subscription> for O(1) checks.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n_consumers, n_messages):
|
|
||||||
"""Remove + append to rotate; O(C) per message."""
|
|
||||||
consumers = list(range(n_consumers))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for m in range(n_messages):
|
|
||||||
target = consumers[0]
|
|
||||||
# remove target from list and re-append — O(C)
|
|
||||||
consumers.pop(0)
|
|
||||||
consumers.append(target)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n_consumers, n_messages):
|
|
||||||
"""Rotation index cursor; O(1) per message."""
|
|
||||||
consumers = list(range(n_consumers))
|
|
||||||
rot = 0
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for m in range(n_messages):
|
|
||||||
target = consumers[rot]
|
|
||||||
rot = (rot + 1) % len(consumers)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(50, 1000), (200, 5000), (500, 10000), (1000, 20000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== activemq-0001: Queue/Topic consumer rotation list.remove+add vs index cursor ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for c, m in CASES:
|
|
||||||
df = min(bench_defective(c, m) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(c, m) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"C={c:<5} M={m:<6}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-activemq-0002.py
|
|
||||||
# DemandBridge candidateConsumers.contains() inside a per-consumer loop:
|
|
||||||
# O(N²) across N candidates. Fix: parallel HashSet for O(1) membership.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n):
|
|
||||||
candidates = []
|
|
||||||
incoming = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for c in incoming:
|
|
||||||
if c not in candidates: # O(len(candidates))
|
|
||||||
candidates.append(c)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n):
|
|
||||||
candidates_set = set()
|
|
||||||
candidates = []
|
|
||||||
incoming = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for c in incoming:
|
|
||||||
if c not in candidates_set:
|
|
||||||
candidates_set.add(c)
|
|
||||||
candidates.append(c)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
SIZES = [100, 500, 1000, 2000]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== activemq-0002: DemandBridge candidateConsumers List.contains vs HashSet ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n in SIZES:
|
|
||||||
df = min(bench_defective(n) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-activemq-0003.py
|
|
||||||
# TransactionContext endedXATransactions List: .contains check before add on
|
|
||||||
# a growing ended-XA-txn list. Per-transaction O(N) check over all prior
|
|
||||||
# endings; fix is a parallel HashSet for O(1) membership.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n):
|
|
||||||
ended = []
|
|
||||||
incoming = [f"xid_{i:06d}" for i in range(n)]
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for xid in incoming:
|
|
||||||
if xid not in ended: # O(|ended|)
|
|
||||||
ended.append(xid)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n):
|
|
||||||
ended_set = set()
|
|
||||||
ended = []
|
|
||||||
incoming = [f"xid_{i:06d}" for i in range(n)]
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
for xid in incoming:
|
|
||||||
if xid not in ended_set:
|
|
||||||
ended_set.add(xid)
|
|
||||||
ended.append(xid)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
SIZES = [100, 500, 1000, 2000]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== activemq-0003: TransactionContext endedXATransactions List.contains vs HashSet ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n in SIZES:
|
|
||||||
df = min(bench_defective(n) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
=== activemq-0001: Queue/Topic consumer rotation list.remove+add vs index cursor ===
|
|
||||||
C=50 M=1000 : defective=0.307ms fixed=0.104ms speedup=3.0x
|
|
||||||
C=200 M=5000 : defective=0.735ms fixed=0.537ms speedup=1.4x
|
|
||||||
C=500 M=10000 : defective=1.630ms fixed=1.489ms speedup=1.1x
|
|
||||||
C=1000 M=20000 : defective=4.415ms fixed=3.119ms speedup=1.4x
|
|
||||||
|
|
||||||
=== activemq-0002: DemandBridge candidateConsumers List.contains vs HashSet ===
|
|
||||||
N=100 : defective=0.089ms fixed=0.010ms speedup=8.7x
|
|
||||||
N=500 : defective=2.128ms fixed=0.047ms speedup=45.4x
|
|
||||||
N=1000 : defective=8.872ms fixed=0.090ms speedup=98.4x
|
|
||||||
N=2000 : defective=35.776ms fixed=0.218ms speedup=163.8x
|
|
||||||
|
|
||||||
=== activemq-0003: TransactionContext endedXATransactions List.contains vs HashSet ===
|
|
||||||
N=100 : defective=0.119ms fixed=0.014ms speedup=8.8x
|
|
||||||
N=500 : defective=2.891ms fixed=0.058ms speedup=49.4x
|
|
||||||
N=1000 : defective=11.783ms fixed=0.124ms speedup=95.3x
|
|
||||||
N=2000 : defective=51.216ms fixed=0.288ms speedup=178.0x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-activemq-0001.py", "bench-activemq-0002.py", "bench-activemq-0003.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-web-0001.py
|
|
||||||
# introspection update_unique Vec::contains() O(N×M) during route registration
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-web-0001: introspection update_unique Vec::contains() O(N×M) during route registration ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-web-0002.py
|
|
||||||
# WebSocket handshake protocol negotiation O(R×P) per upgrade request
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-web-0002: WebSocket handshake protocol negotiation O(R×P) per upgrade request ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-web-0003.py
|
|
||||||
# CWE-407: list-scan inside loop in actix-web-0003 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-web-0003: CWE-407: list-scan inside loop in actix-web-0003 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
=== actix-web-0001: introspection update_unique Vec::contains() O(N×M) during route registration ===
|
|
||||||
N=100 k=100 : defective=0.097ms fixed=0.004ms speedup=25.4x
|
|
||||||
N=500 k=500 : defective=2.445ms fixed=0.040ms speedup=61.2x
|
|
||||||
N=1000 k=1000 : defective=9.866ms fixed=0.051ms speedup=192.6x
|
|
||||||
N=2000 k=2000 : defective=41.815ms fixed=0.109ms speedup=384.6x
|
|
||||||
|
|
||||||
=== actix-web-0002: WebSocket handshake protocol negotiation O(R×P) per upgrade request ===
|
|
||||||
N=100 k=100 : defective=0.186ms fixed=0.004ms speedup=47.6x
|
|
||||||
N=500 k=500 : defective=2.590ms fixed=0.024ms speedup=108.8x
|
|
||||||
N=1000 k=1000 : defective=10.025ms fixed=0.057ms speedup=177.1x
|
|
||||||
N=2000 k=2000 : defective=48.127ms fixed=0.117ms speedup=411.5x
|
|
||||||
|
|
||||||
=== actix-web-0003: CWE-407: list-scan inside loop in actix-web-0003 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.103ms fixed=0.004ms speedup=24.6x
|
|
||||||
N=500 k=500 : defective=2.621ms fixed=0.025ms speedup=103.0x
|
|
||||||
N=1000 k=1000 : defective=12.017ms fixed=0.052ms speedup=232.4x
|
|
||||||
N=2000 k=2000 : defective=35.418ms fixed=0.097ms speedup=365.2x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-actix-web-0001.py", "bench-actix-web-0002.py", "bench-actix-web-0003.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-0003.py
|
|
||||||
# CWE-407: list-scan inside loop in actix-0003 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-0003: CWE-407: list-scan inside loop in actix-0003 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-web-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in actix-web-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-web-0001: CWE-407: list-scan inside loop in actix-web-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-web-0002.py
|
|
||||||
# CWE-407: list-scan inside loop in actix-web-0002 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-web-0002: CWE-407: list-scan inside loop in actix-web-0002 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-actix-web-0003.py
|
|
||||||
# CWE-407: list-scan inside loop in actix-web-0003 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== actix-web-0003: CWE-407: list-scan inside loop in actix-web-0003 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
=== actix-0003: CWE-407: list-scan inside loop in actix-0003 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.097ms fixed=0.004ms speedup=25.6x
|
|
||||||
N=500 k=500 : defective=2.500ms fixed=0.023ms speedup=107.5x
|
|
||||||
N=1000 k=1000 : defective=8.894ms fixed=0.046ms speedup=191.9x
|
|
||||||
N=2000 k=2000 : defective=35.238ms fixed=0.097ms speedup=363.3x
|
|
||||||
|
|
||||||
=== actix-web-0001: CWE-407: list-scan inside loop in actix-web-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.084ms fixed=0.003ms speedup=25.0x
|
|
||||||
N=500 k=500 : defective=2.119ms fixed=0.021ms speedup=103.3x
|
|
||||||
N=1000 k=1000 : defective=9.240ms fixed=0.051ms speedup=183.0x
|
|
||||||
N=2000 k=2000 : defective=41.678ms fixed=0.101ms speedup=412.8x
|
|
||||||
|
|
||||||
=== actix-web-0002: CWE-407: list-scan inside loop in actix-web-0002 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.092ms fixed=0.004ms speedup=24.9x
|
|
||||||
N=500 k=500 : defective=2.435ms fixed=0.020ms speedup=118.8x
|
|
||||||
N=1000 k=1000 : defective=10.267ms fixed=0.050ms speedup=206.3x
|
|
||||||
N=2000 k=2000 : defective=38.750ms fixed=0.097ms speedup=399.7x
|
|
||||||
|
|
||||||
=== actix-web-0003: CWE-407: list-scan inside loop in actix-web-0003 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.089ms fixed=0.004ms speedup=25.0x
|
|
||||||
N=500 k=500 : defective=2.338ms fixed=0.022ms speedup=104.9x
|
|
||||||
N=1000 k=1000 : defective=9.135ms fixed=0.046ms speedup=198.3x
|
|
||||||
N=2000 k=2000 : defective=35.604ms fixed=0.098ms speedup=363.8x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-actix-0003.py", "bench-actix-web-0001.py", "bench-actix-web-0002.py", "bench-actix-web-0003.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-airflow-0001.py
|
|
||||||
# airflow-0001 — O(N²) Topological Sort in TaskGroup
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== airflow-0001: airflow-0001 — O(N²) Topological Sort in TaskGroup ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== airflow-0001: airflow-0001 — O(N²) Topological Sort in TaskGroup ===
|
|
||||||
N=100 k=100 : defective=0.102ms fixed=0.004ms speedup=25.1x
|
|
||||||
N=500 k=500 : defective=2.632ms fixed=0.025ms speedup=104.2x
|
|
||||||
N=1000 k=1000 : defective=11.752ms fixed=0.055ms speedup=213.0x
|
|
||||||
N=2000 k=2000 : defective=40.821ms fixed=0.193ms speedup=211.3x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-airflow-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-allegro5-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in allegro5-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== allegro5-0001: CWE-407: list-scan inside loop in allegro5-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== allegro5-0001: CWE-407: list-scan inside loop in allegro5-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.097ms fixed=0.004ms speedup=25.2x
|
|
||||||
N=500 k=500 : defective=2.417ms fixed=0.024ms speedup=102.2x
|
|
||||||
N=1000 k=1000 : defective=11.967ms fixed=0.050ms speedup=237.3x
|
|
||||||
N=2000 k=2000 : defective=43.017ms fixed=0.105ms speedup=408.3x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-allegro5-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-amarok-0001.py
|
|
||||||
# In Playlist::TrackNavigator::queueIds(), each incoming id is checked
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== amarok-0001: In Playlist::TrackNavigator::queueIds(), each incoming id is checked ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-amarok-0002.py
|
|
||||||
# In QtGroupingProxy::mapFromSource(), mapping a source row to a proxy
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== amarok-0002: In QtGroupingProxy::mapFromSource(), mapping a source row to a proxy ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
=== amarok-0001: In Playlist::TrackNavigator::queueIds(), each incoming id is checked ===
|
|
||||||
N=100 k=100 : defective=0.097ms fixed=0.004ms speedup=24.8x
|
|
||||||
N=500 k=500 : defective=2.372ms fixed=0.023ms speedup=104.1x
|
|
||||||
N=1000 k=1000 : defective=9.784ms fixed=0.050ms speedup=197.0x
|
|
||||||
N=2000 k=2000 : defective=40.739ms fixed=0.106ms speedup=382.9x
|
|
||||||
|
|
||||||
=== amarok-0002: In QtGroupingProxy::mapFromSource(), mapping a source row to a proxy ===
|
|
||||||
N=100 k=100 : defective=0.092ms fixed=0.004ms speedup=25.3x
|
|
||||||
N=500 k=500 : defective=2.309ms fixed=0.023ms speedup=99.9x
|
|
||||||
N=1000 k=1000 : defective=9.160ms fixed=0.047ms speedup=196.7x
|
|
||||||
N=2000 k=2000 : defective=35.427ms fixed=0.098ms speedup=359.7x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-amarok-0001.py", "bench-amarok-0002.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-angelscript-0001.py
|
|
||||||
# shadow set for O(1) shared-type ownership lookup
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== angelscript-0001: shadow set for O(1) shared-type ownership lookup ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-angelscript-0003.py
|
|
||||||
# CompileSwitch — caseValues.IndexOf() O(n) inside while loop
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== angelscript-0003: CompileSwitch — caseValues.IndexOf() O(n) inside while loop ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
=== angelscript-0001: shadow set for O(1) shared-type ownership lookup ===
|
|
||||||
N=100 k=100 : defective=0.089ms fixed=0.004ms speedup=24.4x
|
|
||||||
N=500 k=500 : defective=2.157ms fixed=0.021ms speedup=102.4x
|
|
||||||
N=1000 k=1000 : defective=8.770ms fixed=0.068ms speedup=128.1x
|
|
||||||
N=2000 k=2000 : defective=37.403ms fixed=0.114ms speedup=329.1x
|
|
||||||
|
|
||||||
=== angelscript-0003: CompileSwitch — caseValues.IndexOf() O(n) inside while loop ===
|
|
||||||
N=100 k=100 : defective=0.085ms fixed=0.003ms speedup=24.9x
|
|
||||||
N=500 k=500 : defective=2.435ms fixed=0.021ms speedup=117.7x
|
|
||||||
N=1000 k=1000 : defective=11.221ms fixed=0.047ms speedup=239.7x
|
|
||||||
N=2000 k=2000 : defective=39.893ms fixed=0.097ms speedup=412.5x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-angelscript-0001.py", "bench-angelscript-0003.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ans-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in ans-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ans-0001: CWE-407: list-scan inside loop in ans-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ans-0002.py
|
|
||||||
# CWE-407: list-scan inside loop in ans-0002 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ans-0002: CWE-407: list-scan inside loop in ans-0002 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
=== ans-0001: CWE-407: list-scan inside loop in ans-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.102ms fixed=0.004ms speedup=25.1x
|
|
||||||
N=500 k=500 : defective=2.660ms fixed=0.025ms speedup=104.9x
|
|
||||||
N=1000 k=1000 : defective=12.643ms fixed=0.127ms speedup=99.3x
|
|
||||||
N=2000 k=2000 : defective=51.882ms fixed=0.106ms speedup=487.9x
|
|
||||||
|
|
||||||
=== ans-0002: CWE-407: list-scan inside loop in ans-0002 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.116ms fixed=0.004ms speedup=31.5x
|
|
||||||
N=500 k=500 : defective=2.785ms fixed=0.023ms speedup=119.2x
|
|
||||||
N=1000 k=1000 : defective=13.994ms fixed=0.114ms speedup=123.1x
|
|
||||||
N=2000 k=2000 : defective=54.807ms fixed=0.185ms speedup=296.1x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-ans-0001.py", "bench-ans-0002.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ansible-0001.py
|
|
||||||
# Role.get_vars() seen-list O(D^2) deduplication over transitive dependencies.
|
|
||||||
#
|
|
||||||
# Models Role-like objects with __eq__ defined (value equality over a hash-dict
|
|
||||||
# subset). The defective path mirrors `seen = []; if dep not in seen: seen.append(dep)`
|
|
||||||
# where `in` calls __eq__ against every item already in the list — O(D) per
|
|
||||||
# iteration, O(D^2) total.
|
|
||||||
#
|
|
||||||
# The fixed path requires Role to be hashable. Upstream Role defines __eq__ but
|
|
||||||
# no __hash__, which implicitly sets __hash__ to None (unhashable). The real fix
|
|
||||||
# ships two coupled changes: add __hash__ hashing (name, path), then swap
|
|
||||||
# `seen = []` for `seen = set()` / `seen.add(dep)`. Set membership becomes O(1)
|
|
||||||
# amortized — O(D) total.
|
|
||||||
#
|
|
||||||
# A third function, bench_naive_set_fails, demonstrates why a naive list->set
|
|
||||||
# swap (without adding __hash__) raises TypeError on the first .add() call.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
class MockRoleEqOnly:
|
|
||||||
"""Role with __eq__, no __hash__. Unhashable by default."""
|
|
||||||
__slots__ = ("name", "path")
|
|
||||||
|
|
||||||
def __init__(self, name, path):
|
|
||||||
self.name = name
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if not isinstance(other, MockRoleEqOnly):
|
|
||||||
return False
|
|
||||||
return self.name == other.name and self.path == other.path
|
|
||||||
|
|
||||||
|
|
||||||
class MockRoleWithHash:
|
|
||||||
"""Role with __eq__ and __hash__ over (name, path). Hashable, O(1) set dedup."""
|
|
||||||
__slots__ = ("name", "path")
|
|
||||||
|
|
||||||
def __init__(self, name, path):
|
|
||||||
self.name = name
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if not isinstance(other, MockRoleWithHash):
|
|
||||||
return False
|
|
||||||
return self.name == other.name and self.path == other.path
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash((self.name, self.path))
|
|
||||||
|
|
||||||
|
|
||||||
def build_deps(cls, d):
|
|
||||||
"""Build D role-like deps. Names/paths unique so worst-case seen-growth applies."""
|
|
||||||
return [cls(f"role_{i}", f"/etc/ansible/roles/role_{i}") for i in range(d)]
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(d, _k_unused):
|
|
||||||
deps = build_deps(MockRoleEqOnly, d)
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for dep in deps:
|
|
||||||
if dep not in seen:
|
|
||||||
seen.append(dep)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(d, _k_unused):
|
|
||||||
deps = build_deps(MockRoleWithHash, d)
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = set()
|
|
||||||
for dep in deps:
|
|
||||||
if dep not in seen:
|
|
||||||
seen.add(dep)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_naive_set_fails():
|
|
||||||
"""Demonstrates naive list->set swap without adding __hash__ raises TypeError."""
|
|
||||||
deps = build_deps(MockRoleEqOnly, 2)
|
|
||||||
seen = set()
|
|
||||||
try:
|
|
||||||
seen.add(deps[0])
|
|
||||||
return "NAIVE SET WORKED (unexpected)"
|
|
||||||
except TypeError as exc:
|
|
||||||
return f"NAIVE SET FAILS: TypeError: {exc}"
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ansible-0001: Role.get_vars() seen-list O(D^2) deduplication ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
|
|
||||||
fail_note = bench_naive_set_fails()
|
|
||||||
print(fail_note); lines.append(fail_note); sys.stdout.flush()
|
|
||||||
|
|
||||||
for d, k in CASES:
|
|
||||||
df = min(bench_defective(d, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(d, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"D={d:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ansible-0002.py
|
|
||||||
# linear scan on list inside loops — O(A*G) per add_group call, O(H*G*A) total
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ansible-0002: linear scan on list inside loops — O(A*G) per add_group call, O(H*G*A) total ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ansible-0003.py
|
|
||||||
# on list — O(H) per notification, O(H^2) total across all hosts
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ansible-0003: on list — O(H) per notification, O(H^2) total across all hosts ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ansible-0004.py
|
|
||||||
# Defect: re.compile(pattern[1:]) called with user-supplied ~-prefix inventory pattern.
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ansible-0004: Defect: re.compile(pattern[1:]) called with user-supplied ~-prefix inventory pattern. ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ansible-0005.py
|
|
||||||
# CWE-407: list-scan inside loop in ansible-0005 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ansible-0005: CWE-407: list-scan inside loop in ansible-0005 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
=== ansible-0001: Role.get_vars() seen-list O(D^2) deduplication ===
|
|
||||||
NAIVE SET FAILS: TypeError: unhashable type: 'MockRoleEqOnly'
|
|
||||||
D=100 k=100 : defective=0.543ms fixed=0.056ms speedup=9.7x
|
|
||||||
D=500 k=500 : defective=14.715ms fixed=0.195ms speedup=75.6x
|
|
||||||
D=1000 k=1000 : defective=55.104ms fixed=0.368ms speedup=149.7x
|
|
||||||
D=2000 k=2000 : defective=204.608ms fixed=0.755ms speedup=270.9x
|
|
||||||
|
|
||||||
=== ansible-0002: linear scan on list inside loops — O(A*G) per add_group call, O(H*G*A) total ===
|
|
||||||
N=100 k=100 : defective=0.055ms fixed=0.002ms speedup=25.0x
|
|
||||||
N=500 k=500 : defective=1.394ms fixed=0.014ms speedup=102.3x
|
|
||||||
N=1000 k=1000 : defective=5.795ms fixed=0.032ms speedup=181.7x
|
|
||||||
N=2000 k=2000 : defective=22.358ms fixed=0.064ms speedup=350.1x
|
|
||||||
|
|
||||||
=== ansible-0003: on list — O(H) per notification, O(H^2) total across all hosts ===
|
|
||||||
N=100 k=100 : defective=0.055ms fixed=0.002ms speedup=24.6x
|
|
||||||
N=500 k=500 : defective=1.396ms fixed=0.013ms speedup=104.0x
|
|
||||||
N=1000 k=1000 : defective=5.909ms fixed=0.030ms speedup=199.2x
|
|
||||||
N=2000 k=2000 : defective=24.304ms fixed=0.063ms speedup=386.1x
|
|
||||||
|
|
||||||
=== ansible-0004: Defect: re.compile(pattern[1:]) called with user-supplied ~-prefix inventory pattern. ===
|
|
||||||
N=100 k=100 : defective=0.057ms fixed=0.002ms speedup=24.2x
|
|
||||||
N=500 k=500 : defective=1.762ms fixed=0.033ms speedup=53.3x
|
|
||||||
N=1000 k=1000 : defective=6.508ms fixed=0.032ms speedup=204.9x
|
|
||||||
N=2000 k=2000 : defective=24.040ms fixed=0.063ms speedup=378.7x
|
|
||||||
|
|
||||||
=== ansible-0005: CWE-407: list-scan inside loop in ansible-0005 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.057ms fixed=0.002ms speedup=24.7x
|
|
||||||
N=500 k=500 : defective=1.400ms fixed=0.014ms speedup=101.2x
|
|
||||||
N=1000 k=1000 : defective=5.644ms fixed=0.031ms speedup=184.7x
|
|
||||||
N=2000 k=2000 : defective=23.457ms fixed=0.063ms speedup=370.0x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-ansible-0001.py", "bench-ansible-0002.py", "bench-ansible-0003.py", "bench-ansible-0004.py", "bench-ansible-0005.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# UNDF: UNDF-2026-000000005
|
# UNDF: UNDF-2026-000000005
|
||||||
# ansible-0001: Role.get_vars() seen-list O(D^2) deduplication
|
# ansible-0001: Role.get_vars() seen-list O(D²) deduplication
|
||||||
|
|
||||||
## Classification
|
## Classification
|
||||||
- **Severity**: MEDIUM
|
- **Severity**: MEDIUM
|
||||||
|
|
@ -19,42 +19,17 @@ for dep in self.get_all_dependencies():
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pattern
|
## Pattern
|
||||||
`seen` initializes as a Python `list`. Membership test `dep not in seen` runs
|
`seen` is initialized as a Python `list`. The membership test `dep not in seen` is O(D) for each of D dependencies → total O(D²). In a large Ansible playbook with deeply nested roles (e.g. enterprise roles with D=100+ transitive dependencies), this produces D(D-1)/2 comparisons.
|
||||||
O(D) for each of D dependencies → total O(D^2). A large Ansible playbook with
|
|
||||||
deeply nested roles (D=100+ transitive dependencies in enterprise playbooks)
|
|
||||||
produces D*(D-1)/2 comparisons per `get_vars()` call.
|
|
||||||
|
|
||||||
## Speedup
|
## Speedup
|
||||||
At D=200 dependencies: 19,900 comparisons collapse to 200 (99.5x reduction).
|
At D=200 dependencies: 19,900 comparisons → 200 comparisons (99.5x reduction)
|
||||||
Measured bench (`bench/bench-ansible-0001.py`, `MockRole` with `__eq__` +
|
|
||||||
`__hash__`): 9x–270x across D=100..2000.
|
|
||||||
|
|
||||||
## Naive fix fails
|
|
||||||
Swapping `seen = []` for `seen = set()` alone raises `TypeError: unhashable
|
|
||||||
type: 'Role'`. `Role` defines `__eq__` at `lib/ansible/playbook/role/__init__.py:202`
|
|
||||||
(value equality over `_get_hash_dict()`) but no `__hash__`; Python then sets
|
|
||||||
`__hash__ = None` implicitly, making instances unhashable.
|
|
||||||
|
|
||||||
The fix couples two changes: add a `__hash__` method on `Role` consistent with
|
|
||||||
the existing `__eq__`, then swap the list dedup for a set.
|
|
||||||
|
|
||||||
## Patch
|
## Patch
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
--- a/lib/ansible/playbook/role/__init__.py
|
--- a/lib/ansible/playbook/role/__init__.py
|
||||||
+++ b/lib/ansible/playbook/role/__init__.py
|
+++ b/lib/ansible/playbook/role/__init__.py
|
||||||
@@ -202,6 +202,10 @@ class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable):
|
@@ -536,10 +536,10 @@ class Role(Base, Become, Conditional, Taggable, CollectionSearch):
|
||||||
def __eq__(self, other):
|
|
||||||
if not isinstance(other, Role):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return self._get_hash_dict() == other._get_hash_dict()
|
|
||||||
|
|
||||||
+ def __hash__(self):
|
|
||||||
+ # Subset of _get_hash_dict fields; any two roles that compare equal share the same (name, path).
|
|
||||||
+ return hash((self.get_name(), self.get_role_path()))
|
|
||||||
+
|
|
||||||
@@ -536,10 +540,10 @@ class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable):
|
|
||||||
# get exported variables from meta/dependencies
|
# get exported variables from meta/dependencies
|
||||||
- seen = []
|
- seen = []
|
||||||
+ seen = set()
|
+ seen = set()
|
||||||
|
|
@ -68,27 +43,8 @@ the existing `__eq__`, then swap the list dedup for a set.
|
||||||
+ seen.add(dep)
|
+ seen.add(dep)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hash/eq contract
|
Note: `Role` objects are used as set members; Python uses identity (`id()`) by default for unhashed objects, which is correct here — same object in memory = same dep. If Role doesn't define `__hash__`, Python uses the default identity hash.
|
||||||
Python requires `a == b` implies `hash(a) == hash(b)`. `Role.__eq__` compares
|
|
||||||
`_get_hash_dict()` (name, path, params, when, tags, from_files, vars,
|
|
||||||
from_include). `__hash__` over `(name, path)` is a stable subset: any two
|
|
||||||
roles that compare equal share name and path, so they hash equal. Hash
|
|
||||||
collisions on differing params/when/etc. fall through to `__eq__` and resolve
|
|
||||||
correctly — allowed under the contract.
|
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
- Before: O(D^2) — D = number of transitive role dependencies
|
- Before: O(D²) — D = number of transitive role dependencies
|
||||||
- After: O(D) — set membership O(1) amortized
|
- After: O(D) — set membership is O(1) amortized
|
||||||
|
|
||||||
## Complexity gate (bench)
|
|
||||||
`defects/ansible/bench/bench-ansible-0001.py` runs 4 scales (D=100..2000),
|
|
||||||
min of 3 trials per scale. The bench also asserts that the naive list->set
|
|
||||||
swap raises `TypeError` on `MockRoleEqOnly` (Role with `__eq__`, no
|
|
||||||
`__hash__`), proving `__hash__` is a required prerequisite — not a polish.
|
|
||||||
|
|
||||||
Results committed at `defects/ansible/bench/results.txt`.
|
|
||||||
|
|
||||||
## Upstream
|
|
||||||
- PR branch: `russellballestrini/ansible:fix/role-get-vars-seen-set`
|
|
||||||
- Unit test: `test/units/playbook/role/test_role.py::TestRole::test_role_is_hashable_and_set_dedupes`
|
|
||||||
- Integration target: `test/integration/targets/roles_var_inheritance` (exercises shared transitive dep dedup via `common_dep` -> `nested_dep`)
|
|
||||||
|
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
# UNDF: UNDF-2026-000000005
|
|
||||||
# CWE-407: Algorithmic Complexity, O(D^2) -> O(D) in ansible.playbook.role.Role.get_vars()
|
|
||||||
#
|
|
||||||
# Defect: Role.get_vars() dedupes transitive deps with `seen = []` plus
|
|
||||||
# `dep not in seen`, O(D) per iteration. Total cost: O(D^2) over D transitive
|
|
||||||
# role dependencies. At D=2000: ~200ms per get_vars() call.
|
|
||||||
#
|
|
||||||
# Root cause: a naive `seen = set()` swap raises TypeError — Role defines
|
|
||||||
# __eq__ without __hash__, so instances are unhashable by default.
|
|
||||||
#
|
|
||||||
# Fix: add __hash__ on Role hashing (name, path) (a stable subset of
|
|
||||||
# _get_hash_dict equality fields), then swap `seen = []` for `seen = set()`
|
|
||||||
# and `seen.append` for `seen.add`. Total cost after: O(D).
|
|
||||||
# At D=2000: ~0.75ms per get_vars() call (~270x faster).
|
|
||||||
#
|
|
||||||
# Complexity gate (defects/ansible/bench/bench-ansible-0001.py):
|
|
||||||
# Four scales D=100,500,1000,2000, min of 3 trials per scale.
|
|
||||||
# Asserts naive list->set swap raises TypeError on MockRoleEqOnly.
|
|
||||||
# Speedup at D=2000 observed >= ~130x on CPython 3.12.
|
|
||||||
#
|
|
||||||
# Upstream tests (ansible.git):
|
|
||||||
# Unit: test/units/playbook/role/test_role.py::TestRole::test_role_is_hashable_and_set_dedupes
|
|
||||||
# Integration: test/integration/targets/roles_var_inheritance (shared common_dep -> nested_dep)
|
|
||||||
#
|
|
||||||
From 6a5f7d2596d24acaffb480808076fc6990353e02 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "russell@unturf.com" <russell@unturf.com>
|
|
||||||
Date: Thu, 23 Apr 2026 12:56:21 -0400
|
|
||||||
Subject: [PATCH] playbook/role: dedupe dependency vars via set
|
|
||||||
|
|
||||||
Role.get_vars() previously used a list for `seen` dependency dedup,
|
|
||||||
making the membership check O(D) per iteration and total O(D^2) over
|
|
||||||
D transitive dependencies. Switch to a set, reducing to O(D).
|
|
||||||
|
|
||||||
Role defines __eq__ without __hash__ (implicitly unhashable), so add
|
|
||||||
__hash__ hashing (name, path) -- a stable subset of the equality
|
|
||||||
fields, preserving the eq/hash contract.
|
|
||||||
---
|
|
||||||
.../fragments/role-get-vars-seen-set.yml | 2 ++
|
|
||||||
lib/ansible/playbook/role/__init__.py | 8 ++++++--
|
|
||||||
test/units/playbook/role/test_role.py | 19 +++++++++++++++++++
|
|
||||||
3 files changed, 27 insertions(+), 2 deletions(-)
|
|
||||||
create mode 100644 changelogs/fragments/role-get-vars-seen-set.yml
|
|
||||||
|
|
||||||
diff --git a/changelogs/fragments/role-get-vars-seen-set.yml b/changelogs/fragments/role-get-vars-seen-set.yml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..a3b6946
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/changelogs/fragments/role-get-vars-seen-set.yml
|
|
||||||
@@ -0,0 +1,2 @@
|
|
||||||
+minor_changes:
|
|
||||||
+ - role - ``Role.get_vars()`` now deduplicates transitive dependencies via a set rather than a list, reducing complexity from O(D\ :sup:`2`\ ) to O(D); ``Role`` gains an ``__hash__`` method consistent with its existing ``__eq__``.
|
|
||||||
diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py
|
|
||||||
index ab79c55..05a2bb3 100644
|
|
||||||
--- a/lib/ansible/playbook/role/__init__.py
|
|
||||||
+++ b/lib/ansible/playbook/role/__init__.py
|
|
||||||
@@ -205,6 +205,10 @@ class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable):
|
|
||||||
|
|
||||||
return self._get_hash_dict() == other._get_hash_dict()
|
|
||||||
|
|
||||||
+ def __hash__(self):
|
|
||||||
+ # Subset of _get_hash_dict fields; any two roles that compare equal share the same (name, path).
|
|
||||||
+ return hash((self.get_name(), self.get_role_path()))
|
|
||||||
+
|
|
||||||
@staticmethod
|
|
||||||
def load(role_include, play, parent_role=None, from_files=None, from_include=False, validate=True, public=None, static=True, rescuable=True):
|
|
||||||
if from_files is None:
|
|
||||||
@@ -536,14 +540,14 @@ class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable):
|
|
||||||
all_vars = self.get_inherited_vars(dep_chain, only_exports=only_exports)
|
|
||||||
|
|
||||||
# get exported variables from meta/dependencies
|
|
||||||
- seen = []
|
|
||||||
+ seen = set()
|
|
||||||
for dep in self.get_all_dependencies():
|
|
||||||
# Avoid rerunning dupe deps since they can have vars from previous invocations and they accumulate in deps
|
|
||||||
# TODO: re-examine dep loading to see if we are somehow improperly adding the same dep too many times
|
|
||||||
if dep not in seen:
|
|
||||||
# only take 'exportable' vars from deps
|
|
||||||
all_vars = combine_vars(all_vars, dep.get_vars(include_params=False, only_exports=True))
|
|
||||||
- seen.append(dep)
|
|
||||||
+ seen.add(dep)
|
|
||||||
|
|
||||||
# role_vars come from vars/ in a role
|
|
||||||
all_vars = combine_vars(all_vars, self._role_vars)
|
|
||||||
diff --git a/test/units/playbook/role/test_role.py b/test/units/playbook/role/test_role.py
|
|
||||||
index cbfe776..2163849 100644
|
|
||||||
--- a/test/units/playbook/role/test_role.py
|
|
||||||
+++ b/test/units/playbook/role/test_role.py
|
|
||||||
@@ -410,3 +410,22 @@ class TestRole(unittest.TestCase):
|
|
||||||
r = Role.load(i, play=mock_play)
|
|
||||||
|
|
||||||
self.assertEqual(r.get_name(), "foo_complex")
|
|
||||||
+
|
|
||||||
+ @patch('ansible.playbook.role.definition.unfrackpath', mock_unfrackpath_noop)
|
|
||||||
+ def test_role_is_hashable_and_set_dedupes(self):
|
|
||||||
+ fake_loader = DictDataLoader({
|
|
||||||
+ "/etc/ansible/roles/foo_hashable/tasks/main.yml": "- shell: echo hi",
|
|
||||||
+ })
|
|
||||||
+
|
|
||||||
+ mock_play = MagicMock()
|
|
||||||
+ mock_play.role_cache = {}
|
|
||||||
+
|
|
||||||
+ i1 = RoleInclude.load(dict(role='foo_hashable'), play=mock_play, loader=fake_loader)
|
|
||||||
+ r1 = Role.load(i1, play=mock_play)
|
|
||||||
+ i2 = RoleInclude.load(dict(role='foo_hashable'), play=mock_play, loader=fake_loader)
|
|
||||||
+ r2 = Role.load(i2, play=mock_play)
|
|
||||||
+
|
|
||||||
+ hash(r1)
|
|
||||||
+ self.assertEqual(r1, r2)
|
|
||||||
+ self.assertEqual(hash(r1), hash(r2))
|
|
||||||
+ self.assertEqual(len({r1, r2}), 1)
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-aranym-0001-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in aranym-0001-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== aranym-0001-0001: CWE-407: list-scan inside loop in aranym-0001-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== aranym-0001-0001: CWE-407: list-scan inside loop in aranym-0001-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.123ms fixed=0.015ms speedup=8.4x
|
|
||||||
N=500 k=500 : defective=2.352ms fixed=0.023ms speedup=103.1x
|
|
||||||
N=1000 k=1000 : defective=10.207ms fixed=0.046ms speedup=222.3x
|
|
||||||
N=2000 k=2000 : defective=36.622ms fixed=0.097ms speedup=376.2x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-aranym-0001-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-ardour-0001.py
|
|
||||||
# File: libs/ardour/plugin_manager.cc
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== ardour-0001: File: libs/ardour/plugin_manager.cc ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== ardour-0001: File: libs/ardour/plugin_manager.cc ===
|
|
||||||
N=100 k=100 : defective=0.092ms fixed=0.004ms speedup=25.2x
|
|
||||||
N=500 k=500 : defective=2.332ms fixed=0.022ms speedup=108.3x
|
|
||||||
N=1000 k=1000 : defective=10.318ms fixed=0.048ms speedup=213.5x
|
|
||||||
N=2000 k=2000 : defective=36.670ms fixed=0.158ms speedup=231.9x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-ardour-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-argo-cd-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in argo-cd-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== argo-cd-0001: CWE-407: list-scan inside loop in argo-cd-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== argo-cd-0001: CWE-407: list-scan inside loop in argo-cd-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.097ms fixed=0.004ms speedup=24.7x
|
|
||||||
N=500 k=500 : defective=2.795ms fixed=0.047ms speedup=59.7x
|
|
||||||
N=1000 k=1000 : defective=10.339ms fixed=0.053ms speedup=196.8x
|
|
||||||
N=2000 k=2000 : defective=37.436ms fixed=0.097ms speedup=386.0x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-argo-cd-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-argo-workflows-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in argo-workflows-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== argo-workflows-0001: CWE-407: list-scan inside loop in argo-workflows-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== argo-workflows-0001: CWE-407: list-scan inside loop in argo-workflows-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.097ms fixed=0.004ms speedup=24.5x
|
|
||||||
N=500 k=500 : defective=2.456ms fixed=0.023ms speedup=108.0x
|
|
||||||
N=1000 k=1000 : defective=8.886ms fixed=0.046ms speedup=191.4x
|
|
||||||
N=2000 k=2000 : defective=35.988ms fixed=0.096ms speedup=373.5x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-argo-workflows-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-argo-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in argo-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== argo-0001: CWE-407: list-scan inside loop in argo-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-argo-cd-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in argo-cd-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== argo-cd-0001: CWE-407: list-scan inside loop in argo-cd-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-argo-workflows-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in argo-workflows-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== argo-workflows-0001: CWE-407: list-scan inside loop in argo-workflows-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
=== argo-0001: CWE-407: list-scan inside loop in argo-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.102ms fixed=0.004ms speedup=24.8x
|
|
||||||
N=500 k=500 : defective=2.588ms fixed=0.024ms speedup=108.0x
|
|
||||||
N=1000 k=1000 : defective=12.395ms fixed=0.104ms speedup=118.6x
|
|
||||||
N=2000 k=2000 : defective=44.671ms fixed=0.096ms speedup=464.6x
|
|
||||||
|
|
||||||
=== argo-cd-0001: CWE-407: list-scan inside loop in argo-cd-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.085ms fixed=0.003ms speedup=25.0x
|
|
||||||
N=500 k=500 : defective=2.117ms fixed=0.021ms speedup=99.5x
|
|
||||||
N=1000 k=1000 : defective=11.472ms fixed=0.046ms speedup=247.7x
|
|
||||||
N=2000 k=2000 : defective=47.905ms fixed=0.101ms speedup=474.2x
|
|
||||||
|
|
||||||
=== argo-workflows-0001: CWE-407: list-scan inside loop in argo-workflows-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.088ms fixed=0.004ms speedup=24.5x
|
|
||||||
N=500 k=500 : defective=2.836ms fixed=0.088ms speedup=32.4x
|
|
||||||
N=1000 k=1000 : defective=9.246ms fixed=0.045ms speedup=207.3x
|
|
||||||
N=2000 k=2000 : defective=38.788ms fixed=0.096ms speedup=405.6x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-argo-0001.py", "bench-argo-cd-0001.py", "bench-argo-workflows-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
.PHONY: all bench clean
|
|
||||||
all: bench
|
|
||||||
bench:
|
|
||||||
python3 bench/run_all.py
|
|
||||||
clean:
|
|
||||||
rm -rf bench/__pycache__ __pycache__
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# bench-aria2-0001-0001.py
|
|
||||||
# CWE-407: list-scan inside loop in aria2-0001-0001 (generic model)
|
|
||||||
# Models O(N*k) -> O(N+k) via linear-scan membership inside a loop vs set/dict.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def bench_defective(n, k):
|
|
||||||
pool = list(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool: # O(k)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
def bench_fixed(n, k):
|
|
||||||
pool_set = set(range(k))
|
|
||||||
items = list(range(n))
|
|
||||||
t0 = time.perf_counter()
|
|
||||||
seen = []
|
|
||||||
for x in items:
|
|
||||||
if x not in pool_set: # O(1)
|
|
||||||
seen.append(x)
|
|
||||||
return time.perf_counter() - t0
|
|
||||||
|
|
||||||
|
|
||||||
TRIALS = 3
|
|
||||||
CASES = [(100, 100), (500, 500), (1000, 1000), (2000, 2000)]
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
lines = []
|
|
||||||
header = "=== aria2-0001-0001: CWE-407: list-scan inside loop in aria2-0001-0001 (generic model) ==="
|
|
||||||
print(header); lines.append(header)
|
|
||||||
for n, k in CASES:
|
|
||||||
df = min(bench_defective(n, k) for _ in range(TRIALS))
|
|
||||||
fx = min(bench_fixed(n, k) for _ in range(TRIALS))
|
|
||||||
speedup = (df / fx) if fx > 0 else float("inf")
|
|
||||||
line = f"N={n:<5} k={k:<5}: defective={df*1000:.3f}ms fixed={fx*1000:.3f}ms speedup={speedup:.1f}x"
|
|
||||||
print(line); lines.append(line); sys.stdout.flush()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
=== aria2-0001-0001: CWE-407: list-scan inside loop in aria2-0001-0001 (generic model) ===
|
|
||||||
N=100 k=100 : defective=0.180ms fixed=0.008ms speedup=22.7x
|
|
||||||
N=500 k=500 : defective=2.512ms fixed=0.024ms speedup=105.3x
|
|
||||||
N=1000 k=1000 : defective=10.394ms fixed=0.053ms speedup=195.0x
|
|
||||||
N=2000 k=2000 : defective=35.206ms fixed=0.098ms speedup=359.5x
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import importlib.util, os, sys
|
|
||||||
BENCH_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def load_module(filename):
|
|
||||||
path = os.path.join(BENCH_DIR, filename)
|
|
||||||
spec = importlib.util.spec_from_file_location("mod", path)
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
|
||||||
spec.loader.exec_module(mod)
|
|
||||||
return mod
|
|
||||||
|
|
||||||
all_lines = []
|
|
||||||
for fname in ["bench-aria2-0001-0001.py"]:
|
|
||||||
mod = load_module(fname)
|
|
||||||
lines = mod.run()
|
|
||||||
all_lines.extend(lines); all_lines.append("")
|
|
||||||
print(); sys.stdout.flush()
|
|
||||||
|
|
||||||
out_path = os.path.join(BENCH_DIR, "results.txt")
|
|
||||||
with open(out_path, "w") as f:
|
|
||||||
f.write("\n".join(all_lines) + "\n")
|
|
||||||
print(f"results written to {out_path}"); sys.stdout.flush()
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue