@lookingfor2

Что будет при увеличении вместимости канала?

Интересует несколько вопросов.
1. runtime.Gosched() - есть ли практическое применение этого метода?
2. runtime.GOMAXPROCS(1) - есть ли практическое применение этого метода?
На форумах читал, что использование этих методов, признак плохой архитектуры, в теории для чего они могут применяться?
Я вижу что меняется поведение горутин, но не могу найти логики в этом.
3. worketInput := make(chan string, 2) - что будет при увеличении канала?
package main

import (
	"fmt"
	"log"
	"strings"
	"time"
)

const goroutinesNum = 5

func startWorker(workerNum int, in <-chan string) {
	// обрабатываем канал горутинами
	for input := range in {
		time.Sleep(time.Second)
		fmt.Printf(formatWork(workerNum, input))
		//runtime.Gosched()  // <- ЭТО
	}
	printFinishWork(workerNum)
}

func main() {
	//runtime.GOMAXPROCS(1)               // // <- ЭТО с 0 (все доступные) и 1
	worketInput := make(chan string, 2) // <- Что будет при увеличении канала
	// Запускаем горутины, которые начинают слушать канал worketInput
	for i := 0; i < goroutinesNum; i++ {
		log.Println("FOR GO")
		go startWorker(i, worketInput)
	}

	// пользователи
	log.Println("START")
	users := []string{"Дмитрий", "Петр", "Василий",
		"Сергей", "Иван", "Влад",
	}

	// В канал складываем пользователей
	for _, userName := range users {
		worketInput <- userName
	}

	close(worketInput) // <- закрываем

	fmt.Scanln()
}

func formatWork(in int, input string) string {
	return fmt.Sprintln(strings.Repeat("  ", in), "█",
		strings.Repeat("  ", goroutinesNum-in),
		"th", in,
		"recieved", input)
}

func printFinishWork(in int) {
	fmt.Println(strings.Repeat("  ", in), "█",
		strings.Repeat("  ", goroutinesNum-in),
		"===", in,
		"finished")
}
  • Вопрос задан
  • 215 просмотров
Решения вопроса 1
@deliro
1. Нет, либо нет в 99.9999% случаев
2. Да, чтобы ограничить то, на скольких OS тредах может расположиться рантайм. Это прямо влияет на CPU-bound задачи и почти не влияет на IO-bound. Например, у тебя есть функция, которая перемножает матрицы. В канал поступают матрицы, есть 10 горутин, которые читают оттуда и умножают матрицы. Очевидно, что если GOMAXPROCS будет == 1, то все эти горутины будут жить на одном треде и будут "мешать" друг другу, задействуя не более одного ядра процессора. Если GOMAXPROCS будет 10, то каждая горутина может расположиться в отдельном ОС треде и считать себе там матрицы на "собственном" ядре.
3. Увеличится канал (sic!). Канал — это очередь. Канал без буфера — это "очередь", в которую можно добавить элемент только если с другой стороны этот канал кто-то пытается прочитать. Если такого нет — горутина будет ждать, пока этот канал кто-то захочет прочитать и наоборот, если кто-то читает канал, а с другого конца никто туда не пишет, то горутина будет ждать до тех пор, пока в канал кто-то не захочет записать. Если в канале есть буфер, то это уже становится полноценной очередью. Есть N слотов, если кто-то пришёл записать в канал, канал никем не слушается и там есть хотя бы один свободный слот — этот "кто-то" запишет в канал и пойдёт по своим делам и только если в буфере нет свободных слотов, то этот "кто-то" будет ждать, пока слот освободится. И наоборот, если кто-то слушает канал и в буфере канала уже что-то есть, то он сразу забирает первый на очереди элемент и уходит. Обычно это делают, чтобы сгладить нагрузку. Например, у тебя есть парсеры, которые что-то парсят, чтобы потом записать на диск. Но диск — штука непредсказуемая, может записать за 1мс, а может тупить 20мс. Довольно странно, если парсер будет ждать диск эти 20мс, хотя у него есть работа, которую он может выполнять прямо сейчас. Для этого можно создать буфер, куда парсер будет кидать данные СРАЗУ, а горутина, которая пишет на диск, заберёт их "когда-нибудь потом", когда диск перестанет тупить.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы