Skip to content

Commit 5c6cf4f

Browse files
nigeltaobradfitz
authored andcommitted
internal/gen: work around long string concatenation.
The compiler has trouble compiling the concatenation of many strings, s0 + s1 + s2 + ... + sN, for large N. We insert redundant, explicit parentheses to work around that, lowering the N at any given step. Some before/after's on GOOS=linux GOARCH=amd64 from /usr/bin/time -v go install golang.org/x/text/unicode/runenames Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.21 Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.33 Maximum resident set size (kbytes): 4414556 Maximum resident set size (kbytes): 135040 Minor (reclaiming a frame) page faults: 1071428 Minor (reclaiming a frame) page faults: 40242 Fixes golang/go#18078 Change-Id: I6f0bfcc26ae4f1c8fea010a2ee3d815567426b2d Reviewed-on: https://go-review.googlesource.com/33598 Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 4ea6c07 commit 5c6cf4f

File tree

2 files changed

+193
-175
lines changed

2 files changed

+193
-175
lines changed

internal/gen/code.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,27 @@ func (w *CodeWriter) WriteString(s string) {
197197
// When starting on its own line, go fmt indents line 2+ an extra level.
198198
n, max := maxWidth, maxWidth-4
199199

200+
// As per https://golang.org/issue/18078, the compiler has trouble
201+
// compiling the concatenation of many strings, s0 + s1 + s2 + ... + sN,
202+
// for large N. We insert redundant, explicit parentheses to work around
203+
// that, lowering the N at any given step: (s0 + s1 + ... + s63) + (s64 +
204+
// ... + s127) + etc + (etc + ... + sN).
205+
explicitParens, extraComment := len(s) > 128*1024, ""
206+
if explicitParens {
207+
w.printf(`(`)
208+
extraComment = "; the redundant, explicit parens are for https://golang.org/issue/18078"
209+
}
210+
200211
// Print "" +\n, if a string does not start on its own line.
201212
b := w.buf.Bytes()
202213
if p := len(bytes.TrimRight(b, " \t")); p > 0 && b[p-1] != '\n' {
203-
w.printf("\"\" + // Size: %d bytes\n", len(s))
214+
w.printf("\"\" + // Size: %d bytes%s\n", len(s), extraComment)
204215
n, max = maxWidth, maxWidth
205216
}
206217

207218
w.printf(`"`)
208219

209-
for sz, p := 0, 0; p < len(s); {
220+
for sz, p, nLines := 0, 0, 0; p < len(s); {
210221
var r rune
211222
r, sz = utf8.DecodeRuneInString(s[p:])
212223
out := s[p : p+sz]
@@ -223,13 +234,20 @@ func (w *CodeWriter) WriteString(s string) {
223234
chars = len(out)
224235
}
225236
if n -= chars; n < 0 {
237+
nLines++
238+
if explicitParens && nLines&63 == 63 {
239+
w.printf("\") + (\"")
240+
}
226241
w.printf("\" +\n\"")
227242
n = max - len(out)
228243
}
229244
w.printf("%s", out)
230245
p += sz
231246
}
232247
w.printf(`"`)
248+
if explicitParens {
249+
w.printf(`)`)
250+
}
233251
}
234252

235253
// WriteSlice writes a slice value.

0 commit comments

Comments
 (0)