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
4 changes: 2 additions & 2 deletions adr/0001-ffm-over-jni.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ Native symbols bind to `MethodHandle`s in `Bindings`; the library targets JDK
`--enable-native-access`.

### Risks to manage
- FFM is young; signatures/restrictions may evolve. Centralised in `Bindings`
and `NativeCall` so changes are localised.
- FFM is young; signatures/restrictions may evolve. Centralized in `Bindings`
and `NativeCall` so changes are localized.

## Alternatives considered

Expand Down
2 changes: 1 addition & 1 deletion adr/0002-zig-cc-native-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ it is idempotent (skips if the library exists).
- `zig cc` is a clang wrapper, not the zstd-blessed build path.

### Risks to manage
- Zig is pre-1.0; `zig cc` flag behaviour can shift between versions. The Zig
- Zig is pre-1.0; `zig cc` flag behavior can shift between versions. The Zig
version is **pinned** (0.16.0) in CI; upgrades require a re-test.

## Alternatives considered
Expand Down
2 changes: 1 addition & 1 deletion adr/0009-nativeobject-idempotent-close.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Native contexts and dictionaries (CCtx, DCtx, CDict, DDict) own off-heap memory
that must be freed via their zstd `ZSTD_free*` calls. Java's GC does not free
native memory; double-free is undefined behaviour. The lifecycle model must be
native memory; double-free is undefined behavior. The lifecycle model must be
deterministic and safe to call twice.

## Decision
Expand Down
6 changes: 3 additions & 3 deletions adr/0012-benchmark-methodology.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ Benchmarks live in the `benchmark/` module (JMH), comparing zstd-java

Two payload families:

- **Synthetic, semi-compressible** (`BenchData`, ~3x ratio) parameterised over
- **Synthetic, semi-compressible** (`BenchData`, ~3x ratio) parameterized over
*sizes* — exercises the bandwidth regime.
- **The vendored golden corpus** (`GoldenCorpusBenchmark`) parameterised over
- **The vendored golden corpus** (`GoldenCorpusBenchmark`) parameterized over
*real files* — exercises per-call native-boundary overhead, where FFM-vs-JNI
fixed costs show up.

Published numbers in `docs/benchmarks.md` state the host, JDK, dependency
versions, and the JMH run parameters. Quick low-iteration runs are labelled
versions, and the JMH run parameters. Quick low-iteration runs are labeled
**directional, not publication-grade**; publication numbers use higher fork and
iteration counts.

Expand Down
4 changes: 2 additions & 2 deletions docs/how-to.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Task-focused recipes. Each assumes you have the library on the classpath (see th

## Compress on a hot path

Reuse a context to amortise native allocation across many calls:
Reuse a context to amortize native allocation across many calls:

```java
try (ZstdCompressContext cctx = new ZstdCompressContext().level(19);
Expand Down Expand Up @@ -39,7 +39,7 @@ try (ZstdCompressContext cctx = new ZstdCompressContext().level(19)) {
}
```

`ZstdDecompressContext.reset(...)` works the same way. Reuse alone amortises
`ZstdDecompressContext.reset(...)` works the same way. Reuse alone amortizes
allocation; reset lets a long-lived or pooled context return to a known state
without churning native memory.

Expand Down
2 changes: 1 addition & 1 deletion docs/supported.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ rather than the deprecated `ZSTD_getDecompressedSize`.
1. ~~**Streaming**~~ — done: `ZstdOutputStream` / `ZstdInputStream` (`compressStream2`, `decompressStream`, bounded buffers, dictionary constructors, `pledgedSrcSize` via `withPledgedSize`). Remaining: `MemorySegment`-buffer driver.
2. ~~**Advanced parameters**~~ — done: every `ZSTD_cParameter`/`ZSTD_dParameter` via `ZstdCompressParameter`/`ZstdDecompressParameter` (+ `bounds()`), on both contexts; `pledgedSrcSize`. `nbWorkers` is settable but inert until the native build enables multithreading.
3. ~~**Frame inspection**~~ — done: `ZstdFrame` (`isFrame`, `header`, `compressedSize`, `decompressedBound`, `decompressedSize`, `dictId`, skippable, `getFrameProgression`); dict-id from raw/CDict/DDict.
4. ~~**Better dictionaries**~~ — done: COVER / fast-COVER optimisers, `finalizeDictionary`, `getDictHeaderSize`.
4. ~~**Better dictionaries**~~ — done: COVER / fast-COVER optimizers, `finalizeDictionary`, `getDictHeaderSize`.
5. ~~**Typed errors**~~ — done: `ZstdException.code()` returns `ZstdErrorCode` (via `getErrorCode`).

## Full symbol table
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ private static Path locateCorpus() {
}
throw new IllegalStateException(
"golden corpus not found: third_party/zstd/tests is missing — "
+ "initialise the zstd submodule (git submodule update --init --recursive)");
+ "initialize the zstd submodule (git submodule update --init --recursive)");
}

