2017-02-20 50 views
2

Я использую goroutines в пакете, где есть tcp-сервер. Ответ большую часть времени очень тяжелый, но когда процедуры заканчиваются, он не очищается от памяти.FreeOSMemory() in production

func Handle() { 
    service := ":7777" 
    tcpAddr, err := net.ResolveTCPAddr("tcp4", service) 
    checkError(err) 
    listener, err := net.ListenTCP("tcp", tcpAddr) 
    checkError(err) 
    defer listener.Close() 

    for { 
     conn, err := listener.Accept() 
     checkError(err) 
     go handleRequest(conn, db) 

    } 
} 

func handleRequest(conn net.Conn, db *sql.DB) { 
    message := make([]byte, 0, 4096) 
    tmp := make([]byte, 256) 
    n, err := conn.Read(tmp) 
    if err != nil { 
     if err != io.EOF { 
      fmt.Println("read error:", err) 
     } 
    } 
    message = append(message, tmp[:n]...) 
    fmt.Println("Message Received:", string(message)) 
    // do something to get resp 
    conn.Write(append(resp, []byte("\n")...)) 
    conn.Close() 
    debug.FreeOSMemory() 
    return 
} 

Так что в этом случае реакция является большим, и goroutine с использованием 10% памяти, это нормально, потому что я получаю 170.000 пользователей из базы данных и анализировать результат JSON. Но когда handleRequest и все еще находится в памяти, если я не использую debug.FreeOsMemory(). У меня есть сомнения, что это хороший способ сделать это, потому что он находится в debug pacakge, поэтому мой вопрос - это хороший способ освободить память, что используют goroutines? Я тестировал его, чтобы он не влиял на систему и не работал очень хорошо. Если нет, что хорошего? Я не могу дождаться GC, чтобы понять это ?! Я читал this, и именно поэтому я начал его использовать, в первом ответе есть последнее предложение.

+0

«это хороший способ, чтобы освободить память, какие goroutines используют». Ответ: Нет. Держитесь подальше от таких хаков, тем более что они не помогают. – Volker

+0

@ Волькер Во-первых, почему я получил голос? Во-вторых, что хорошего тогда? – PumpkinSeed

ответ

4

Среда выполнения Go не освобождает свободную память обратно в ОС «немедленно», это было бы неэффективно. Узнайте больше об этом здесь: Golang - Cannot free memory once occupied by bytes.Buffer.

Вы должны разрешить выполнение Run runtime. Если ваше приложение нестабильно, не вызывая debug.FreeOsMemory(), есть большие проблемы, которые вам не следует скрыть, даже если это «похоже» помогает. Это может даже ухудшить ситуацию, так как если для выполнения запроса требуется большой объем памяти (который должным образом освобожден GC, когда он сделан с запросом), вызов FreeOsMemory() просто вернет его в операционную систему, на которую должна будет потребоваться среда выполнения for/allocate снова при обслуживании другого запроса. Если вы не передали его обратно в ОС, он будет доступен для следующего запроса ...

Попробуйте уменьшить потребность в памяти обработчика запроса. Если это невозможно (сомнительно), то ограничьте количество запросов, требующих большой памяти, которые могут быть одновременно отправлены.

Смотрите этот вопрос + ответ, как это сделать: Process Management for the Go Webserver

также: Is this an idiomatic worker thread pool in Go?

+0

Спасибо, сервис стабильный без FreeOSMemory, я просто не знаю, это хороший способ или нет. Теперь я так понимаю. – PumpkinSeed

3

GO lang очистить всю память, которая не используется, но не является промежуточной. Вы можете прочитать другой вопрос:

Golang - Cannot free memory once occupied by bytes.Buffer

+0

Да, я прочитал это, поэтому я начал использовать этот пакет, но у меня возникли сомнения из-за основного имени пакета, это хороший способ? – PumpkinSeed

+0

Это хороший способ, если вам нужна память сразу, но память сброса силы опасна на всех языках программирования. –