Как я могу уменьшить виртуальную память, необходимую для скомпилированного исполняемого файла gccgo? - PullRequest
0 голосов
/ 12 декабря 2018

Когда я компилирую этот простой пример hello world с использованием gccgo, полученный исполняемый файл использует более 800 МБ VmData.Я хотел бы знать, почему, и если есть что-то, что я могу сделать, чтобы снизить это.Сон только для того, чтобы дать мне время наблюдать за использованием памяти.

Источник:

package main

import (
  "fmt"
  "time"
)

func main() {
  fmt.Println("hello world")
  time.Sleep(1000000000 * 5)
}

Скрипт, который я использую для компиляции:

#!/bin/bash

TOOLCHAIN_PREFIX=i686-linux-gnu
OPTIMIZATION_FLAG="-O3"

CGO_ENABLED=1 \
CC=${TOOLCHAIN_PREFIX}-gcc-8 \
CXX=${TOOLCHAIN_PREFIX}-g++-8 \
AR=${TOOLCHAIN_PREFIX}-ar \
GCCGO=${TOOLCHAIN_PREFIX}-gccgo-8 \
CGO_CFLAGS="-g ${OPTIMIZATION_FLAG}" \
CGO_CPPFLAGS="" \
CGO_CXXFLAGS="-g ${OPTIMIZATION_FLAG}" \
CGO_FFLAGS="-g ${OPTIMIZATION_FLAG}" \
CGO_LDFLAGS="-g ${OPTIMIZATION_FLAG}" \
GOOS=linux \
GOARCH=386 \
go build -x \
   -compiler=gccgo \
   -gccgoflags=all="-static -g ${OPTIMIZATION_FLAG}" \
   $1

Версияgccgo:

$ i686-linux-gnu-gccgo-8 --version
i686-linux-gnu-gccgo-8 (Ubuntu 8.2.0-1ubuntu2~18.04) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Вывод из / proc / / status:

VmPeak:  811692 kB
VmSize:  811692 kB
VmLck:        0 kB
VmPin:        0 kB
VmHWM:     5796 kB
VmRSS:     5796 kB
VmData:  807196 kB
VmStk:      132 kB
VmExe:     2936 kB
VmLib:        0 kB
VmPTE:       52 kB
VmPMD:        0 kB
VmSwap:       0 kB

Я спрашиваю, потому что мое устройство имеет только 512 МБ оперативной памяти.Я знаю, что это виртуальная память, но я бы хотел уменьшить или убрать чрезмерную загрузку, если это возможно.Мне не кажется разумным, чтобы простой исполняемый файл требовал такого большого выделения.

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Мне удалось определить, где gccgo запрашивает столько памяти.Он находится в файле libgo / go / runtime / malloc.go в функции mallocinit:

// If we fail to allocate, try again with a smaller arena.
// This is necessary on Android L where we share a process
// with ART, which reserves virtual memory aggressively.
// In the worst case, fall back to a 0-sized initial arena,
// in the hope that subsequent reservations will succeed.
arenaSizes := [...]uintptr{
  512 << 20,
  256 << 20,
  128 << 20,
  0,
}

for _, arenaSize := range &arenaSizes {
  // SysReserve treats the address we ask for, end, as a hint,
  // not as an absolute requirement. If we ask for the end
  // of the data segment but the operating system requires
  // a little more space before we can start allocating, it will
  // give out a slightly higher pointer. Except QEMU, which
  // is buggy, as usual: it won't adjust the pointer upward.
  // So adjust it upward a little bit ourselves: 1/4 MB to get
  // away from the running binary image and then round up
  // to a MB boundary.
  p = round(getEnd()+(1<<18), 1<<20)
  pSize = bitmapSize + spansSize + arenaSize + _PageSize
  if p <= procBrk && procBrk < p+pSize {
    // Move the start above the brk,
    // leaving some room for future brk
    // expansion.
    p = round(procBrk+(1<<20), 1<<20)
  }
  p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved))
  if p != 0 {
    break
  }
}
if p == 0 {
  throw("runtime: cannot reserve arena virtual address space")
}

Интересная часть заключается в том, что при сбое больших размеров он возвращается к меньшим размерам арены.Поэтому ограничение виртуальной памяти, доступной для исполняемого файла go, фактически ограничит объем, который он будет успешно распределять.

Я смог использовать ulimit -v 327680, чтобы ограничить виртуальную память меньшими числами:

VmPeak:   300772 kB
VmSize:   300772 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:      5712 kB
VmRSS:      5712 kB
VmData:   296276 kB
VmStk:       132 kB
VmExe:      2936 kB
VmLib:         0 kB
VmPTE:        56 kB
VmPMD:         0 kB
VmSwap:        0 kB

Это все еще большие числа, но лучшее, что может достичь исполняемый файл gccgo.Таким образом, ответ на вопрос: да, вы можете уменьшить VmData скомпилированного исполняемого файла gccgo, но вам не стоит об этом беспокоиться. (На 64-битной машине gccgo пытается выделить 512 ГБ.)

0 голосов
/ 12 декабря 2018

Скорее всего, вы связываете библиотеки в код.Я предполагаю, что вы сможете получить меньшее логическое адресное пространство, если будете явно ссылаться на статические библиотеки, чтобы вы добавили минимум к вашему исполняемому файлу.В любом случае наличие большого логического адресного пространства приносит минимальный вред.

...