Skip to content

Releases

memfs-kit v1.1.1

Choose a tag to compare

@github-actions github-actions released this 25 Oct 10:18

This patch release reduces small-read and directory-entry metadata overhead
while preserving the existing API, snapshots, hooks and concurrency guarantees.

Highlights

  • File.Read explicitly unlocks its two return paths, reducing the deferred
    unlock wrapper work on small reads. The same mutex still protects the closed
    check, content access and cursor update.
  • Directory entries without a regular-file hook own an immutable metadata
    snapshot that Info returns directly, avoiding another allocation per call.
    This also applies to directory entries when a hook is configured. Returned
    metadata stays usable after the entry slice or directory handle is discarded.
  • Regular-file entries with hooks keep their lazy per-entry result, including
    concurrent initialization, cached errors and replay of a hook panic. Listing
    names still does not run hooks, and callbacks execute outside internal locks.
  • The English and Chinese documentation now distinguishes captured stored
    metadata from lazy hook metadata, identifies each performance baseline, and
    records release verification steps.

Measured results

The local comparison used Go 1.27.3, darwin/arm64, Apple M5,
GOMAXPROCS=1
, with six adjacent AB/BA pairs per scenario in one binary
(-benchtime=200ms -count=1 -cpu=1). It compared the runtime implementation in
this release with published v1.1.0
(d69c7500e0034579d72819a2a05cda1f97de960e). Percentages use the median of
paired ratios, not the ratio of separately computed medians.

  • Opening a fresh 4 KiB file, reading through EOF in 64 B chunks and closing it
    took 16.7% less time. The 16 B and 256 B chunk cases improved similarly;
    allocation remained 128 B and one allocation per operation.
  • Listing 1,000 entries and calling every Info took 26.9% less time.
    Allocation fell from 144,512 to 80,512 B/op (44.3% less) and from
    2,002 to 1,002 allocations/op.
  • Names-only listings retained their previous allocation counts. Repeated
    no-hook Info calls became allocation-free; fresh hook listings plus every
    Info were approximately unchanged in time and allocations.

These measurements describe specific microbenchmarks, not application
throughput. In a separate paired comparison with original soulteary/memfs
v0.1.0, the 1,000-entry listing plus every Info took about 18.9% less time,
while the 64 B chunk read still took about 48% more time. This release keeps
the per-handle synchronization absent from the original implementation. The
original comparison uses a static tree and independent handles.

See the performance notes
for workloads, reproduction commands, allocation data and limitations.

Installation

Requires Go 1.27.3 or newer, unchanged from v1.1.0.

go get github.com/soulteary/memfs-kit@v1.1.1
import memfs "github.com/soulteary/memfs-kit"

There are no third-party Go module dependencies. The module path and package
name are unchanged.

Compatibility and validation

No exported methods or signatures change. Snapshots, error behavior, content
ownership, hook paths and timing, per-listing caches and synchronization are
preserved. Seek, ReadAt and Close retain their existing behavior. Wrappers
that override Open still need to handle promoted Stat and ReadDir methods;
see optional-interface dispatch.

Validation includes Linux, macOS and Windows tests, the full race-enabled suite
with 97.9% statement coverage, 15-second/two-worker path fuzzing, formatting,
vet, module checks and a smoke run of every benchmark. New regression tests
cover read/cursor boundaries, shared-handle byte consumption, retained file and
directory metadata, and hook panic caching. They also pass against v1.1.0 to
check that the existing contracts are preserved.

Licensing

The project uses Apache License 2.0. Code inherited from memfs retains its
BSD-3-Clause license and original notices. See
LICENSE,
the preserved BSD license,
and third-party notices.

memfs-kit v1.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 09:08

This minor release reduces filesystem allocations and adds direct metadata and
directory-listing methods through Go's optional io/fs interfaces.

Highlights

  • *FS now implements fs.StatFS. Stat captures metadata with one tree lookup
    without constructing a file handle or enumerating and sorting a directory's
    children. Regular and virtual files retain their hook behavior.
  • *FS now implements fs.ReadDirFS. ReadDir returns a fresh, sorted entry
    snapshot, avoiding the standard helper's extra slice copy and sort. Directory
    opens construct full child paths only when a regular-file hook needs them.
  • Hooks still receive private input copies. Equal hook output reuses the stored
    immutable snapshot, while transformed output remains isolated by a copy.
    Metadata-only operations avoid copying output that they do not retain.
  • Path traversal uses strings.SplitSeq, and each file handle embeds its
    bytes.Reader, reducing allocations. Close resets the reader to release its
    reference to the content snapshot.

Measured allocation changes

