Repository navigation
Releases
memfs-kit v1.1.1
This patch release reduces small-read and directory-entry metadata overhead
while preserving the existing API, snapshots, hooks and concurrency guarantees.
Highlights
File.Readexplicitly 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 thatInforeturns 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
Infotook 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-hookInfocalls became allocation-free; fresh hook listings plus every
Infowere 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.1import 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
This minor release reduces filesystem allocations and adds direct metadata and
directory-listing methods through Go's optional io/fs interfaces.
Highlights
*FSnow implementsfs.StatFS.Statcaptures 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.*FSnow implementsfs.ReadDirFS.ReadDirreturns 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.Closeresets 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.0import 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
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, andWriteFile, then
use it with standardfshelpers, templates, andhttp.FileServer. *FSimplementsfs.FSandfs.SubFS. Regular file handles support seeking
and positional reads; directory handles implementfs.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. WithOpenHookcan 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.0import 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.