Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,24 @@ jobs:
find out/ -name "*.json" -mtime +30 -delete 2>/dev/null || true
rm -rf build/ input/

- name: Build corese.next JAR
env:
CORESE_COMMIT: 1215ab78adbfad7f0edc20e212446780a23182c1
run: |
CORESE_DIR="$HOME/corese-next-build"
if [ ! -d "$CORESE_DIR/.git" ]; then
git clone https://github.com/corese-stack/corese-core.git "$CORESE_DIR"
fi
cd "$CORESE_DIR"
git fetch origin feature/corese-next
git checkout "$CORESE_COMMIT"
chmod +x gradlew
./gradlew shadowJar --no-daemon -q
JAR=$(find build/libs -name "*-jar-with-dependencies.jar" | head -1)
mkdir -p "$GITHUB_WORKSPACE/libs"
cp "$JAR" "$GITHUB_WORKSPACE/libs/corese-core-local.jar"
echo "corese.next JAR built from $CORESE_COMMIT → libs/corese-core-local.jar"

- name: Set up conda environment
run: |
CONDA_SH=$(find $HOME -name "conda.sh" -path "*/profile.d/conda.sh" -not -path "*/pkgs/*" 2>/dev/null | head -1)
Expand All @@ -95,8 +113,8 @@ jobs:
source "$CONDA_SH"
conda activate benchmarkenv
python python-utils/workflow.py \
--engines="corese.4.6.5,jena.6.2.0,rdf4j.5.3.2" \
--datasets="dbpedia,bowlogna"
--engines="corese.next,corese.4.6.5,jena.6.2.0,rdf4j.5.3.2" \
--datasets="dbpedia,bowlogna,lubm"

- name: Check site/data output
run: ls -la ./site/data/
Expand Down Expand Up @@ -128,7 +146,7 @@ jobs:
- name: Build corese.next JAR
if: contains(github.event.inputs.engines, 'corese.next')
env:
CORESE_COMMIT: b8dbc158
CORESE_COMMIT: 1215ab78adbfad7f0edc20e212446780a23182c1
run: |
CORESE_DIR="$HOME/corese-next-build"
if [ ! -d "$CORESE_DIR/.git" ]; then
Expand Down
23 changes: 21 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,24 @@ DATASET ?= dbpedia
DATASETS ?= dbpedia,bowlogna,bsbm,lubm
SCALES ?= small

.PHONY: help env regression compare next bowlogna lubm bsbm all site clean-out
# Predefined version sets
ALL_VERSIONS ?= corese.next,corese.4.6.5,jena.6.2.0,jena.6.1.0,rdf4j.5.3.2,rdf4j.5.3.1

.PHONY: help env regression compare next bowlogna lubm bsbm all versions versions-resume corese-all quick site clean-out

help:
@echo ""
@echo " make regression Detect a Corese regression (local vs 4.6.5)"
@echo " make compare Compare corese + jena + rdf4j on dbpedia"
@echo " make next Benchmark corese.next vs corese.4.6.5"
@echo " make versions All versions: corese(next+3) + jena(3) + rdf4j(3)"
@echo " make versions-resume Idem, reprend là où c'était arrêté"
@echo " make corese-all corese.next + corese.4.6.5 sur tous les datasets"
@echo " make bowlogna Bowlogna dataset with SPARQL queries (corese.local vs 4.6.5)"
@echo " make lubm LUBM dataset with SPARQL queries"
@echo " make bsbm BSBM dataset"
@echo " make all All datasets (dbpedia + bowlogna + bsbm + lubm) in one run"
@echo " make quick Quick run (1 rep instead of 3) — faster, less accurate"
@echo " make site Serve the dashboard at http://localhost:8080"
@echo " make env Create conda environment"
@echo " make clean-out Delete all generated reports in out/"
Expand All @@ -41,7 +48,19 @@ compare:
$(PYTHON) $(WORKFLOW) --engines $(ENGINES) --dataset $(DATASET)

next:
$(PYTHON) $(WORKFLOW) --engines corese.next,corese.4.6.5,jena.6.2.0,rdf4j.5.3.2 --datasets dbpedia,bowlogna --scales $(SCALES)
$(PYTHON) $(WORKFLOW) --engines corese.next,corese.4.6.5,jena.6.2.0,rdf4j.5.3.2 --datasets dbpedia,bowlogna,bsbm,lubm --scales $(SCALES)

versions:
$(PYTHON) $(WORKFLOW) --engines $(ALL_VERSIONS) --datasets $(DATASETS) --scales $(SCALES)

versions-resume:
$(PYTHON) $(WORKFLOW) --engines $(ALL_VERSIONS) --datasets $(DATASETS) --scales $(SCALES) --resume

corese-all:
$(PYTHON) $(WORKFLOW) --engines corese.next,corese.4.6.5 --datasets dbpedia,bowlogna,bsbm,lubm --scales $(SCALES)

quick:
$(PYTHON) $(WORKFLOW) --engines $(ENGINES) --datasets $(DATASETS) --scales $(SCALES) --quick

