.cognition/skills/profile-perlonjava/SKILL.md
# Profile PerlOnJava ## ⚠️⚠️⚠️ CRITICAL: NEVER USE `git stash` ⚠️⚠️⚠️ **DANGER: Changes are SILENTLY LOST when using git stash/stash pop!** - NEVER use `git stash` to temporarily revert changes - INSTEAD: Commit to a WIP branch or use `git diff > backup.patch` - This warning exists because completed work was lost during debugging Profile and optimize PerlOnJava runtime performance using Java Flight Recorder. ## Git Workflow **IMPORTANT: Never push directly to master. Always use feature bra
npx skillsauth add fglock/perlonjava .cognition/skills/profile-perlonjavaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
git stash ⚠️⚠️⚠️DANGER: Changes are SILENTLY LOST when using git stash/stash pop!
git stash to temporarily revert changesgit diff > backup.patchProfile and optimize PerlOnJava runtime performance using Java Flight Recorder.
IMPORTANT: Never push directly to master. Always use feature branches and PRs.
IMPORTANT: Always commit or stash changes BEFORE switching branches. If git stash pop has conflicts, uncommitted changes may be lost.
git checkout -b perf/optimization-name
# ... make changes ...
git push origin perf/optimization-name
gh pr create --title "Perf: description" --body "Details"
cd /Users/fglock/projects/PerlOnJava2
# Profile a long-running script (adjust duration as needed)
java -XX:+FlightRecorder \
-XX:StartFlightRecording=duration=60s,filename=profile.jfr \
-jar target/perlonjava-3.0.0.jar <script.pl> [args...]
# Path to jfr tool
JFR="$(/usr/libexec/java_home)/bin/jfr"
# Summary of recorded events
$JFR summary profile.jfr
# Extract execution samples (CPU hotspots)
$JFR print --events jdk.ExecutionSample profile.jfr
# Aggregate hotspots by method (most useful)
$JFR print --events jdk.ExecutionSample profile.jfr 2>&1 | \
grep -E "^\s+[a-z].*line:" | \
sed 's/line:.*//' | \
sort | uniq -c | sort -rn | head -40
| Category | Methods to Watch | Optimization Approach |
|----------|------------------|----------------------|
| Number parsing | Long.parseLong, Double.parseDouble, NumberParser.parseNumber | Cache numeric values, avoid string→number conversions |
| Type checking | ScalarUtils.looksLikeNumber, RuntimeScalar.getDefinedBoolean | Fast-path for common types (INTEGER, DOUBLE) |
| Bitwise ops | BitwiseOperators.* | Ensure values stay as INTEGER type |
| Regex | Pattern.match, Matcher.matches | Reduce unnecessary regex checks |
| Loop control | RuntimeControlFlowRegistry.checkLoopAndGetAction | ThreadLocal overhead |
| Array ops | ArrayList.grow, Arrays.copyOf | Pre-size arrays, reduce allocations |
| File | Purpose |
|------|---------|
| src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeScalar.java | Scalar value representation, getLong/getDouble/getInt |
| src/main/java/org/perlonjava/runtime/runtimetypes/ScalarUtils.java | Utility functions like looksLikeNumber |
| src/main/java/org/perlonjava/runtime/operators/BitwiseOperators.java | Bitwise operations (&, |, ^, ~, <<, >>) |
| src/main/java/org/perlonjava/runtime/operators/Operator.java | General operators |
| src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeArray.java | Array operations |
public static boolean looksLikeNumber(RuntimeScalar runtimeScalar) {
// Inlined fast-path for most common numeric types
int t = runtimeScalar.type;
if (t == INTEGER || t == DOUBLE) {
return true;
}
return looksLikeNumberSlow(runtimeScalar, t);
}
// Bad: parses string every time
long val = runtimeScalar.getLong(); // calls Long.parseLong if STRING
// Better: check type first, use cached value
if (runtimeScalar.type == INTEGER) {
long val = (int) runtimeScalar.value; // direct access
}
# Quick benchmark with life_bitpacked.pl
java -jar target/perlonjava-3.0.0.jar examples/life_bitpacked.pl \
-w 200 -h 200 -g 10000 -r none
# Multiple runs for consistency
for i in 1 2 3; do
java -jar target/perlonjava-3.0.0.jar examples/life_bitpacked.pl \
-w 200 -h 200 -g 10000 -r none 2>&1 | grep "per second"
done
ALWAYS use make commands. NEVER use raw mvn/gradlew commands.
| Command | What it does |
|---------|--------------|
| make | Build + run all unit tests (use before committing) |
| make dev | Build only, skip tests (for quick iteration during profiling) |
make # Standard build - compiles and runs tests
make dev # Quick build - compiles only, NO tests
1. Identify slow script or operation
2. Profile with JFR (60s recording)
3. Aggregate hotspots by method
4. Identify top bottlenecks (parsing, type checks, etc.)
5. Implement fast-path optimization
6. Rebuild and benchmark
7. Profile again to verify improvement
8. Run tests to ensure correctness
development
# PerlOnJava Debugging Skills and Architecture Knowledge This document captures key knowledge about PerlOnJava internals learned during debugging sessions. ## Variable Storage and Scoping ### Three Types of Variable Declarations 1. **`my` variables** - Lexical scope - Stored in JVM local variable slots during normal execution - When captured by closures: stored as closure fields or in GlobalVariable with IDs - Symbol table entry: `decl = "my"`, has `index` (JVM slot number) 2. **`o
development
# PerlOnJava Interpreter Developer Guide - name all test files /tmp/test.pl ## Quick Reference **Performance:** 46.84M ops/sec (1.75x slower than compiler ✓) **Opcodes:** 0-157 (contiguous) for JVM tableswitch optimization **Runtime:** 100% API compatibility with compiler (zero duplication) ### Testing Modes **JPERL_EVAL_USE_INTERPRETER=1** - Forces all eval STRING to use the interpreter - Used for testing interpreter implementation of operators in eval context - Compiler still used for mai
development
# Port CPAN Module to PerlOnJava ## ⚠️⚠️⚠️ CRITICAL: NEVER USE `git stash` ⚠️⚠️⚠️ **DANGER: Changes are SILENTLY LOST when using git stash/stash pop!** - NEVER use `git stash` to temporarily revert changes - INSTEAD: Commit to a WIP branch or use `git diff > backup.patch` - This warning exists because completed work was lost during debugging This skill guides you through porting a CPAN module with XS/C components to PerlOnJava using Java implementations. ## When to Use This Skill - User as
development
Migrate from JNA to a modern native access library (eliminate sun.misc.Unsafe warnings)