java-topology/defects/varnish/unit/VarnishBanCheckAlgorithmTest.java
russell@unturf.com 9934133dcf whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
  HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
        vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
        tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
        allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
        mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
        linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
        perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002

  MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
          cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
          pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
          ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
          r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
          ovs-0001, onos-0003, odl-0002, jetty-0001

PDF: 976K
2026-03-27 15:23:43 -04:00

126 lines
4.3 KiB
Java

package unit;
import java.util.ArrayList;
import java.util.List;
/**
* varnish-0001: BAN_CheckObject O(B) ban list walk vs O(1) pre-filtered check.
*
* slow() models the defect: iterates the full ban list from head to object's
* creation ban, calling ban_evaluate on each non-completed ban.
* fast() models the fix structural improvement: bans are indexed by field type;
* non-applicable bans are skipped in O(1) without calling evaluate.
*
* For benchmarking we model:
* slow: evaluateOps = B (all pending bans checked per object)
* fast: evaluateOps = 1 (only bans that share the object's field type checked)
*
* Assert: slowOps > fastOps * 5 for B=30 bans.
*/
public class VarnishBanCheckAlgorithmTest {
static long slowOps;
static long fastOps;
// ---- simulated ban entry -----------------------------------------------
enum BanField { URL, HEADER_HOST, HEADER_ACCEPT, REQ_ONLY }
static class Ban {
final BanField field;
final String pattern;
boolean completed;
Ban(BanField field, String pattern) {
this.field = field;
this.pattern = pattern;
this.completed = false;
}
}
// ---- simulated cached object -------------------------------------------
static class CachedObject {
final String url;
final int createdAtBanIndex; // object was created when ban list had this many entries
CachedObject(String url, int createdAtBanIndex) {
this.url = url;
this.createdAtBanIndex = createdAtBanIndex;
}
}
// ---- slow: O(B) walk, evaluate every non-completed ban (defect) --------
static boolean slowBanCheck(List<Ban> banList, CachedObject obj) {
// Walk from head (newest) to obj.createdAtBanIndex (exclusive)
for (int i = 0; i < obj.createdAtBanIndex; i++) {
Ban b = banList.get(i);
if (b.completed) continue;
slowOps++; // one evaluate call
if (b.field == BanField.URL && obj.url.startsWith(b.pattern)) {
return true; // object banned
}
}
return false;
}
// ---- fast: O(1) indexed check (fix) ------------------------------------
// Bans indexed by field; only URL bans relevant for URL-keyed objects
static boolean fastBanCheck(List<Ban> urlBans, CachedObject obj) {
for (Ban b : urlBans) {
if (b.completed) continue;
fastOps++; // only URL bans evaluated
if (obj.url.startsWith(b.pattern)) return true;
}
return false;
}
// ---- benchmark driver --------------------------------------------------
public static void main(String[] args) {
final int B = 30; // total pending bans
final int URL_BANS = 3; // only 3 are URL-field bans (the rest are HEADER/REQ)
final int REQUESTS = 5_000;
List<Ban> banList = new ArrayList<>();
List<Ban> urlBanIndex = new ArrayList<>();
// Mix: 3 URL bans, rest HEADER/REQ bans (non-matching)
for (int i = 0; i < B; i++) {
if (i < URL_BANS) {
Ban b = new Ban(BanField.URL, "/static/v" + i + "/");
banList.add(b);
urlBanIndex.add(b);
} else {
banList.add(new Ban(BanField.HEADER_HOST, "example.com"));
}
}
// Object created before any bans were added
CachedObject obj = new CachedObject("/api/data", B);
slowOps = 0;
fastOps = 0;
for (int r = 0; r < REQUESTS; r++) {
slowBanCheck(banList, obj);
}
for (int r = 0; r < REQUESTS; r++) {
fastBanCheck(urlBanIndex, obj);
}
// slow evaluates ALL B bans per object; fast evaluates only URL_BANS
long ratio = slowOps / Math.max(fastOps, 1);
boolean pass = slowOps > fastOps * (B / URL_BANS - 1);
System.out.printf("varnish-0001 slow=%d fast=%d ratio=%dx %s%n",
slowOps, fastOps, ratio, pass ? "PASS" : "FAIL");
if (!pass) {
System.err.printf("FAIL: expected slowOps(%d) > fastOps(%d) * %d%n",
slowOps, fastOps, B / URL_BANS - 1);
System.exit(1);
}
}
}