From 1e1f83c63d025b185ed374600c06a29537ae45b5 Mon Sep 17 00:00:00 2001 From: shamaton Date: Fri, 5 Jun 2026 22:26:14 +0900 Subject: [PATCH 1/3] perf: speed up generated encode paths --- internal/generator/gen.go | 12 ++++++++---- internal/generator/structure/code_array.go | 17 +++++++++++++++-- internal/generator/structure/code_slice.go | 17 +++++++++++++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/internal/generator/gen.go b/internal/generator/gen.go index 84fe2ff..ca90db0 100644 --- a/internal/generator/gen.go +++ b/internal/generator/gen.go @@ -492,8 +492,10 @@ func (g *generator) publicEncodeReturn(privateFuncName, fallbackFuncName string) } if !g.strict { code = append(code, - If(Qual("errors", "Is").Call(Err(), Qual(ptn.PkTop, "ErrUndefinedType"))).Block( - Return(Qual(ptn.PkFallback, fallbackFuncName).Call(Id("v"))), + If(Err().Op("!=").Nil()).Block( + If(Qual("errors", "Is").Call(Err(), Qual(ptn.PkTop, "ErrUndefinedType"))).Block( + Return(Qual(ptn.PkFallback, fallbackFuncName).Call(Id("v"))), + ), ), ) } @@ -506,8 +508,10 @@ func (g *generator) publicDecodeReturn(privateFuncName, fallbackFuncName string) } if !g.strict { code = append(code, - If(Qual("errors", "Is").Call(Err(), Qual(ptn.PkTop, "ErrUndefinedType"))).Block( - Return(Qual(ptn.PkFallback, fallbackFuncName).Call(Id("data"), Id("v"))), + If(Err().Op("!=").Nil()).Block( + If(Qual("errors", "Is").Call(Err(), Qual(ptn.PkTop, "ErrUndefinedType"))).Block( + Return(Qual(ptn.PkFallback, fallbackFuncName).Call(Id("data"), Id("v"))), + ), ), ) } diff --git a/internal/generator/structure/code_array.go b/internal/generator/structure/code_array.go index 08b9734..985350a 100644 --- a/internal/generator/structure/code_array.go +++ b/internal/generator/structure/code_array.go @@ -45,7 +45,11 @@ func (st *Structure) createArrayCode(node *Node, encodeFieldName, decodeFieldNam func (g arrayCodeGen) createCalcCode(fieldName, childName string, isChildByte, passChildPointer bool, elmCodes []Code) []Code { blockCodes := createAddSizeErrCheckCode("CalcSliceLength", Len(Id(fieldName)), Lit(isChildByte)) - blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + if isChildByte { + blockCodes = append(blockCodes, Id("size").Op("+=").Len(Id(fieldName))) + } else { + blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + } codes := make([]Code, 0) codes = append(codes, Block( @@ -58,7 +62,16 @@ func (g arrayCodeGen) createEncCode(fieldName, childName string, isChildByte, pa blockCodes := make([]Code, 0) blockCodes = append(blockCodes, Id("offset").Op("=").Qual(ptn.PkEnc, "WriteSliceLength").Call(Id("buf"), Len(Id(fieldName)), Id("offset"), Lit(isChildByte))) - blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + if isChildByte { + blockCodes = append(blockCodes, + Id("offset").Op("+=").Id("copy").Call( + Id("buf").Index(Id("offset").Op(":").Id("offset").Op("+").Len(Id(fieldName))), + Id(fieldName).Index(Op(":")), + ), + ) + } else { + blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + } codes := make([]Code, 0) codes = append(codes, Block( diff --git a/internal/generator/structure/code_slice.go b/internal/generator/structure/code_slice.go index ed5454a..4ae1a84 100644 --- a/internal/generator/structure/code_slice.go +++ b/internal/generator/structure/code_slice.go @@ -42,7 +42,11 @@ func (st *Structure) createSliceCode(node *Node, encodeFieldName, decodeFieldNam func (g sliceCodeGen) createCalcCode(fieldName, childName string, isChildTypeByte, passChildPointer bool, elmCodes []Code) []Code { blockCodes := createAddSizeErrCheckCode("CalcSliceLength", Len(Id(fieldName)), Lit(isChildTypeByte)) - blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + if isChildTypeByte { + blockCodes = append(blockCodes, Id("size").Op("+=").Len(Id(fieldName))) + } else { + blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + } codes := make([]Code, 0) codes = append(codes, If(Id(fieldName).Op("!=").Nil()).Block( @@ -57,7 +61,16 @@ func (g sliceCodeGen) createEncCode(fieldName, childName string, isChildTypeByte blockCodes := make([]Code, 0) blockCodes = append(blockCodes, Id("offset").Op("=").Qual(ptn.PkEnc, "WriteSliceLength").Call(Id("buf"), Len(Id(fieldName)), Id("offset"), Lit(isChildTypeByte))) - blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + if isChildTypeByte { + blockCodes = append(blockCodes, + Id("offset").Op("+=").Id("copy").Call( + Id("buf").Index(Id("offset").Op(":").Id("offset").Op("+").Len(Id(fieldName))), + Id(fieldName), + ), + ) + } else { + blockCodes = append(blockCodes, createSequenceRangeCode(fieldName, childName, passChildPointer, elmCodes)) + } codes := make([]Code, 0) codes = append(codes, If(Id(fieldName).Op("!=").Nil()).Block( From 71deae47aef502ef53cd9044044ff58fff8b7f6f Mon Sep 17 00:00:00 2001 From: shamaton Date: Sun, 7 Jun 2026 15:28:15 +0900 Subject: [PATCH 2/3] chore: update README --- README.md | 88 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index c26e154..0a314dd 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ **msgpackgen** provides a code generation tool and serialization library for [MessagePack](http://msgpack.org/). -* 🚀 Extremely Fast -* ♻️ Easy Maintenance -* 💯 Compliant with [specifications](https://github.com/msgpack/msgpack/blob/master/spec.md) -* 🦺 No use `unsafe` +- 🚀 Extremely Fast +- ♻️ Easy Maintenance +- 💯 Compliant with [specifications](https://github.com/msgpack/msgpack/blob/master/spec.md) +- 🦺 No use `unsafe` ## Quickstart @@ -95,17 +95,17 @@ struct: `time.Time` and structures you defined Renaming or omitting are available. -* Renaming fields via `msgpack:"field_name"` -* Omitting fields via `msgpack:"-"` -* Omitting zero-value fields from map encoding via `msgpack:",omitempty"` or `msgpack:"field_name,omitempty"` +- Renaming fields via `msgpack:"field_name"` +- Omitting fields via `msgpack:"-"` +- Omitting zero-value fields from map encoding via `msgpack:",omitempty"` or `msgpack:"field_name,omitempty"` For example: ```go type Example struct { - ID int - Name string `msgpack:"name,omitempty"` - Extra string `msgpack:",omitempty"` + ID int + Name string `msgpack:"name,omitempty"` + Extra string `msgpack:",omitempty"` } ``` @@ -132,9 +132,9 @@ All you have to delete is one generated `.go` file. Code is generated by recursively searching directories, but some directories and files are ignored. -* Prefix `_` and `.` directory. -* `testdata` and `vendor` directory -* `_test.go` file +- Prefix `_` and `.` directory. +- `testdata` and `vendor` directory +- `_test.go` file If you use `-input-file` option, it will work without considering the above conditions. @@ -144,9 +144,9 @@ Compatible with various import rules. ```go import ( - "example.com/user/a/b" - d "example.com/user/a/c" - . "example.com/user/a/e" + "example.com/user/a/b" + d "example.com/user/a/c" + . "example.com/user/a/e" ) ``` @@ -157,31 +157,31 @@ Not generated in the following cases: ```go // ex. a/example.go type Example struct { - // unsupported types - Interface any - Uintptr uintptr - Error error - Chan chan - Func func() + // unsupported types + Interface any + Uintptr uintptr + Error error + Chan chan + Func func() - // nested struct is also unsupported - NestedStruct struct {} + // nested struct is also unsupported + NestedStruct struct {} - // because b.Example is not generated - B b.Example + // because b.Example is not generated + B b.Example - // because bytes.Buffer is in outside package - Buf bytes.Buffer + // because bytes.Buffer is in outside package + Buf bytes.Buffer } func (e Example) F() { - // unsupported struct defined in func - type InFunction struct {} + // unsupported struct defined in func + type InFunction struct {} } // ex a/b/example.go type Example struct { - Interface any + Interface any } ``` @@ -225,14 +225,18 @@ Our package results show in `ShamatonGen`. ![Benchmark Decode][benchmark-decode-image] -[go-reference-badge]:https://pkg.go.dev/badge/github.com/shamaton/msgpackgen.svg -[go-reference]:https://pkg.go.dev/github.com/shamaton/msgpackgen -[test-badge]:https://github.com/shamaton/msgpackgen/workflows/test/badge.svg -[go-report-badge]:https://goreportcard.com/badge/github.com/shamaton/msgpackgen -[go-report]:https://goreportcard.com/report/github.com/shamaton/msgpackgen -[codecov-badge]:https://codecov.io/gh/shamaton/msgpackgen/branch/main/graph/badge.svg?token=K7M3778X7C -[codecov]:https://codecov.io/gh/shamaton/msgpackgen -[fossa-badge]:https://app.fossa.com/api/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpackgen.svg?type=shield -[fossa]:https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpackgen?ref=badge_shield -[benchmark-encode-image]:https://raw.githubusercontent.com/shamaton/msgpack_bench/refs/heads/main/docs/benchmarks/compare-encode.svg -[benchmark-decode-image]:https://raw.githubusercontent.com/shamaton/msgpack_bench/refs/heads/main/docs/benchmarks/compare-decode.svg +## License + +This library is under the MIT License. See the [LICENSE](./LICENSE) file for details. + +[go-reference-badge]: https://pkg.go.dev/badge/github.com/shamaton/msgpackgen.svg +[go-reference]: https://pkg.go.dev/github.com/shamaton/msgpackgen +[test-badge]: https://github.com/shamaton/msgpackgen/workflows/test/badge.svg +[go-report-badge]: https://goreportcard.com/badge/github.com/shamaton/msgpackgen +[go-report]: https://goreportcard.com/report/github.com/shamaton/msgpackgen +[codecov-badge]: https://codecov.io/gh/shamaton/msgpackgen/branch/main/graph/badge.svg?token=K7M3778X7C +[codecov]: https://codecov.io/gh/shamaton/msgpackgen +[fossa-badge]: https://app.fossa.com/api/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpackgen.svg?type=shield +[fossa]: https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpackgen?ref=badge_shield +[benchmark-encode-image]: https://raw.githubusercontent.com/shamaton/msgpack_bench/refs/heads/main/docs/benchmarks/compare-encode.svg +[benchmark-decode-image]: https://raw.githubusercontent.com/shamaton/msgpack_bench/refs/heads/main/docs/benchmarks/compare-decode.svg From f9f3867d932078951ed4c851c6b6fbde4a7309d0 Mon Sep 17 00:00:00 2001 From: shamaton Date: Sun, 7 Jun 2026 15:46:57 +0900 Subject: [PATCH 3/3] ci: add go 1.26 to test targets --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 787b53a..feb0399 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,6 @@ env: WORKSPACE: ${{ github.workspace }}/src/github.com/${{ github.repository }} jobs: - test: defaults: run: @@ -15,7 +14,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - go: [1.23, 1.24, 1.25] + go: [1.23, 1.24, 1.25, 1.26] name: ${{ matrix.os }} @ Go ${{ matrix.go }} runs-on: ${{ matrix.os }} steps: @@ -44,7 +43,7 @@ jobs: run: sh testdata/test.sh - name: Upload coverage to Codecov - if: success() && matrix.go == 1.25 && matrix.os == 'windows-latest' + if: success() && matrix.go == 1.26 && matrix.os == 'windows-latest' uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: