Skip to content
This repository was archived by the owner on Jan 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
5cb33c9
Update .gitignore
expanded-for-real Jun 1, 2025
63313e4
initial commit for imprint-java
Jun 1, 2025
dd4fdbc
initial commit for imprint-java
expanded-for-real Jun 1, 2025
bce1d13
Add GitHub Actions CI workflow for automated testing
Jun 2, 2025
f5d90b5
Merge remote-tracking branch 'origin/dev' into dev
Jun 2, 2025
72c468f
Update GitHub Actions workflow to use upload-artifact@v4
Jun 2, 2025
468d682
Add Gradle wrapper validation to CI workflow
Jun 2, 2025
cf05b13
Fix gitignore to include gradle-wrapper.jar for CI
Jun 2, 2025
d0d7983
Force add gradle-wrapper.jar to repository
Jun 2, 2025
f2cdd1b
Update wrapper validation action to v3
Jun 2, 2025
57c8249
Fix Javadoc syntax errors and disable strict Javadoc checking
Jun 2, 2025
edb3057
Add JMH benchmark .bat and .sh for full suite benchmarking and perfor…
Jun 2, 2025
2853e3f
fix map serialization error in benchmark test and streamline ci file …
Jun 2, 2025
3a5a113
Add execute permissions back for gradlew in CI
Jun 2, 2025
50a288b
Add some more string based performance benchmarks and try to make str…
Jun 2, 2025
ea1c4c4
Merge pull request #2 from imprint-serde/faster-strings
expanded-for-real Jun 2, 2025
43cab28
second main commit to address initial commits
expanded-for-real Jun 3, 2025
fdb8a56
additional cleanup to address concerns in https://github.com/imprint-…
Jun 3, 2025
2e56688
minor style fixes
Jun 3, 2025
9353388
minor style fixes again
Jun 3, 2025
09d0377
minor style fixes on benchmark tests and supress unused
Jun 3, 2025
6209bb1
minor reordering
Jun 4, 2025
ace7c67
Merge branch 'main' into dev
Jun 4, 2025
4632e01
Full comprehensive comparison tests with a lot of other libraries + s…
Jun 5, 2025
3738861
replace deprecated gradle methods with latest
Jun 5, 2025
12d2823
Merge Comparisons into dev branch (#8)
expanded-for-real Jun 5, 2025
f7a6e8e
Lazy load of directory and header data
Jun 5, 2025
2834dbb
Merge remote-tracking branch 'origin/main' into dev
Jun 5, 2025
83ed961
minor cleanup
Jun 5, 2025
a605b65
minor cleanup
Jun 5, 2025
aacddeb
minor cleanup
Jun 5, 2025
3bf81ad
Actually fixes offsets and read Byte Values for Maps and Arrays even …
Jun 5, 2025
7eaa6e9
change CI file to use JMH plugin to respect iteration and warmup valu…
Jun 5, 2025
32640cd
ok plugin didn't work apparently so reverting that and just reducing …
Jun 5, 2025
2d882c2
Merge branch 'dev' into lazy-directory
Jun 5, 2025
880aeb0
trying to update github ci to make jmh actually work correctly
Jun 5, 2025
8831922
lazy directory deserialization
Jun 6, 2025
e361cf0
Merge branch 'main' into dev
Jun 6, 2025
73eade6
remove extra comments
Jun 6, 2025
02866d5
remove extra comments
Jun 6, 2025
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
226 changes: 3 additions & 223 deletions .github/workflows/ci.yml
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Massively reduced the ci compared to last time - probably won't have to change this much for a while

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

on:
push:
branches: [ main, dev ]
branches: [ main ]
pull_request:
branches: [ main, dev ]
branches: [ main ]

jobs:
test:
Expand Down Expand Up @@ -41,224 +41,4 @@ jobs:
run: ./gradlew test

- name: Run build
run: ./gradlew build

benchmark:
runs-on: ubuntu-latest
needs: test
# Add explicit permissions for commenting on PRs
permissions:
contents: read
pull-requests: write
issues: write
# Only run benchmarks on main branch pushes and PRs to main to avoid excessive CI time
if: github.ref == 'refs/heads/main' || github.base_ref == 'main'

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'temurin'

- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Make gradlew executable
run: chmod +x ./gradlew

- name: Create benchmark results directory
run: mkdir -p benchmark-results

- name: Run serialization benchmarks
run: |
./gradlew jmhRunSerializationBenchmarks
continue-on-error: true

- name: Run deserialization benchmarks
run: |
./gradlew jmhRunDeserializationBenchmarks
continue-on-error: true

- name: Run field access benchmarks
run: |
./gradlew jmhRunFieldAccessBenchmarks
continue-on-error: true

- name: Run size comparison benchmarks
run: |
./gradlew jmhRunSizeComparisonBenchmarks
continue-on-error: true

- name: Upload benchmark results
uses: actions/upload-artifact@v4
if: always()
with:
name: benchmark-results-${{ github.sha }}
path: benchmark-results/
retention-days: 30

- name: Comment benchmark results on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
continue-on-error: true
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
try {
const fs = require('fs');
const path = require('path');

// Find the latest benchmark results file
const resultsDir = 'benchmark-results';
let latestFile = null;
let latestTime = 0;

if (fs.existsSync(resultsDir)) {
const files = fs.readdirSync(resultsDir);
for (const file of files) {
if (file.endsWith('.json')) {
const filePath = path.join(resultsDir, file);
const stats = fs.statSync(filePath);
if (stats.mtime.getTime() > latestTime) {
latestTime = stats.mtime.getTime();
latestFile = filePath;
}
}
}
}

if (latestFile) {
console.log(`📊 Found benchmark results: ${latestFile}`);
const results = JSON.parse(fs.readFileSync(latestFile, 'utf8'));

// Group results by benchmark type
const serialization = results.filter(r => r.benchmark.includes('serialize'));
const deserialization = results.filter(r => r.benchmark.includes('deserialize'));
const fieldAccess = results.filter(r => r.benchmark.includes('singleFieldAccess'));
const sizes = results.filter(r => r.benchmark.includes('measure'));

// Format results into a table
const formatResults = (benchmarks, title) => {
if (benchmarks.length === 0) return '';

let table = `\n### ${title}\n\n| Library | Score (ns/op) | Error | Unit |\n|---------|---------------|-------|------|\n`;

benchmarks
.sort((a, b) => a.primaryMetric.score - b.primaryMetric.score)
.forEach(benchmark => {
const name = benchmark.benchmark.split('.').pop().replace(/serialize|deserialize|singleFieldAccess|measure/, '').replace(/Imprint|JacksonJson|Kryo|MessagePack|Avro|Protobuf|FlatBuffers/, (match) => match);
const score = benchmark.primaryMetric.score.toFixed(2);
const error = benchmark.primaryMetric.scoreError.toFixed(2);
const unit = benchmark.primaryMetric.scoreUnit;
table += `| ${name} | ${score} | ±${error} | ${unit} |\n`;
});

return table;
};

const comment = `## 📊 Benchmark Results

Benchmark comparison between Imprint and other serialization libraries:
${formatResults(serialization, 'Serialization Performance')}
${formatResults(deserialization, 'Deserialization Performance')}
${formatResults(fieldAccess, 'Single Field Access Performance')}
${formatResults(sizes, 'Serialized Size Comparison')}

<details>
<summary>View detailed results</summary>

Results generated from commit: \`${context.sha.substring(0, 7)}\`

Lower scores are better for performance benchmarks.

</details>`;

await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});

console.log('✅ Successfully posted benchmark results to PR');
} else {
console.log('⚠️ No benchmark results found');
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '## 📊 Benchmark Results\n\nBenchmark execution completed but no results file was found. Check the [workflow logs](' +
`https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}` + ') for details.'
});
}
} catch (error) {
console.log('❌ Failed to post benchmark comment:', error.message);
console.log('📁 Benchmark results are still available in workflow artifacts');

// Try to post a simple error message
try {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 📊 Benchmark Results\n\n⚠️ Failed to process benchmark results automatically.\n\nResults are available in the [workflow artifacts](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).`
});
} catch (commentError) {
console.log('❌ Also failed to post error comment:', commentError.message);
}
}

# Optional: Run full benchmark suite on releases
benchmark-full:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'temurin'

- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Make gradlew executable
run: chmod +x ./gradlew

- name: Create benchmark results directory
run: mkdir -p benchmark-results

- name: Run full benchmark suite
run: |
./gradlew jmhRunAllBenchmarks

- name: Upload full benchmark results
uses: actions/upload-artifact@v4
with:
name: full-benchmark-results-${{ github.ref_name }}
path: benchmark-results/
retention-days: 90
run: ./gradlew build
135 changes: 4 additions & 131 deletions build.gradle
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Massively reduced gradle from last time

Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ test {
}
}

// JMH configuration - optimized for Java 11
// JMH configuration
jmh {
fork = 1
warmupIterations = 2 // Reduced for faster CI
iterations = 3 // Reduced for faster CI
fork = 2
warmupIterations = 3
iterations = 5
resultFormat = 'JSON'
includeTests = false
resultsFile = file("${projectDir}/benchmark-results/jmh-results-${new Date().format('yyyy-MM-dd-HHmmss')}.json")
Expand All @@ -184,133 +184,6 @@ jmh {
]
}

// Create individual benchmark tasks for CI pipeline
tasks.register('jmhRunSerializationBenchmarks', JavaExec) {
dependsOn compileJmhJava
description = 'Run serialization benchmarks'
group = 'benchmarking'

classpath = sourceSets.jmh.runtimeClasspath
mainClass = 'com.imprint.benchmark.ComparisonBenchmark'
args = ['runSerializationBenchmarks']

// Java 11 optimized JVM settings
jvmArgs = [
'-XX:+UseG1GC',
'-Xmx2g',
'-XX:+UnlockExperimentalVMOptions'
]

doFirst {
file("${projectDir}/benchmark-results").mkdirs()
}
}

tasks.register('jmhRunDeserializationBenchmarks', JavaExec) {
dependsOn compileJmhJava
description = 'Run deserialization benchmarks'
group = 'benchmarking'

classpath = sourceSets.jmh.runtimeClasspath
mainClass = 'com.imprint.benchmark.ComparisonBenchmark'
args = ['runDeserializationBenchmarks']

// Java 11 optimized JVM settings
jvmArgs = [
'-XX:+UseG1GC',
'-Xmx2g',
'-XX:+UnlockExperimentalVMOptions'
]

doFirst {
file("${projectDir}/benchmark-results").mkdirs()
}
}

tasks.register('jmhRunFieldAccessBenchmarks', JavaExec) {
dependsOn compileJmhJava
description = 'Run field access benchmarks'
group = 'benchmarking'

classpath = sourceSets.jmh.runtimeClasspath
mainClass = 'com.imprint.benchmark.ComparisonBenchmark'
args = ['runFieldAccessBenchmarks']

// Java 11 optimized JVM settings
jvmArgs = [
'-XX:+UseG1GC',
'-Xmx2g',
'-XX:+UnlockExperimentalVMOptions'
]

doFirst {
file("${projectDir}/benchmark-results").mkdirs()
}
}

tasks.register('jmhRunSizeComparisonBenchmarks', JavaExec) {
dependsOn compileJmhJava
description = 'Run size comparison benchmarks'
group = 'benchmarking'

classpath = sourceSets.jmh.runtimeClasspath
mainClass = 'com.imprint.benchmark.ComparisonBenchmark'
args = ['runSizeComparisonBenchmarks']

// Java 11 optimized JVM settings
jvmArgs = [
'-XX:+UseG1GC',
'-Xmx2g',
'-XX:+UnlockExperimentalVMOptions'
]

doFirst {
file("${projectDir}/benchmark-results").mkdirs()
}
}

tasks.register('jmhRunMergeBenchmarks', JavaExec) {
dependsOn compileJmhJava
description = 'Run merge operation benchmarks'
group = 'benchmarking'

classpath = sourceSets.jmh.runtimeClasspath
mainClass = 'com.imprint.benchmark.ComparisonBenchmark'
args = ['runMergeBenchmarks']

// Java 11 optimized JVM settings
jvmArgs = [
'-XX:+UseG1GC',
'-Xmx2g',
'-XX:+UnlockExperimentalVMOptions'
]

doFirst {
file("${projectDir}/benchmark-results").mkdirs()
}
}

tasks.register('jmhRunAllBenchmarks', JavaExec) {
dependsOn compileJmhJava
description = 'Run all comparison benchmarks'
group = 'benchmarking'

classpath = sourceSets.jmh.runtimeClasspath
mainClass = 'com.imprint.benchmark.ComparisonBenchmark'
args = ['runAll']

// Java 11 optimized JVM settings
jvmArgs = [
'-XX:+UseG1GC',
'-Xmx2g',
'-XX:+UnlockExperimentalVMOptions'
]

doFirst {
file("${projectDir}/benchmark-results").mkdirs()
}
}

compileJava {
options.compilerArgs << '-Xlint:unchecked'
options.deprecation = true
Expand Down
Loading