Может ли Go порождать и взаимодействовать с внешними процессами без запуска одного OS-потока на каждый внешний процесс?
Укороченная версия:
Возможно ли в Голанге порождать ряд внешних процессов (команд оболочки)в параллелитак, что он не запускается одинпоток операционной системы на внешний процесс ... и все еще быть в состоянии получить его вывод, когда он будет завершен?
Более длинная версия:
В Elixir, если вы используете порты, вы можете создавать тысячи внешних процессов, не увеличивая количество потоков в виртуальной машине Erlang.
Например. следующий фрагмент кода, который запускает 2500 внешнихsleep
процессы, управляется всего 20потоки операционной системы под Erlang VM:
defmodule Exmultiproc do
for _ <- 1..2500 do
cmd = "sleep 3600"
IO.puts "Starting another process ..."
Port.open({:spawn, cmd}, [:exit_status, :stderr_to_stdout])
end
System.cmd("sleep", ["3600"])
end
(При условии, что вы установилиulimit -n
на большое число, такое как 10000)
С другой стороны, следующий код в Go, который должен делать то же самое - запуск 2500 внешнихsleep
процессы - тоже запускается 2500потоки операционной системы, Так что, очевидно, начинается одинпоток операционной системы per (blocking?) системный вызов (чтобы не блокировать весь процессор или что-то подобное, если я правильно понимаю):
package main
import (
"fmt"
"os/exec"
"sync"
)
func main() {
wg := new(sync.WaitGroup)
for i := 0; i < 2500; i++ {
wg.Add(1)
go func(i int) {
fmt.Println("Starting sleep ", i, "...")
cmd := exec.Command("sleep", "3600")
_, err := cmd.Output()
if err != nil {
panic(err)
}
fmt.Println("Finishing sleep ", i, "...")
wg.Done()
}(i)
}
fmt.Println("Waiting for WaitGroup ...")
wg.Wait()
fmt.Println("WaitGroup finished!")
}
Таким образом, мне было интересно, есть ли способ написать код Go, чтобы он делал то же самое, что и код Elixir, а не открывал егопоток операционной системы за внешний процесс?
Я в основном ищу способ управления как минимум несколькими тысячами внешних долгосрочных (до 10 дней) процессов, которые бы вызывали как можно меньше проблем с любыми виртуальными или физическими ограничениями в операционной системе.
(Извините за любые ошибки в кодах, так как я новичок в Elixir и совершенно новый для Go. Мне не терпится узнать о любых ошибках, которые я делаю.)
РЕДАКТИРОВАТЬ: разъяснил о требовании для запуска долгосрочных процессов параллельно.