Skip to content

Commit 7466cad

Browse files
committed
[dev.link] cmd/link: only allow heap area to grow to 10MB
With CL 228782, we've removed file I/O, but we're growing the memory too much. This change will periodically flush the heap area to the mmapped area (if possible). Change-Id: I1622c738ee5a1a6d02bff5abb0a5751caf8095c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/229439 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
1 parent 0072360 commit 7466cad

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

src/cmd/link/internal/ld/outbuf.go

+28-14
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ func (out *OutBuf) Close() error {
113113
return viewCloseError
114114
}
115115
if out.isMmapped() {
116-
return out.Munmap()
116+
out.copyHeap()
117+
out.munmap()
118+
return nil
117119
}
118120
if out.f == nil {
119121
return nil
@@ -135,26 +137,33 @@ func (out *OutBuf) isMmapped() bool {
135137
return len(out.buf) != 0
136138
}
137139

138-
// Munmap cleans up all the output buffer.
139-
func (out *OutBuf) Munmap() error {
140-
wasMapped := out.isMmapped()
140+
// copyHeap copies the heap to the mmapped section of memory, returning true if
141+
// a copy takes place.
142+
func (out *OutBuf) copyHeap() bool {
143+
if !out.isMmapped() { // only valuable for mmapped OutBufs.
144+
return false
145+
}
146+
if out.isView {
147+
panic("can't copyHeap a view")
148+
}
149+
141150
bufLen := len(out.buf)
142151
heapLen := len(out.heap)
143152
total := uint64(bufLen + heapLen)
144-
if wasMapped {
145-
out.munmap()
146-
if heapLen != 0 {
147-
if err := out.Mmap(total); err != nil {
148-
return err
149-
}
150-
copy(out.buf[bufLen:], out.heap[:heapLen])
151-
out.heap = nil
152-
out.munmap()
153+
out.munmap()
154+
if heapLen != 0 {
155+
if err := out.Mmap(total); err != nil {
156+
panic(err)
153157
}
158+
copy(out.buf[bufLen:], out.heap[:heapLen])
159+
out.heap = out.heap[:0]
154160
}
155-
return nil
161+
return true
156162
}
157163

164+
// maxOutBufHeapLen limits the growth of the heap area.
165+
const maxOutBufHeapLen = 10 << 20
166+
158167
// writeLoc determines the write location if a buffer is mmaped.
159168
// We maintain two write buffers, an mmapped section, and a heap section for
160169
// writing. When the mmapped section is full, we switch over the heap memory
@@ -176,6 +185,11 @@ func (out *OutBuf) writeLoc(lenToWrite int64) (int64, []byte) {
176185
if out.isView {
177186
panic("cannot write to heap in parallel")
178187
}
188+
// See if our heap would grow to be too large, and if so, copy it to the end
189+
// of the mmapped area.
190+
if heapLen > maxOutBufHeapLen && out.copyHeap() {
191+
heapPos, heapLen, lenNeeded = 0, 0, lenToWrite
192+
}
179193
out.heap = append(out.heap, make([]byte, lenNeeded-heapLen)...)
180194
}
181195
return heapPos, out.heap

0 commit comments

Comments
 (0)