• Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    calculator212, попробовал, ничего не изменилось. Размер map`ы все ширится.
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    calculator212, программа использует одновременно не более 200 потоков. Тайм-аут у меня 200 миллисекунд. Итого скорость которую я замерял где-то 2 тысячи адресов в секунду(у меня есть функция которая измеряет скорость).
    Касаемо новых параметров, опробую сразу как буду у машины
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    calculator212,
    > в целом может быть проблема, если используется одна из старых версий го, но баг с этой штукой пофиксили давно

    В целом действительно похоже на мой случай, но у меня практически актуальная версия Golang.

    └[~/Develop/GO/Gnet-Scanner]> go version               
    go version go1.22.2 linux/amd64
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    calculator212,
    > первое что в глаза бросается, это то что вы неправильно обрабатываете ошибки
    Не думаю, Body.Close() понадобится только в том случае если соединение было успешным. Как и сказано таких соединений дай бог будет 5% от общей массы. Потому поначалу когда их вообще нет (первые пол часа перебора наверное) то и забивать такие соединения память не могут. И Body.Close() в таком случае вообще не отрабатывает ни разу.

    > вам стоит почитать про http.Transport и некоторые особенности клиентов
    Собственно я читал и изучал код библиотеки, но пока не понял как правильно совершать запрос, что бы запросы в никуда очищались. Потому я и здесь, хочу узнать как. Знай я как это сделать не задавал бы вопрос.

    > Сколько занимает эта мапа памяти и как проводилась проверка?
    Память занимает в зависимости от времени работы программы (это же утечка). Расход замерялся профайлером.

    1. Потребление в диспетчере задач - 386 МиБ
    662b54267d7f1012724568.jpeg

    2. Вывод top из pprof
    Showing top 10 nodes out of 33
          flat  flat%   sum%        cum   cum%
       69.51MB 43.29% 43.29%   131.07MB 81.63%  net/http.(*Transport).getConn
       60.56MB 37.72% 81.00%    61.06MB 38.03%  net/http.(*Transport).queueForIdleConn
        7.50MB  4.67% 85.68%     7.50MB  4.67%  net.(*Resolver).internetAddrList.func1
        7.50MB  4.67% 90.35%   143.07MB 89.10%  main.scan
           6MB  3.74% 94.08%        7MB  4.36%  net.(*sysDialer).dialSingle
           4MB  2.49% 96.57%        4MB  2.49%  net.JoinHostPort
           2MB  1.25% 97.82%        2MB  1.25%  net.IPv4
        0.50MB  0.31% 98.13%       17MB 10.59%  net/http.(*Transport).dialConn
             0     0% 98.13%   143.07MB 89.10%  main.scanChunk
             0     0% 98.13%    16.50MB 10.28%  net.(*Dialer).DialContext

    3. Вот что профайлер думает про функцию queueForIdleConn
    .          .   1100:	// Register to receive next connection that becomes idle.
             .          .   1101:	if t.idleConnWait == nil {
             .          .   1102:		t.idleConnWait = make(map[connectMethodKey]wantConnQueue)
             .          .   1103:	}
             .          .   1104:	q := t.idleConnWait[w.key]
             .          .   1105:	q.cleanFront()
             .        6MB   1106:	q.pushBack(w)
      380.89MB   380.89MB   1107:	t.idleConnWait[w.key] = q
             .          .   1108:	return false
             .          .   1109:}
             .          .   1110:
             .          .   1111:// removeIdleConn marks pconn as dead.
             .          .   1112:func (t *Transport) removeIdleConn(pconn *persistConn) bool {

    4. Деббагер GoLand показывает что эта map`а имеет в себе аж 347 956 элементов.
    662b558a789b7937714694.jpeg
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    tr := &http.Transport{
    	MaxIdleConns:       10,
    	IdleConnTimeout:    30 * time.Second,
    	DisableCompression: true,
    }

    Уже пытался, не сработало и в этот раз.

    > В целом есть вероятность, что "утечка" тут
    Вероятность этого 100% т.к я специально лазил проверять где забивается. Вопрос мой в том как очищать этот массив или ещё лучше как сделать так что бы библиотека net/http сама за собой правильно подчищала.
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    Виктор Кожухарь,
    > Может быть, мне ещё и проект за вас дописать? ))
    Было бы неплохо, но пока вы не справляетесь даже с собственными мыслями в голове потому не могу его вам доверить.
    > Понятно, что ошибки надо обрабатывать
    Ну тогда прежде чем закомментировать мой if который как раз обрабатывает ошибку(её возвращает в другую часть кода) вам стоило лучше подумать.
    Да и в конечном итоге есть главный вопрос. Как все это должно помочь? Потому что resp.Body.close() работает только на удавшиеся подключения (коих 5% от общей массы соединений). А у меня проблема в том что куча неудавшихся соединений копится в очереди и потому занимает память.
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    Это решение не сработает сразу по нескольким причинам:
    1. Когда вы убрали проверку на то появилась ли ошибка или нет, вы будете пытаться закрыть nil (чему будет равен resp при неудачной попытки соединения) что будет приводить к ошибкам.
    2. Из выше сказанного выходит что это помогает от засилья удавшихся, но простаивающих соединений. У меня же все наоборот, куча неудавшихся соединений которые библиотека net/http зачем то ждёт и хранит в памяти
    Написано
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    @videxerion Автор вопроса
    Евгений Мамонов,
    > есть сомнения, что эта map'а, занимает много памяти.
    Собственно, именно на это я и жалуюсь.
    > Также нужно понять сколько горутин запускается?
    Одновременно работает не более 200 горутин которые точно завершаются. Проблема не в количестве горутин, а то что эта мапа которая представляет собой очередь, раздувается (вполне себе может и 100 тыс. элементов содержать и 300 тыс).
    Написано
  • Как организовать структуру проекта с несколькими модулями Golang?

    @videxerion Автор вопроса
    Виктор Кожухарь, спасибо ещё раз! Вечером отвечу или поставлю метку решения
    Написано
  • Как организовать структуру проекта с несколькими модулями Golang?

    @videxerion Автор вопроса
    Виктор Кожухарь, спасибо! Я обязательно попробую как приду домой. Но прямо сейчас есть вопрос. Мне не совсем понятен откуда взялся путь "test/pkg/c-library". Откуда test? Как получается файл который находится в соседней директории без относительного пути? Был бы признателен за пояснения
    Написано
  • Как организовать структуру проекта с несколькими модулями Golang?

    @videxerion Автор вопроса
    Не подскажите, а как импортировать функцию из clibrary.go функцию например в controller? Что нужно прописывать?
    Написано