The following local microbenchmark results compare the combined changes with
commit 39284834af24fe80d4b607f2746813c8b7a41ea4, using the same benchmark source
on Go 1.27.3, darwin/arm64, Apple M5, with -cpu=1. Each of the 27 cases ran
five 200 ms samples; allocation counts and bytes were consistent across samples.

  • Opening and closing a regular file: 3 to 1 allocations/op, with a
    one-component path falling from 160 to 128 B/op.
  • Reading metadata for a directory with 1,000 entries: 96,592 to 64 B/op
    and 2,004 to 1 allocations/op.
  • Listing a directory with 1,000 entries: 112,912 to 80,512 B/op and
    2,004 to 1,002 allocations/op.
  • Opening and closing a 1 MiB file with a passthrough hook: full-size content
    copies fall from 2 MiB to 1 MiB. Total allocation falls from
    2,097,328 to 1,048,704 B/op, including handle and path overhead.

These are operation-level microbenchmarks, with setup outside timed sections;
they do not establish application throughput or production latency. Transforming
hooks still require separate input and output copies when opening content.
See the performance notes
for reproduction commands, workload details, and the remaining optimization scope.

Installation

Requires Go 1.27.3 or newer, unchanged from v1.0.0.

go get github.com/soulteary/memfs-kit@v1.1.0
import memfs "github.com/soulteary/memfs-kit"

The module path and package name are unchanged. There are no third-party Go
module dependencies.

Compatibility

Existing method signatures, snapshot ownership, hook semantics, and error
behavior are preserved. Directory-entry metadata remains lazy, and each entry caches
its first metadata result or error independently. Hooks continue to execute
outside tree and handle locks and may write to the filesystem.

Standard fs.Stat and fs.ReadDir helpers now dispatch to the new optional
interfaces. A wrapper that anonymously embeds *memfs.FS and overrides Open
also promotes Stat and ReadDir; it must override those methods to preserve
its custom behavior, or expose only fs.FS when requesting the standard fallback:

info, err := fs.Stat(struct{ fs.FS }{wrapped}, name)
entries, err := fs.ReadDir(struct{ fs.FS }{wrapped}, name)

See wrapper compatibility
and the documented behavior.

Validation

CI covers Linux, macOS, and Windows, with Linux race detection and bounded path
fuzzing. The local race-enabled test suite passed with 97.9% statement
coverage
. Path validation, including the new methods, passed a 15-second,
two-worker fuzz run. Formatting, go vet, and module consistency checks passed.

Regression tests compare the optional methods with standard-library Open-only
fallbacks and cover subtree paths, error identity, retained hook slices,
independent lazy metadata caches, concurrent Info calls, reentrant hooks, and
snapshot ownership.

Licensing

The project uses Apache License 2.0. Code inherited from memfs retains its
BSD-3-Clause license and original notices. See
LICENSE,
the preserved BSD license,
and third-party notices.

memfs-kit v1.0.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 06:04

The first stable release of memfs-kit, a lightweight in-memory filesystem
built around Go's io/fs interfaces.

Highlights

  • Create and populate a filesystem with New, MkdirAll, and WriteFile, then
    use it with standard fs helpers, templates, and http.FileServer.
  • *FS implements fs.FS and fs.SubFS. Regular file handles support seeking
    and positional reads; directory handles implement fs.ReadDirFile.
  • Writes copy their input, and open handles retain independent content and
    metadata snapshots. Directory entries are sorted and support consistent
    paginated reads.
  • Filesystem operations and individual handle methods support concurrent use.
    Subtree views share the same underlying tree.
  • WithOpenHook can transform regular files or supply content for missing
    paths. Hooks are preserved across subtrees, and directory metadata reflects
    transformed content.
  • Correctness fixes cover locking, file ownership, directory iteration, error
    propagation, hook metadata, and references retained by closed handles.
  • No third-party Go module dependencies.

Installation

Requires Go 1.27.3 or newer.

go get github.com/soulteary/memfs-kit@v1.0.0
import memfs "github.com/soulteary/memfs-kit"

Migration from soulteary/memfs

Change the import path from github.com/soulteary/memfs to
github.com/soulteary/memfs-kit. The package name remains memfs, and ordinary
memfs.New() calls continue to work.

New now accepts variadic options. Code assigning it to an exact
func() *memfs.FS variable needs a wrapper:

newFS := func() *memfs.FS { return memfs.New() }

Review the documented behavior,
hook semantics,
and upstream review
when migrating. Hook callbacks must synchronize their own shared state and
provide stable output when metadata and content are consumed in separate
operations.

Validation

CI covers Linux, macOS, and Windows, with Linux race detection and bounded path
fuzzing. Formatting, module consistency, and go vet checks remain enabled.

The generated release reports record 97.45% statement coverage and a
Go Report Card grade of A+ (94.7%). See the
test report
and quality report.

Licensing

The project uses Apache License 2.0. Code inherited from memfs retains its
BSD-3-Clause license and original notices. See
LICENSE,
the preserved BSD license,
and third-party notices.