private static Stream<Arguments> filesIn(String subdir, String suffix) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ void javaRejectsCorruptedChecksum() {
}

/// Skippable frames carry application metadata the decoder must pass over. A
/// skippable frame written by this library must be recognised and skipped by
/// skippable frame written by this library must be recognized and skipped by
/// the zstd-jni stream decoder, leaving the following real frame intact.
@Nested
class Skippable {
Expand Down
2 changes: 1 addition & 1 deletion zstd/src/main/java/io/github/dfa1/zstd/Bindings.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/// Signatures and semantics follow the
/// [official manual](https://facebook.github.io/zstd/doc/api_manual_latest.html).
///
/// `size_t` and `unsigned long long` are modelled as
/// `size_t` and `unsigned long long` are modeled as
/// [java.lang.foreign.ValueLayout#JAVA_LONG] (LP64); the public API guards
/// against negative interpretations where zstd uses sentinel values.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

/// A reusable compression context.
///
/// Reusing one context across many [#compress] calls amortises native
/// Reusing one context across many [#compress] calls amortizes native
/// state allocation, making it cheaper than the stateless [Zstd#compress]
/// on hot paths. Not thread-safe: confine an instance to one thread or pool it.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

/// A reusable decompression context.
///
/// Reusing one context across many [#decompress] calls amortises native
/// Reusing one context across many [#decompress] calls amortizes native
/// state allocation. Not thread-safe: confine an instance to one thread or pool it.
public final class ZstdDecompressContext extends NativeObject {

Expand Down
18 changes: 9 additions & 9 deletions zstd/src/main/java/io/github/dfa1/zstd/ZstdDictionary.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public static ZstdDictionary trainCover(List<byte[]> samples, int maxDictBytes)
return trainCover(samples, maxDictBytes, 0);
}

/// Trains a COVER dictionary optimised for a specific compression level.
/// Trains a COVER dictionary optimized for a specific compression level.
///
/// @param samples representative payloads to learn from
/// @param maxDictBytes upper bound on the produced dictionary size
Expand All @@ -135,7 +135,7 @@ public static ZstdDictionary trainCover(List<byte[]> samples, int maxDictBytes,
}

/// Trains a dictionary with the fast COVER algorithm, auto-tuning its
/// parameters. The recommended optimiser: nearly the quality of
/// parameters. The recommended optimizer: nearly the quality of
/// [#trainCover] at a fraction of the time.
///
/// @param samples representative payloads to learn from
Expand All @@ -146,7 +146,7 @@ public static ZstdDictionary trainFastCover(List<byte[]> samples, int maxDictByt
return trainFastCover(samples, maxDictBytes, 0);
}

/// Trains a fast COVER dictionary optimised for a specific compression level.
/// Trains a fast COVER dictionary optimized for a specific compression level.
///
/// @param samples representative payloads to learn from
/// @param maxDictBytes upper bound on the produced dictionary size
Expand Down Expand Up @@ -184,19 +184,19 @@ private static ZstdDictionary optimize(List<byte[]> samples, int maxDictBytes,
/// Turns raw dictionary `content` you supply (e.g. hand-picked common bytes,
/// or a prefix from elsewhere) into a usable zstd dictionary by adding a
/// header and entropy tables tuned on `samples`. Use this when you control the
/// dictionary content and only want zstd to finalise it.
/// dictionary content and only want zstd to finalize it.
///
/// @param content the raw dictionary content to wrap
/// @param samples representative payloads to tune entropy tables on
/// @param maxDictBytes upper bound on the produced dictionary size
/// @param compressionLevel the level the dictionary will be used at (0 = default)
/// @return the finalised dictionary
/// @throws ZstdException if finalisation fails
/// @return the finalized dictionary
/// @throws ZstdException if finalization fails
public static ZstdDictionary finalizeFrom(byte[] content, List<byte[]> samples,
int maxDictBytes, int compressionLevel) {
Objects.requireNonNull(content, "content");
Objects.requireNonNull(samples, SAMPLES);
requireNonEmpty(samples, "finalise");
requireNonEmpty(samples, "finalize");
try (Arena arena = Arena.ofConfined()) {
FlatSamples in = flatten(arena, samples);
MemorySegment contentSeg = Zstd.copyIn(arena, content);
Expand All @@ -211,7 +211,7 @@ public static ZstdDictionary finalizeFrom(byte[] content, List<byte[]> samples,
} catch (Throwable t) {
throw NativeCall.rethrow(t);
}
return toDictionary(dictBuf, produced, "dictionary finalisation");
return toDictionary(dictBuf, produced, "dictionary finalization");
}
}

Expand Down Expand Up @@ -283,7 +283,7 @@ public int headerSize() {
}
}

/// Serialises this dictionary to a fresh byte array.
/// Serializes this dictionary to a fresh byte array.
///
/// @return a copy of the raw dictionary bytes, suitable for persisting
public byte[] toByteArray() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.github.dfa1.zstd;

/// Controls how much a [ZstdCompressStream#compress] call finalises, mirroring
/// Controls how much a [ZstdCompressStream#compress] call finalizes, mirroring
/// `ZSTD_EndDirective`.
public enum ZstdEndDirective {

Expand Down
8 changes: 4 additions & 4 deletions zstd/src/main/java/io/github/dfa1/zstd/ZstdErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
///
/// The numeric values mirror `ZSTD_ErrorCode` in the vendored zstd header. zstd
/// does not guarantee these values across versions, but this library pins a
/// specific zstd source, so they are stable for a given release. An unrecognised
/// specific zstd source, so they are stable for a given release. An unrecognized
/// code maps to [#UNKNOWN].
public enum ZstdErrorCode {

Expand All @@ -19,7 +19,7 @@ public enum ZstdErrorCode {
NO_ERROR(0),
/// Unspecified error.
GENERIC(1),
/// Input does not start with a recognised zstd frame prefix.
/// Input does not start with a recognized zstd frame prefix.
PREFIX_UNKNOWN(10),
/// Frame requires an unsupported zstd version.
VERSION_UNSUPPORTED(12),
Expand Down Expand Up @@ -57,7 +57,7 @@ public enum ZstdErrorCode {
STABILITY_CONDITION_NOT_RESPECTED(50),
/// Operation called at the wrong stage of the context lifecycle.
STAGE_WRONG(60),
/// Context was not initialised before use.
/// Context was not initialized before use.
INIT_MISSING(62),
/// A memory allocation failed.
MEMORY_ALLOCATION(64),
Expand Down Expand Up @@ -116,7 +116,7 @@ public String description() {
/// Maps a native `ZSTD_ErrorCode` integer to its category.
///
/// @param value the native error code
/// @return the matching category, or [#UNKNOWN] if unrecognised
/// @return the matching category, or [#UNKNOWN] if unrecognized
static ZstdErrorCode of(int value) {
for (ZstdErrorCode code : values()) {
if (code.value == value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Classifier {
"Windows 11, amd64, windows-x86_64",
"Windows 11, aarch64, windows-aarch64",
"Linux, x86_64, linux-x86_64",
// unknown os falls back to linux; arch aliases normalise
// unknown os falls back to linux; arch aliases normalize
"FreeBSD, aarch64, linux-aarch64",
"Linux, amd64, linux-x86_64",
"Linux, arm64, linux-aarch64",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ void trainedDictionaryHasHeader() {

@Test
void finalizeFailsWithoutSamples() {
// When finalising raw content with no tuning samples
// When finalizing raw content with no tuning samples
ThrowingCallable result = () -> ZstdDictionary.finalizeFrom(new byte[]{1, 2, 3}, List.of(), 4096, 0);

// Then it fails fast with the empty-samples guard
Expand Down Expand Up @@ -320,11 +320,11 @@ void factoryDictionariesRoundTrip() {
}

@Nested
class Serialisation {
class Serialization {

@Test
void reloadedDictionaryKeepsIdentityAndDecodes() {
// Given the dictionary serialised and reloaded
// Given the dictionary serialized and reloaded
ZstdDictionary reloaded = ZstdDictionary.of(sut.toByteArray());

// Then it carries the same dictionary id
Expand Down
6 changes: 3 additions & 3 deletions zstd/src/test/java/io/github/dfa1/zstd/ZstdFrameTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ZstdFrameTest {
class IsFrame {

@Test
void recognisesAZstdFrame() {
void recognizesAZstdFrame() {
assertThat(ZstdFrame.isZstdFrame(Zstd.compress(PAYLOAD))).isTrue();
}

Expand Down Expand Up @@ -323,7 +323,7 @@ void roundTripsContentAndMagicVariant() {
byte[] meta = "sidecar metadata".getBytes(StandardCharsets.UTF_8);
byte[] frame = ZstdFrame.writeSkippableFrame(meta, 7);

// Then it is recognised as skippable and decodes back with its variant
// Then it is recognized as skippable and decodes back with its variant
assertThat(ZstdFrame.isSkippableFrame(frame)).isTrue();
assertThat(ZstdFrame.header(frame).frameType()).isEqualTo(ZstdFrameType.SKIPPABLE);

Expand Down Expand Up @@ -430,7 +430,7 @@ void mirrorTheByteArrayOverloadsForANativeFrame() {
}

@Test
void recognisesASkippableNativeFrame() {
void recognizesASkippableNativeFrame() {
// Given a skippable frame in a native segment
byte[] frame = ZstdFrame.writeSkippableFrame("meta".getBytes(StandardCharsets.UTF_8), 5);
try (Arena arena = Arena.ofConfined()) {
Expand Down
Loading