Почему использование потоков увеличивается с сетевым вводом-выводом в golang? - PullRequest
0 голосов
/ 31 декабря 2018

Я создал тестовую программу, чтобы проверить мое понимание того, как Golang обрабатывает сетевой ввод-вывод.Приведенная ниже программа создает 1000 подпрограмм, и в каждой она отправляет запрос сетевого ввода-вывода.

Когда я пытался отслеживать количество используемых потоков, он достигает 400 потоков.Я использовал команду top для мониторинга. Насколько я понимаю, для сети io Golang использует netpoll (то есть async io).

Пожалуйста, исправьте меня, если мое понимание неверно.

ОС: macos high sierra

Версия Go: go1.11.2 darwin / amd64

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "sync"
    "time"
)

func main() {
    timeout := time.Duration(5 * time.Second)
    client := http.Client{
        Timeout: timeout,
    }
    var wg sync.WaitGroup

    start := time.Now()
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go callAPI(&wg, client)
    }
    wg.Wait()
    log.Println(time.Since(start))
}

func callAPI(wg *sync.WaitGroup, client http.Client) {
    defer wg.Done()
    url := `JSON-API-URL-OF-YOUR-CHOICE` // Please enter a valid json api url.
    request, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatalln(err)
    }

    resp, err := client.Do(request)
    if err != nil {
        log.Fatalln(err)
    }

    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    defer resp.Body.Close()

    log.Println(result)
}

1 Ответ

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

Когда поток заблокирован при системном вызове ввода-вывода, Go может создать новый поток, чтобы другие программы продолжали работать.Это имеет хорошее объяснение: https://povilasv.me/go-scheduler/:

Интересные вещи случаются, когда ваша программа выполняет блокирующий системный вызов.Блокирующий системный вызов будет перехвачен, если есть G для запуска, среда выполнения отсоединит поток от P и создаст новый поток ОС (если свободный поток не существует) для обслуживания этого процессора.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...