bowlogna:
$(PYTHON) $(WORKFLOW) --engines corese.local,corese.4.6.5 --dataset bowlogna --scales $(SCALES)
Expand Down
81 changes: 64 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ This repository benchmarks Java-based RDF triple stores on loading and SPARQL qu
**Principles:**
- Java 21 harness with a rigorous measurement protocol (warmup + 3 repetitions + median)
- Memory measured as delta before/after loading with forced GC
- SPARQL query benchmark with per-query timeout and warmup
- Automatic JSON + CSV output
- Run history for trend tracking
- Python orchestration for dataset download, build, and deployment

---
Expand All @@ -26,7 +26,19 @@ This repository benchmarks Java-based RDF triple stores on loading and SPARQL qu
The interactive benchmark dashboard is published at:
**[https://corese-stack.github.io/corese-benchmark/](https://corese-stack.github.io/corese-benchmark/)**

To view it locally, open `site/index.html` in a browser.
To view it locally:

```bash
make site # serves at http://localhost:8080
```

**Dashboard features:**
- **Scalability charts** — when a single dataset is selected, Performance charts switch to line charts (X = graph size in triples) showing how each engine scales
- **W3C Conformance** — live pass/fail results fetched from [corese-stack.github.io/corese-w3c](https://corese-stack.github.io/corese-w3c/data/w3c-report.json) (All mode only)
- **Shareable URLs** — state (dataset, engine filter, reference engine) is encoded in the URL (`?ds=dbpedia&engines=corese.4.6.5,jena.6.2.0&ref=corese.4.6.5`)
- **Export CSV** — exports the currently filtered results directly from the browser (Full results section)
- **Engine filter** — click engine cards to filter charts; click × on pills to remove from comparison
- **SPARQL section** — per-engine latency cards, median per query, color-coded comparison table

---

Expand Down Expand Up @@ -120,7 +132,7 @@ python python-utils/workflow.py --coreseCommits a17f3d6,b089a03

### E) Benchmark with SPARQL queries

For datasets that have associated queries (e.g. Bowlogna):
For datasets that have associated queries (Bowlogna, BSBM):

```bash
python python-utils/workflow.py --engines corese.local,corese.4.6.5 --dataset bowlogna
Expand All @@ -130,6 +142,39 @@ The **SPARQL Queries** section appears in the dashboard with:
- Per-engine latency cards: avg, p50, p95, p99
- Median time per query and per engine
- Color-coded comparison table (green = best, orange = ×5–19, red = ×20+)
- `—` indicates timeout or error

---

### F) Resume mode

Resume mode runs one engine × one dataset at a time and skips combinations whose output already contains a valid JSON report. Useful for long runs that may be interrupted:

```bash
python python-utils/workflow.py \
--engines corese.local,corese.4.6.5,jena.6.2.0,rdf4j.5.3.2 \
--datasets dbpedia,bowlogna,bsbm,lubm \
--resume
```

Partial or empty JSON files are automatically re-run (not skipped).

---

### Workflow options

| Option | Default | Description |
|--------|---------|-------------|
| `--engines` | — | Comma-separated engine list (e.g. `corese.4.6.5,jena.6.2.0`) |
| `--dataset` | `dbpedia` | Single dataset: `dbpedia`, `bowlogna`, `bsbm`, `lubm` |
| `--datasets` | — | Multiple datasets in one run (e.g. `dbpedia,bowlogna`) |
| `--scales` | `small,medium,large` | Scale tiers for synthetic datasets |
| `--resume` | off | Skip already-completed engine × dataset pairs |
| `--quick` | off | 1 repetition instead of 3 (faster, less accurate) |
| `--query-timeout` | `30` | Per-query SPARQL timeout in seconds |
| `--inference` | off | Enable RDFS inference for Corese engines |
| `--coreseLocalPath` | auto | Path to corese-core project or JAR |
| `--dataDir` | `./input` | Custom data directory |

---

Expand All @@ -144,6 +189,9 @@ The **SPARQL Queries** section appears in the dashboard with:

# Run (with queries)
./gradlew runBenchmark --args="input/dbpedia/unzip out/json/report.json corese.4.6.5 dbpedia queries.txt"

# Run with custom query timeout (60s)
./gradlew runBenchmark --args="input/dbpedia/unzip out/json/report.json corese.4.6.5 dbpedia queries.txt --query-timeout 60"
```

---
Expand All @@ -158,15 +206,13 @@ Each run automatically generates:
| `out/csv/<timestamp>_<engines>.csv` | Same data in CSV format (Excel, etc.) |
| `site/data/benchmark-report.json` | Copy of the latest report (current dashboard) |
| `site/data/benchmark-report.csv` | Copy of the latest CSV (download button) |
| `site/data/history/<timestamp>.json` | History entry (last 30 runs kept) |
| `site/data/history-data.js` | Inline history (trend chart) |

The **historical trend chart** appears in the dashboard once 2 or more runs are available.

---

## Measurement Protocol

### Load benchmark

For each file and each engine:

1. **Warmup** — load → clear → GC (result discarded)
Expand All @@ -177,6 +223,15 @@ For each file and each engine:
- Record time and memory delta
3. **Keep the median** of the 3 repetitions

### SPARQL benchmark

For each query and each engine:

1. **Warmup** — one execution discarded (primes JIT); logs result count with `WARN` if 0 results
2. **3 repetitions** with per-execution timeout (default 30s, configurable via `--query-timeout`)
3. Each rep runs in a **daemon thread** via `ExecutorService` — a stuck query is abandoned without blocking subsequent queries
4. **Keep the median** of the 3 repetitions (`—` if all reps timed out)

This protocol ensures reproducible results by eliminating JIT compilation bias and GC timing noise.

**Note on `clear()`:** RDF4J performs a full repository reinitialisation between repetitions (rather than just `conn.clear()`) to release internal SAIL memory structures and avoid negative memory delta artefacts caused by delayed GC.
Expand Down Expand Up @@ -214,6 +269,8 @@ python python-utils/workflow.py --dataset dbpedia --engines corese.4.6.5,jena.6.

Synthetic dataset describing student/university relations. Includes associated **SPARQL queries** for latency benchmarking. Source: [DICE Research / HOBBIT](https://files.dice-research.org/projects/HOBBIT/benchmarks-data/datasets-dumps/bowlogna-dump.zip)

Dashboard note: Bowlogna shows only the **SPARQL** section (no Performance/Load charts — the dataset is optimised for query benchmarking).

| Scale | Departments | Triples (approx.) |
|-------|-------------|-------------------|
| `small` | 1 | ~1.2 M |
Expand All @@ -224,16 +281,6 @@ Synthetic dataset describing student/university relations. Includes associated *
python python-utils/workflow.py --dataset bowlogna --scales small --engines corese.4.6.5,jena.6.2.0,rdf4j.5.3.2
```

### BSBM

Berlin SPARQL Benchmark — synthetic e-commerce dataset. Generated with [bsbmtools 0.2](https://sourceforge.net/projects/bsbmtools/).

| Scale | Products | Triples (approx.) |
|-------|---------|-------------------|
| `small` | 1,000 | ~50 K |
| `medium` | 50,000 | ~1 M |
| `large` | 500,000 | ~10 M |

```bash
python python-utils/workflow.py --dataset bsbm --scales small,medium --engines corese.4.6.5,jena.6.2.0,rdf4j.5.3.2
```
Expand Down
29 changes: 29 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def useLocalCorese = (project.hasProperty('coreseVersion') && project.coreseVers
if (useLocalCorese && (!localJars.isEmpty() || project.hasProperty('coreseJar'))) {
// corese-next build: exclude 4.x driver (incompatible RuleEngine API)
sourceSets.main.java.exclude '**/CoreseDriver.java'
// Also exclude tests that directly instantiate CoreseDriver (won't compile without it)
sourceSets.test.java.exclude '**/CrossEngineConsistencyTest.java'
sourceSets.test.java.exclude '**/DriverFormatTest.java'
if (project.hasProperty('coreseJar')) {
dependencies { compileOnly files(project.coreseJar) }
} else {
Expand Down Expand Up @@ -60,12 +63,38 @@ dependencies {
implementation "org.eclipse.rdf4j:rdf4j-sail-memory:${rdf4jVersion}"
implementation "org.eclipse.rdf4j:rdf4j-repository-sail:${rdf4jVersion}"
implementation "org.eclipse.rdf4j:rdf4j-rio:${rdf4jVersion}"
// RIO parsers — required for multi-format support (.nq, .ttl, .trig)
implementation "org.eclipse.rdf4j:rdf4j-rio-ntriples:${rdf4jVersion}"
implementation "org.eclipse.rdf4j:rdf4j-rio-nquads:${rdf4jVersion}"
implementation "org.eclipse.rdf4j:rdf4j-rio-turtle:${rdf4jVersion}"
implementation "org.eclipse.rdf4j:rdf4j-rio-trig:${rdf4jVersion}"

// JSON output
implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.0'

// Logging
implementation 'ch.qos.logback:logback-classic:1.4.14'

// Tests
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'fr.inria.corese:corese-core:4.6.5'
def jenaVersionTest = project.hasProperty('jenaVersion') ? project.jenaVersion : '6.2.0'
testImplementation "org.apache.jena:jena-core:${jenaVersionTest}"
testImplementation "org.apache.jena:jena-arq:${jenaVersionTest}"
def rdf4jVersionTest = project.hasProperty('rdf4jVersion') ? project.rdf4jVersion : '5.3.2'
testImplementation "org.eclipse.rdf4j:rdf4j-repository:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-sail-memory:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-repository-sail:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-rio:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-rio-ntriples:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-rio-nquads:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-rio-turtle:${rdf4jVersionTest}"
testImplementation "org.eclipse.rdf4j:rdf4j-rio-trig:${rdf4jVersionTest}"
}

test {
useJUnitPlatform()
}

application {
Expand Down
Loading
Loading