Skip to content
Merged
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
18 changes: 17 additions & 1 deletion jwriter/token_writer_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ var (

const hexDigits = "0123456789abcdef"

// plainStringChars marks the bytes that writeQuotedString copies into a JSON string
// verbatim. Unlike the reader's equivalent table, bytes outside the ASCII range are
// plain here: this writer never escapes them, so multi-byte characters pass through
// without inspection. A single table lookup per byte is measurably faster than the
// equivalent range and equality comparisons in this loop.
var plainStringChars = makePlainStringChars() //nolint:gochecknoglobals

func makePlainStringChars() (t [256]bool) {
for c := 0x20; c < 256; c++ {
if c != '"' && c != '\\' {
t[c] = true
}
}
return
}

// initialBufferCapacity is the buffer capacity preallocated by newTokenWriter. Paying for one
// small allocation up front keeps the append growth ladder short for typical outputs; it is
// the same minimum that bytes.Buffer uses.
Expand Down Expand Up @@ -153,7 +169,7 @@ func (tw *tokenWriter) writeQuotedString(s string) error {
start := 0
for i := 0; i < len(s); i++ {
aByte := s[i]
if aByte >= ' ' && aByte != '"' && aByte != '\\' {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

When working on the read performance we had a similar shape and a LUT was a clear win in comparison. So I tested it out on the writer and it was also a win here.

if plainStringChars[aByte] {
continue
}
dst = append(dst, s[start:i]...)
Expand Down
Loading