orthonym.jvm_flags#
Note
Internal API. Names and behaviour may change between releases.
One place that decides how a JVM is launched. Import this, never hand-roll argv.
Every java invocation in this tree – OPSIN CLI, the centres CIP jar, the
persistent OPSIN child, and the in-process JPype JVM – goes through
JVM_HYGIENE_FLAGS so a single edit reaches all of them.
Why this exists: the hsperfdata stdout-contamination class#
A JVM writes a perf-data file at /tmp/hsperfdata_<user>/<pid>. When it cannot
use that path it prints, to stdout:
[0.003s][warning][perf,memops] Cannot use file /tmp/hsperfdata_kohulan/3428897
because it is locked by another process (errno = 11)
Anything mapping OPSIN output positionally onto its inputs then shifts every later row by one, so correct names silently acquire the previous name’s SMILES. Measured once at 12 concurrent JVMs: 34 of 400 results shifted. That is a wrong molecule, not a parse failure – the single worst failure mode this project has.
Mechanism, verified in all four legs 2026-08-03:
This project kills JVMs routinely – SIGALRM guards in pin_conformance_eval,
measure_breadth slice timeouts, hang-recovery pkill – so it manufactures
the stale files that make the collision possible. Disabling perf data removes the
cause rather than coping with the symptom. It is also rare (pid_max is
4,194,304, so PID reuse is uncommon), which makes it the dangerous kind:
intermittent, silent wrongness that a green test run cannot see.
Cost: jps/jstat/jcmd can no longer discover these JVMs. Nothing in
this tree uses them; orthonym.jvm_budget.status is the supported way to
see what is running.
Belt and braces#
Removing the cause is not sufficient on its own – a JVM can print to stdout for
other reasons (a GC log, an agent, a future JDK warning). So every positional
batch parse must ALSO fail closed on a line-count mismatch, the way
eval/harness.py:opsin_batch already does. Use:func:aligned_batch_lines.
- orthonym.jvm_flags.JVM_CORE_HYGIENE_FLAGS: List[str] = ['-XX:-UsePerfData', '-Djava.awt.headless=true']#
Flags applied to every JVM this project launches.
-XX:-UsePerfDatano /tmp/hsperfdata file -> the contamination class above becomes structurally impossible.-Djava.awt.headlessno display is ever available; avoids an AWT probe.
- orthonym.jvm_flags.JVM_PERF_FLAGS: List[str] = ['-XX:+UseSerialGC', '-XX:TieredStopAtLevel=1']#
Perf lever A2 (2026-09-13). Every worker process runs its own JVM; with the default G1 collector each held 8 parallel + 10 concurrent GC threads, and 40-56 workers on 60 vCPUs spent ~10 % of their CPU in JVM helper threads. Measured on this host (OPSIN in-process parse, 1,200 names): SerialGC starts the JVM in 1.7 s instead of 2.6 s and parses faster on a loaded box; C1-only (TieredStopAtLevel=1) warms up fastest at no steady-state loss (OPSIN parsing is ~3 % of naming time). Neither flag changes any result.
ORTHONYM_JVM_PERF_FLAGS=offdrops them (A/B measurements).
- orthonym.jvm_flags.JVM_HYGIENE_FLAGS: List[str] = ['-XX:-UsePerfData', '-Djava.awt.headless=true', '-XX:+UseSerialGC', '-XX:TieredStopAtLevel=1']#
Flags applied to every JVM this project launches (hygiene first, then the perf flags).
- orthonym.jvm_flags.java_cmd(*args, heap=None)#
Build a
javaargv with the hygiene flags applied.>>> java_cmd("-jar", "opsin.jar", "-osmi")[:3] ['java', '-XX:-UsePerfData', '-Djava.awt.headless=true']
- Parameters:
*args (str) – everything after the JVM options – typically
"-jar", jar_path,...or"-version".heap (str | None) – optional
-Xmxvalue, e.g."512m". Worth passing on any path that may run many JVMs at once: the ~40java -jarsites historically carried NO heap flag, so each inherited the JDK ergonomic default of 25% of RAM (15.8 GB on this host) as reserved address space, while the JPype path was capped at 512m. Actual measured footprint is 196-395 MB, so a cap costs nothing.
- orthonym.jvm_flags.aligned_batch_lines(stdout, expected, where='opsin batch')#
Split
stdoutinto exactlyexpectedlines, or returnNone.Nonemeans “do not trust this output” – the caller must treat the whole batch as unavailable rather than map it positionally. ReturningNoneinstead of raising keeps this usable on the paths that must degrade to “unknown” rather than abort.Any line the JVM injected (a warning, an info line, a banner) changes the count, so this catches the contamination class even when its cause is something
-XX:-UsePerfDatadoes not cover.>>> aligned_batch_lines("C(C)O\nC1=CC=CC=C1\n", 2) ['C(C)O', 'C1=CC=CC=C1'] >>> aligned_batch_lines("[warning] oops\nC(C)O\n", 1) is None True
- orthonym.jvm_flags.strip_jvm_noise(lines)#
Drop lines a JVM prints that are not payload.
A last-resort helper for callers that cannot fail closed. Prefer
aligned_batch_lines()– dropping lines can only ever guess, whereas a count mismatch is proof something is wrong.