Skip to content

Commit

Permalink
fix(fs): fix mergefs bug where files were opened too many times (#2287)
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Henderson <[email protected]>
  • Loading branch information
hairyhenderson authored Dec 16, 2024
1 parent 40c38b7 commit 7eb7829
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 180 deletions.
75 changes: 44 additions & 31 deletions internal/datafs/mergefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ func (f *mergeFS) Open(name string) (fs.File, error) {
// unescaped '+' characters to make it simpler to provide types like
// "application/array+json"
overrideType := typeOverrideParam()
mimeType := u.Query().Get(overrideType)
mimeType = strings.ReplaceAll(mimeType, " ", "+")
mimeTypeHint := u.Query().Get(overrideType)
mimeTypeHint = strings.ReplaceAll(mimeTypeHint, " ", "+")

// now that we have the hint, remove it from the URL - we can't have it
// leaking into the filesystem layer
Expand Down Expand Up @@ -151,23 +151,6 @@ func (f *mergeFS) Open(name string) (fs.File, error) {

fsys = fsimpl.WithHTTPClientFS(f.httpClient, fsys)

// find the content type
fi, err := fs.Stat(fsys, base)
if err != nil {
return nil, &fs.PathError{
Op: "open", Path: name,
Err: fmt.Errorf("stat merge part %q: %w", part, err),
}
}

if fi.ModTime().After(modTime) {
modTime = fi.ModTime()
}

if mimeType == "" {
mimeType = fsimpl.ContentType(fi)
}

f, err := fsys.Open(base)
if err != nil {
return nil, &fs.PathError{
Expand All @@ -176,7 +159,7 @@ func (f *mergeFS) Open(name string) (fs.File, error) {
}
}

subFiles[i] = subFile{f, mimeType}
subFiles[i] = subFile{f, mimeTypeHint}
}

return &mergeFile{
Expand Down Expand Up @@ -226,18 +209,16 @@ func (f *mergeFile) Read(p []byte) (int, error) {
if f.merged == nil {
f.readMux.Lock()
defer f.readMux.Unlock()

// read from all and merge
data := make([]map[string]interface{}, len(f.subFiles))
data := make([]map[string]any, len(f.subFiles))
for i, sf := range f.subFiles {
b, err := io.ReadAll(sf)
if err != nil && !errors.Is(err, io.EOF) {
return 0, fmt.Errorf("readAll: %w", err)
}

data[i], err = parseMap(sf.contentType, string(b))
d, err := f.readSubFile(sf)
if err != nil {
return 0, fmt.Errorf("parsing map with content type %s: %w", sf.contentType, err)
return 0, fmt.Errorf("readSubFile: %w", err)
}

data[i] = d
}

md, err := mergeData(data)
Expand All @@ -253,6 +234,36 @@ func (f *mergeFile) Read(p []byte) (int, error) {
return f.merged.Read(p)
}

func (f *mergeFile) readSubFile(sf subFile) (map[string]any, error) {
// stat for content type and modTime
fi, err := sf.Stat()
if err != nil {
return nil, fmt.Errorf("stat merge part %q: %w", f.name, err)
}

// the merged file's modTime is the most recent of all the sub-files
if fi.ModTime().After(f.modTime) {
f.modTime = fi.ModTime()
}

// if we haven't been given a content type hint, guess the normal way
if sf.contentType == "" {
sf.contentType = fsimpl.ContentType(fi)
}

b, err := io.ReadAll(sf)
if err != nil && !errors.Is(err, io.EOF) {
return nil, fmt.Errorf("readAll: %w", err)
}

sfData, err := parseMap(sf.contentType, string(b))
if err != nil {
return nil, fmt.Errorf("parsing map with content type %s: %w", sf.contentType, err)
}

return sfData, nil
}

func mergeData(data []map[string]interface{}) ([]byte, error) {
dst := data[0]
data = data[1:]
Expand All @@ -269,17 +280,19 @@ func mergeData(data []map[string]interface{}) ([]byte, error) {
return []byte(s), nil
}

func parseMap(mimeType, data string) (map[string]interface{}, error) {
func parseMap(mimeType, data string) (map[string]any, error) {
datum, err := parsers.ParseData(mimeType, data)
if err != nil {
return nil, fmt.Errorf("parseData: %w", err)
}
var m map[string]interface{}

var m map[string]any
switch datum := datum.(type) {
case map[string]interface{}:
case map[string]any:
m = datum
default:
return nil, fmt.Errorf("unexpected data type '%T' for datasource (type %s); merge: can only merge maps", datum, mimeType)
}

return m, nil
}
162 changes: 70 additions & 92 deletions internal/datafs/mergefs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package datafs

import (
"context"
"fmt"
"io"
"io/fs"
"mime"
Expand Down Expand Up @@ -31,19 +32,7 @@ func setupMergeFsys(ctx context.Context, t *testing.T) fs.FS {
yamlContent := "hello: earth\ngoodnight: moon\n"
arrayContent := `["hello", "world"]`

wd, _ := os.Getwd()

// MapFS doesn't support windows path separators, so we use / exclusively
// in this test
vol := filepath.VolumeName(wd)
if vol != "" && wd != vol {
wd = wd[len(vol)+1:]
} else if wd[0] == '/' {
wd = wd[1:]
}
wd = filepath.ToSlash(wd)

t.Logf("wd: %s", wd)
wd := wdForTest(t)

fsys := WrapWdFS(fstest.MapFS{
"tmp": {Mode: fs.ModeDir | 0o777},
Expand Down Expand Up @@ -90,84 +79,22 @@ func setupMergeFsys(ctx context.Context, t *testing.T) fs.FS {
return fsys
}

// func TestReadMerge(t *testing.T) {
// ctx := context.Background()

// jsonContent := `{"hello": "world"}`
// yamlContent := "hello: earth\ngoodnight: moon\n"
// arrayContent := `["hello", "world"]`

// mergedContent := "goodnight: moon\nhello: world\n"

// fsys := fstest.MapFS{}
// fsys["tmp"] = &fstest.MapFile{Mode: fs.ModeDir | 0777}
// fsys["tmp/jsonfile.json"] = &fstest.MapFile{Data: []byte(jsonContent)}
// fsys["tmp/array.json"] = &fstest.MapFile{Data: []byte(arrayContent)}
// fsys["tmp/yamlfile.yaml"] = &fstest.MapFile{Data: []byte(yamlContent)}
// fsys["tmp/textfile.txt"] = &fstest.MapFile{Data: []byte(`plain text...`)}

// // workding dir with volume name trimmed
// wd, _ := os.Getwd()
// vol := filepath.VolumeName(wd)
// wd = wd[len(vol)+1:]

// fsys[path.Join(wd, "jsonfile.json")] = &fstest.MapFile{Data: []byte(jsonContent)}
// fsys[path.Join(wd, "array.json")] = &fstest.MapFile{Data: []byte(arrayContent)}
// fsys[path.Join(wd, "yamlfile.yaml")] = &fstest.MapFile{Data: []byte(yamlContent)}
// fsys[path.Join(wd, "textfile.txt")] = &fstest.MapFile{Data: []byte(`plain text...`)}

// fsmux := fsimpl.NewMux()
// fsmux.Add(fsimpl.WrappedFSProvider(&fsys, "file"))
// ctx = datafs.ContextWithFSProvider(ctx, fsmux)

// source := &Source{Alias: "foo", URL: mustParseURL("merge:file:///tmp/jsonfile.json|file:///tmp/yamlfile.yaml")}
// d := &Data{
// Sources: map[string]*Source{
// "foo": source,
// "bar": {Alias: "bar", URL: mustParseURL("file:///tmp/jsonfile.json")},
// "baz": {Alias: "baz", URL: mustParseURL("file:///tmp/yamlfile.yaml")},
// "text": {Alias: "text", URL: mustParseURL("file:///tmp/textfile.txt")},
// "badscheme": {Alias: "badscheme", URL: mustParseURL("bad:///scheme.json")},
// "badtype": {Alias: "badtype", URL: mustParseURL("file:///tmp/textfile.txt?type=foo/bar")},
// "array": {Alias: "array", URL: mustParseURL("file:///tmp/array.json?type=" + url.QueryEscape(jsonArrayMimetype))},
// },
// Ctx: ctx,
// }

// actual, err := d.readMerge(ctx, source)
// require.NoError(t, err)
// assert.Equal(t, mergedContent, string(actual))

// source.URL = mustParseURL("merge:bar|baz")
// actual, err = d.readMerge(ctx, source)
// require.NoError(t, err)
// assert.Equal(t, mergedContent, string(actual))

// source.URL = mustParseURL("merge:./jsonfile.json|baz")
// actual, err = d.readMerge(ctx, source)
// require.NoError(t, err)
// assert.Equal(t, mergedContent, string(actual))

// source.URL = mustParseURL("merge:file:///tmp/jsonfile.json")
// _, err = d.readMerge(ctx, source)
// require.Error(t, err)

// source.URL = mustParseURL("merge:bogusalias|file:///tmp/jsonfile.json")
// _, err = d.readMerge(ctx, source)
// require.Error(t, err)

// source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|badscheme")
// _, err = d.readMerge(ctx, source)
// require.Error(t, err)

// source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|badtype")
// _, err = d.readMerge(ctx, source)
// require.Error(t, err)

// source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|array")
// _, err = d.readMerge(ctx, source)
// require.Error(t, err)
// }
func wdForTest(t *testing.T) string {
t.Helper()

wd, _ := os.Getwd()

// MapFS doesn't support windows path separators, so we use / exclusively
vol := filepath.VolumeName(wd)
if vol != "" && wd != vol {
wd = wd[len(vol)+1:]
} else if wd[0] == '/' {
wd = wd[1:]
}
wd = filepath.ToSlash(wd)

return wd
}

func TestMergeData(t *testing.T) {
def := map[string]interface{}{
Expand Down Expand Up @@ -228,7 +155,6 @@ func TestMergeData(t *testing.T) {
}

func TestMergeFS_Open(t *testing.T) {
// u, _ := url.Parse("merge:")
fsys := setupMergeFsys(context.Background(), t)
assert.IsType(t, &mergeFS{}, fsys)

Expand Down Expand Up @@ -354,3 +280,55 @@ func TestMergeFS_ReadFile(t *testing.T) {
})
}
}

func TestMergeFS_ReadsSubFilesOnce(t *testing.T) {
mergedContent := "goodnight: moon\nhello: world\n"

wd := wdForTest(t)

fsys := WrapWdFS(
openOnce(&fstest.MapFS{
path.Join(wd, "tmp/jsonfile.json"): {Data: []byte(`{"hello": "world"}`)},
path.Join(wd, "tmp/yamlfile.yaml"): {Data: []byte("hello: earth\ngoodnight: moon\n")},
}))

mux := fsimpl.NewMux()
mux.Add(MergeFS)
mux.Add(WrappedFSProvider(fsys, "file", ""))

ctx := ContextWithFSProvider(context.Background(), mux)

reg := NewRegistry()
reg.Register("jsonfile", config.DataSource{URL: mustParseURL("tmp/jsonfile.json")})
reg.Register("yamlfile", config.DataSource{URL: mustParseURL("tmp/yamlfile.yaml")})

fsys, err := NewMergeFS(mustParseURL("merge:///"))
require.NoError(t, err)

fsys = WithDataSourceRegistryFS(reg, fsys)
fsys = fsimpl.WithContextFS(ctx, fsys)

b, err := fs.ReadFile(fsys, "jsonfile|yamlfile")
require.NoError(t, err)
assert.Equal(t, mergedContent, string(b))
}

type openOnceFS struct {
fs *fstest.MapFS
opened map[string]struct{}
}

// a filesystem that only allows opening or stating a file once
func openOnce(fsys *fstest.MapFS) fs.FS {
return &openOnceFS{fs: fsys, opened: map[string]struct{}{}}
}

func (f *openOnceFS) Open(name string) (fs.File, error) {
if _, ok := f.opened[name]; ok {
return nil, fmt.Errorf("open: %q already opened", name)
}

f.opened[name] = struct{}{}

return f.fs.Open(name)
}
Loading

1 comment on commit 7eb7829

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 7eb7829 Previous: 66fd58b Ratio
BenchmarkFlatten/depth-1_[]int([1_2_3]) 171.9 ns/op 168 B/op 5 allocs/op 165.7 ns/op 168 B/op 5 allocs/op 1.04
BenchmarkFlatten/depth-1_[]int([1_2_3]) - ns/op 171.9 ns/op 165.7 ns/op 1.04
BenchmarkFlatten/depth-1_[]int([1_2_3]) - B/op 168 B/op 168 B/op 1
BenchmarkFlatten/depth-1_[]int([1_2_3]) - allocs/op 5 allocs/op 5 allocs/op 1
BenchmarkFlatten/depth-1_[3]int([1_2_3]) 127 ns/op 144 B/op 2 allocs/op 117.2 ns/op 144 B/op 2 allocs/op 1.08
BenchmarkFlatten/depth-1_[3]int([1_2_3]) - ns/op 127 ns/op 117.2 ns/op 1.08
BenchmarkFlatten/depth-1_[3]int([1_2_3]) - B/op 144 B/op 144 B/op 1
BenchmarkFlatten/depth-1_[3]int([1_2_3]) - allocs/op 2 allocs/op 2 allocs/op 1
BenchmarkFlatten/depth-1_[]interface_{}([[]_[1_2]_3]) 205.1 ns/op 208 B/op 5 allocs/op 203.4 ns/op 208 B/op 5 allocs/op 1.01
BenchmarkFlatten/depth-1_[]interface_{}([[]_[1_2]_3]) - ns/op 205.1 ns/op 203.4 ns/op 1.01
BenchmarkFlatten/depth-1_[]interface_{}([[]_[1_2]_3]) - B/op 208 B/op 208 B/op 1
BenchmarkFlatten/depth-1_[]interface_{}([[]_[1_2]_3]) - allocs/op 5 allocs/op 5 allocs/op 1
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[1_2]]_3]) 437 ns/op 344 B/op 11 allocs/op 422.8 ns/op 344 B/op 11 allocs/op 1.03
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[1_2]]_3]) - ns/op 437 ns/op 422.8 ns/op 1.03
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[1_2]]_3]) - B/op 344 B/op 344 B/op 1
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[1_2]]_3]) - allocs/op 11 allocs/op 11 allocs/op 1
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) 883.8 ns/op 896 B/op 19 allocs/op 791.2 ns/op 896 B/op 19 allocs/op 1.12
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - ns/op 883.8 ns/op 791.2 ns/op 1.12
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - B/op 896 B/op 896 B/op 1
BenchmarkFlatten/depth-1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - allocs/op 19 allocs/op 19 allocs/op 1
BenchmarkFlatten/depth0_[]int([1_2_3]) 118.2 ns/op 72 B/op 4 allocs/op 114.2 ns/op 72 B/op 4 allocs/op 1.04
BenchmarkFlatten/depth0_[]int([1_2_3]) - ns/op 118.2 ns/op 114.2 ns/op 1.04
BenchmarkFlatten/depth0_[]int([1_2_3]) - B/op 72 B/op 72 B/op 1
BenchmarkFlatten/depth0_[]int([1_2_3]) - allocs/op 4 allocs/op 4 allocs/op 1
BenchmarkFlatten/depth0_[3]int([1_2_3]) 63.67 ns/op 48 B/op 1 allocs/op 63.74 ns/op 48 B/op 1 allocs/op 1.00
BenchmarkFlatten/depth0_[3]int([1_2_3]) - ns/op 63.67 ns/op 63.74 ns/op 1.00
BenchmarkFlatten/depth0_[3]int([1_2_3]) - B/op 48 B/op 48 B/op 1
BenchmarkFlatten/depth0_[3]int([1_2_3]) - allocs/op 1 allocs/op 1 allocs/op 1
BenchmarkFlatten/depth0_[]interface_{}([[]_[1_2]_3]) 4.335 ns/op 0 B/op 0 allocs/op 4.33 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkFlatten/depth0_[]interface_{}([[]_[1_2]_3]) - ns/op 4.335 ns/op 4.33 ns/op 1.00
BenchmarkFlatten/depth0_[]interface_{}([[]_[1_2]_3]) - B/op 0 B/op 0 B/op 1
BenchmarkFlatten/depth0_[]interface_{}([[]_[1_2]_3]) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[1_2]]_3]) 4.333 ns/op 0 B/op 0 allocs/op 4.442 ns/op 0 B/op 0 allocs/op 0.98
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[1_2]]_3]) - ns/op 4.333 ns/op 4.442 ns/op 0.98
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[1_2]]_3]) - B/op 0 B/op 0 B/op 1
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[1_2]]_3]) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) 4.334 ns/op 0 B/op 0 allocs/op 4.301 ns/op 0 B/op 0 allocs/op 1.01
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - ns/op 4.334 ns/op 4.301 ns/op 1.01
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - B/op 0 B/op 0 B/op 1
BenchmarkFlatten/depth0_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkFlatten/depth1_[]int([1_2_3]) 170.9 ns/op 168 B/op 5 allocs/op 166.1 ns/op 168 B/op 5 allocs/op 1.03
BenchmarkFlatten/depth1_[]int([1_2_3]) - ns/op 170.9 ns/op 166.1 ns/op 1.03
BenchmarkFlatten/depth1_[]int([1_2_3]) - B/op 168 B/op 168 B/op 1
BenchmarkFlatten/depth1_[]int([1_2_3]) - allocs/op 5 allocs/op 5 allocs/op 1
BenchmarkFlatten/depth1_[3]int([1_2_3]) 116.9 ns/op 144 B/op 2 allocs/op 116.9 ns/op 144 B/op 2 allocs/op 1
BenchmarkFlatten/depth1_[3]int([1_2_3]) - ns/op 116.9 ns/op 116.9 ns/op 1
BenchmarkFlatten/depth1_[3]int([1_2_3]) - B/op 144 B/op 144 B/op 1
BenchmarkFlatten/depth1_[3]int([1_2_3]) - allocs/op 2 allocs/op 2 allocs/op 1
BenchmarkFlatten/depth1_[]interface_{}([[]_[1_2]_3]) 160.3 ns/op 144 B/op 4 allocs/op 157.9 ns/op 144 B/op 4 allocs/op 1.02
BenchmarkFlatten/depth1_[]interface_{}([[]_[1_2]_3]) - ns/op 160.3 ns/op 157.9 ns/op 1.02
BenchmarkFlatten/depth1_[]interface_{}([[]_[1_2]_3]) - B/op 144 B/op 144 B/op 1
BenchmarkFlatten/depth1_[]interface_{}([[]_[1_2]_3]) - allocs/op 4 allocs/op 4 allocs/op 1
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[1_2]]_3]) 219.6 ns/op 168 B/op 5 allocs/op 210.8 ns/op 168 B/op 5 allocs/op 1.04
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[1_2]]_3]) - ns/op 219.6 ns/op 210.8 ns/op 1.04
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[1_2]]_3]) - B/op 168 B/op 168 B/op 1
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[1_2]]_3]) - allocs/op 5 allocs/op 5 allocs/op 1
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) 145 ns/op 128 B/op 3 allocs/op 140.6 ns/op 128 B/op 3 allocs/op 1.03
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - ns/op 145 ns/op 140.6 ns/op 1.03
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - B/op 128 B/op 128 B/op 1
BenchmarkFlatten/depth1_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkFlatten/depth2_[]int([1_2_3]) 171.9 ns/op 168 B/op 5 allocs/op 166.3 ns/op 168 B/op 5 allocs/op 1.03
BenchmarkFlatten/depth2_[]int([1_2_3]) - ns/op 171.9 ns/op 166.3 ns/op 1.03
BenchmarkFlatten/depth2_[]int([1_2_3]) - B/op 168 B/op 168 B/op 1
BenchmarkFlatten/depth2_[]int([1_2_3]) - allocs/op 5 allocs/op 5 allocs/op 1
BenchmarkFlatten/depth2_[3]int([1_2_3]) 116.6 ns/op 144 B/op 2 allocs/op 116.9 ns/op 144 B/op 2 allocs/op 1.00
BenchmarkFlatten/depth2_[3]int([1_2_3]) - ns/op 116.6 ns/op 116.9 ns/op 1.00
BenchmarkFlatten/depth2_[3]int([1_2_3]) - B/op 144 B/op 144 B/op 1
BenchmarkFlatten/depth2_[3]int([1_2_3]) - allocs/op 2 allocs/op 2 allocs/op 1
BenchmarkFlatten/depth2_[]interface_{}([[]_[1_2]_3]) 205 ns/op 208 B/op 5 allocs/op 203.9 ns/op 208 B/op 5 allocs/op 1.01
BenchmarkFlatten/depth2_[]interface_{}([[]_[1_2]_3]) - ns/op 205 ns/op 203.9 ns/op 1.01
BenchmarkFlatten/depth2_[]interface_{}([[]_[1_2]_3]) - B/op 208 B/op 208 B/op 1
BenchmarkFlatten/depth2_[]interface_{}([[]_[1_2]_3]) - allocs/op 5 allocs/op 5 allocs/op 1
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[1_2]]_3]) 381.1 ns/op 280 B/op 10 allocs/op 368.6 ns/op 280 B/op 10 allocs/op 1.03
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[1_2]]_3]) - ns/op 381.1 ns/op 368.6 ns/op 1.03
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[1_2]]_3]) - B/op 280 B/op 280 B/op 1
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[1_2]]_3]) - allocs/op 10 allocs/op 10 allocs/op 1
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) 323.1 ns/op 272 B/op 8 allocs/op 324.6 ns/op 272 B/op 8 allocs/op 1.00
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - ns/op 323.1 ns/op 324.6 ns/op 1.00
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - B/op 272 B/op 272 B/op 1
BenchmarkFlatten/depth2_[]interface_{}([[one]_[[[1]_[2_[3]]]_[4_5]]_6]) - allocs/op 8 allocs/op 8 allocs/op 1
BenchmarkInterfaceSlice/[]int([1_2_3]) 118.2 ns/op 72 B/op 4 allocs/op 112.6 ns/op 72 B/op 4 allocs/op 1.05
BenchmarkInterfaceSlice/[]int([1_2_3]) - ns/op 118.2 ns/op 112.6 ns/op 1.05
BenchmarkInterfaceSlice/[]int([1_2_3]) - B/op 72 B/op 72 B/op 1
BenchmarkInterfaceSlice/[]int([1_2_3]) - allocs/op 4 allocs/op 4 allocs/op 1
BenchmarkInterfaceSlice/[3]int([1_2_3]) 63.8 ns/op 48 B/op 1 allocs/op 60.15 ns/op 48 B/op 1 allocs/op 1.06
BenchmarkInterfaceSlice/[3]int([1_2_3]) - ns/op 63.8 ns/op 60.15 ns/op 1.06
BenchmarkInterfaceSlice/[3]int([1_2_3]) - B/op 48 B/op 48 B/op 1
BenchmarkInterfaceSlice/[3]int([1_2_3]) - allocs/op 1 allocs/op 1 allocs/op 1
BenchmarkInterfaceSlice/[]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) 573.1 ns/op 384 B/op 13 allocs/op 536.3 ns/op 384 B/op 13 allocs/op 1.07
BenchmarkInterfaceSlice/[]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) - ns/op 573.1 ns/op 536.3 ns/op 1.07
BenchmarkInterfaceSlice/[]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) - B/op 384 B/op 384 B/op 1
BenchmarkInterfaceSlice/[]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) - allocs/op 13 allocs/op 13 allocs/op 1
BenchmarkInterfaceSlice/[12]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) 161.5 ns/op 192 B/op 1 allocs/op 152.9 ns/op 192 B/op 1 allocs/op 1.06
BenchmarkInterfaceSlice/[12]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) - ns/op 161.5 ns/op 152.9 ns/op 1.06
BenchmarkInterfaceSlice/[12]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) - B/op 192 B/op 192 B/op 1
BenchmarkInterfaceSlice/[12]string([foo_bar_baz_foo_bar_baz_foo_bar_baz_foo_bar_baz]) - allocs/op 1 allocs/op 1 allocs/op 1
BenchmarkInterfaceSlice/[]interface_{}([[]_[1_2]_3]) 2.169 ns/op 0 B/op 0 allocs/op 2.202 ns/op 0 B/op 0 allocs/op 0.99
BenchmarkInterfaceSlice/[]interface_{}([[]_[1_2]_3]) - ns/op 2.169 ns/op 2.202 ns/op 0.99
BenchmarkInterfaceSlice/[]interface_{}([[]_[1_2]_3]) - B/op 0 B/op 0 B/op 1
BenchmarkInterfaceSlice/[]interface_{}([[]_[1_2]_3]) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkInterfaceSlice/[3]interface_{}([[]_[1_2]_3]) 69.64 ns/op 48 B/op 1 allocs/op 63.17 ns/op 48 B/op 1 allocs/op 1.10
BenchmarkInterfaceSlice/[3]interface_{}([[]_[1_2]_3]) - ns/op 69.64 ns/op 63.17 ns/op 1.10
BenchmarkInterfaceSlice/[3]interface_{}([[]_[1_2]_3]) - B/op 48 B/op 48 B/op 1
BenchmarkInterfaceSlice/[3]interface_{}([[]_[1_2]_3]) - allocs/op 1 allocs/op 1 allocs/op 1
BenchmarkToBytes 1035 ns/op 40 B/op 3 allocs/op 1125 ns/op 40 B/op 3 allocs/op 0.92
BenchmarkToBytes - ns/op 1035 ns/op 1125 ns/op 0.92
BenchmarkToBytes - B/op 40 B/op 40 B/op 1
BenchmarkToBytes - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/int(0) 3.1 ns/op 0 B/op 0 allocs/op 3.178 ns/op 0 B/op 0 allocs/op 0.98
BenchmarkIsFloat/int(0) - ns/op 3.1 ns/op 3.178 ns/op 0.98
BenchmarkIsFloat/int(0) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int(0) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int(1) 3.272 ns/op 0 B/op 0 allocs/op 3.102 ns/op 0 B/op 0 allocs/op 1.05
BenchmarkIsFloat/int(1) - ns/op 3.272 ns/op 3.102 ns/op 1.05
BenchmarkIsFloat/int(1) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int(1) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int(-1) 3.112 ns/op 0 B/op 0 allocs/op 3.135 ns/op 0 B/op 0 allocs/op 0.99
BenchmarkIsFloat/int(-1) - ns/op 3.112 ns/op 3.135 ns/op 0.99
BenchmarkIsFloat/int(-1) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int(-1) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/uint(42) 3.096 ns/op 0 B/op 0 allocs/op 3.097 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/uint(42) - ns/op 3.096 ns/op 3.097 ns/op 1.00
BenchmarkIsFloat/uint(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/uint(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/uint8(255) 3.165 ns/op 0 B/op 0 allocs/op 3.097 ns/op 0 B/op 0 allocs/op 1.02
BenchmarkIsFloat/uint8(255) - ns/op 3.165 ns/op 3.097 ns/op 1.02
BenchmarkIsFloat/uint8(255) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/uint8(255) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/uint16(42) 3.096 ns/op 0 B/op 0 allocs/op 3.102 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/uint16(42) - ns/op 3.096 ns/op 3.102 ns/op 1.00
BenchmarkIsFloat/uint16(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/uint16(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/uint32(42) 3.12 ns/op 0 B/op 0 allocs/op 3.096 ns/op 0 B/op 0 allocs/op 1.01
BenchmarkIsFloat/uint32(42) - ns/op 3.12 ns/op 3.096 ns/op 1.01
BenchmarkIsFloat/uint32(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/uint32(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/uint64(42) 3.096 ns/op 0 B/op 0 allocs/op 3.101 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/uint64(42) - ns/op 3.096 ns/op 3.101 ns/op 1.00
BenchmarkIsFloat/uint64(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/uint64(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int(42) 3.098 ns/op 0 B/op 0 allocs/op 3.101 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/int(42) - ns/op 3.098 ns/op 3.101 ns/op 1.00
BenchmarkIsFloat/int(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int8(127) 3.097 ns/op 0 B/op 0 allocs/op 3.096 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/int8(127) - ns/op 3.097 ns/op 3.096 ns/op 1.00
BenchmarkIsFloat/int8(127) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int8(127) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int16(42) 3.096 ns/op 0 B/op 0 allocs/op 3.102 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/int16(42) - ns/op 3.096 ns/op 3.102 ns/op 1.00
BenchmarkIsFloat/int16(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int16(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int32(42) 3.098 ns/op 0 B/op 0 allocs/op 3.094 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/int32(42) - ns/op 3.098 ns/op 3.094 ns/op 1.00
BenchmarkIsFloat/int32(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int32(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/int64(42) 3.095 ns/op 0 B/op 0 allocs/op 3.1 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/int64(42) - ns/op 3.095 ns/op 3.1 ns/op 1.00
BenchmarkIsFloat/int64(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/int64(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/float32(18.3) 2.785 ns/op 0 B/op 0 allocs/op 2.786 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/float32(18.3) - ns/op 2.785 ns/op 2.786 ns/op 1.00
BenchmarkIsFloat/float32(18.3) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/float32(18.3) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/float64(18.3) 2.79 ns/op 0 B/op 0 allocs/op 2.792 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/float64(18.3) - ns/op 2.79 ns/op 2.792 ns/op 1.00
BenchmarkIsFloat/float64(18.3) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/float64(18.3) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/float64(1.5) 2.792 ns/op 0 B/op 0 allocs/op 2.786 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/float64(1.5) - ns/op 2.792 ns/op 2.786 ns/op 1.00
BenchmarkIsFloat/float64(1.5) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/float64(1.5) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/float64(-18.6) 2.794 ns/op 0 B/op 0 allocs/op 2.789 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/float64(-18.6) - ns/op 2.794 ns/op 2.789 ns/op 1.00
BenchmarkIsFloat/float64(-18.6) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/float64(-18.6) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/string(42) 34.74 ns/op 0 B/op 0 allocs/op 34.1 ns/op 0 B/op 0 allocs/op 1.02
BenchmarkIsFloat/string(42) - ns/op 34.74 ns/op 34.1 ns/op 1.02
BenchmarkIsFloat/string(42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/string(42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/string(052) 38.45 ns/op 0 B/op 0 allocs/op 38.08 ns/op 0 B/op 0 allocs/op 1.01
BenchmarkIsFloat/string(052) - ns/op 38.45 ns/op 38.08 ns/op 1.01
BenchmarkIsFloat/string(052) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/string(052) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/string(0xff) 74.06 ns/op 52 B/op 2 allocs/op 72.28 ns/op 52 B/op 2 allocs/op 1.02
BenchmarkIsFloat/string(0xff) - ns/op 74.06 ns/op 72.28 ns/op 1.02
BenchmarkIsFloat/string(0xff) - B/op 52 B/op 52 B/op 1
BenchmarkIsFloat/string(0xff) - allocs/op 2 allocs/op 2 allocs/op 1
BenchmarkIsFloat/string(-42) 36.88 ns/op 0 B/op 0 allocs/op 35.95 ns/op 0 B/op 0 allocs/op 1.03
BenchmarkIsFloat/string(-42) - ns/op 36.88 ns/op 35.95 ns/op 1.03
BenchmarkIsFloat/string(-42) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/string(-42) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/string(-0) 32.28 ns/op 0 B/op 0 allocs/op 32.63 ns/op 0 B/op 0 allocs/op 0.99
BenchmarkIsFloat/string(-0) - ns/op 32.28 ns/op 32.63 ns/op 0.99
BenchmarkIsFloat/string(-0) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/string(-0) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkIsFloat/string(3.14) 106.7 ns/op 56 B/op 3 allocs/op 105.3 ns/op 56 B/op 3 allocs/op 1.01
BenchmarkIsFloat/string(3.14) - ns/op 106.7 ns/op 105.3 ns/op 1.01
BenchmarkIsFloat/string(3.14) - B/op 56 B/op 56 B/op 1
BenchmarkIsFloat/string(3.14) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/string(-3.14) 121.9 ns/op 64 B/op 3 allocs/op 112.2 ns/op 64 B/op 3 allocs/op 1.09
BenchmarkIsFloat/string(-3.14) - ns/op 121.9 ns/op 112.2 ns/op 1.09
BenchmarkIsFloat/string(-3.14) - B/op 64 B/op 64 B/op 1
BenchmarkIsFloat/string(-3.14) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/string(0.00) 104.8 ns/op 56 B/op 3 allocs/op 105.8 ns/op 56 B/op 3 allocs/op 0.99
BenchmarkIsFloat/string(0.00) - ns/op 104.8 ns/op 105.8 ns/op 0.99
BenchmarkIsFloat/string(0.00) - B/op 56 B/op 56 B/op 1
BenchmarkIsFloat/string(0.00) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/string(NaN) 94.62 ns/op 54 B/op 3 allocs/op 93.86 ns/op 54 B/op 3 allocs/op 1.01
BenchmarkIsFloat/string(NaN) - ns/op 94.62 ns/op 93.86 ns/op 1.01
BenchmarkIsFloat/string(NaN) - B/op 54 B/op 54 B/op 1
BenchmarkIsFloat/string(NaN) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/string(-Inf) 97.06 ns/op 56 B/op 3 allocs/op 92.49 ns/op 56 B/op 3 allocs/op 1.05
BenchmarkIsFloat/string(-Inf) - ns/op 97.06 ns/op 92.49 ns/op 1.05
BenchmarkIsFloat/string(-Inf) - B/op 56 B/op 56 B/op 1
BenchmarkIsFloat/string(-Inf) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/string(+Inf) 96.8 ns/op 56 B/op 3 allocs/op 93.17 ns/op 56 B/op 3 allocs/op 1.04
BenchmarkIsFloat/string(+Inf) - ns/op 96.8 ns/op 93.17 ns/op 1.04
BenchmarkIsFloat/string(+Inf) - B/op 56 B/op 56 B/op 1
BenchmarkIsFloat/string(+Inf) - allocs/op 3 allocs/op 3 allocs/op 1
BenchmarkIsFloat/string() 50.73 ns/op 48 B/op 1 allocs/op 49.84 ns/op 48 B/op 1 allocs/op 1.02
BenchmarkIsFloat/string() - ns/op 50.73 ns/op 49.84 ns/op 1.02
BenchmarkIsFloat/string() - B/op 48 B/op 48 B/op 1
BenchmarkIsFloat/string() - allocs/op 1 allocs/op 1 allocs/op 1
BenchmarkIsFloat/string(foo) 72.12 ns/op 51 B/op 2 allocs/op 69.53 ns/op 51 B/op 2 allocs/op 1.04
BenchmarkIsFloat/string(foo) - ns/op 72.12 ns/op 69.53 ns/op 1.04
BenchmarkIsFloat/string(foo) - B/op 51 B/op 51 B/op 1
BenchmarkIsFloat/string(foo) - allocs/op 2 allocs/op 2 allocs/op 1
BenchmarkIsFloat/bool(true) 3.099 ns/op 0 B/op 0 allocs/op 3.097 ns/op 0 B/op 0 allocs/op 1.00
BenchmarkIsFloat/bool(true) - ns/op 3.099 ns/op 3.097 ns/op 1.00
BenchmarkIsFloat/bool(true) - B/op 0 B/op 0 B/op 1
BenchmarkIsFloat/bool(true) - allocs/op 0 allocs/op 0 allocs/op 1
BenchmarkLookupIPs 48468 ns/op 1872 B/op 46 allocs/op 50737 ns/op 1840 B/op 44 allocs/op 0.96
BenchmarkLookupIPs - ns/op 48468 ns/op 50737 ns/op 0.96
BenchmarkLookupIPs - B/op 1872 B/op 1840 B/op 1.02
BenchmarkLookupIPs - allocs/op 46 allocs/op 44 allocs/op 1.05
BenchmarkIndent 1837 ns/op 2040 B/op 18 allocs/op 1946 ns/op 2064 B/op 20 allocs/op 0.94
BenchmarkIndent - ns/op 1837 ns/op 1946 ns/op 0.94
BenchmarkIndent - B/op 2040 B/op 2064 B/op 0.99
BenchmarkIndent - allocs/op 18 allocs/op 20 allocs/op 0.90

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.