📚 execpool - Awesome Go Library for Goroutines

Go Gopher mascot for execpool

A pool built around exec.Cmd that spins up a given number of processes in advance and attaches stdin and stdout to them when needed. Very similar to FastCGI or Apache Prefork MPM but works for any command.

🏷️ Goroutines
📂 Tools for managing and working with Goroutines.
22 stars
View on GitHub 🔗

Detailed Description of execpool

ExecPool

License Build Coverage Status Go Report Card GoDoc Release Awesome

Why? Sometimes when you implement Go services you have to integrate with third party command line tools. You can do it by simply using exec.Command but the problem with this approach is that your service has to wait while a new process is being loaded into the memory and started. Sometimes this can drastically increase the latency of your service. ExecPool works similarly to FastCGI but it can wrap any regular process. It spins up a given number of processes in advance and when it's time to handle a request from the user your service just attaches stdin to an existing process from the pool. Basically the execpool helps you trade memory for latency.

Usage

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os/exec"
	"strings"

	"github.com/hexdigest/execpool"
)

func main() {
	cmd := exec.Command("grep", "none")

	//spin up 100 processes of grep
	pool, err := execpool.New(cmd, 100)

	rc := pool.Exec(strings.NewReader("this makes sense\nthis is nonesense"))
	b, err := ioutil.ReadAll(rc)
	if err != nil {
		log.Fatalf("failed to read from stdout: %v", err)
	}

	// this is nonesense
	fmt.Println(string(b))
}

Benchmark

This benchmark compares "standard" approach with exec.Command and execpool.Pool by running grep 100 times. For heavier processes you can expect a bigger difference.

make benchmark
goos: darwin
goarch: amd64
pkg: github.com/hexdigest/execpool
cpu: Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
BenchmarkNew-8               100            941753 ns/op
BenchmarkCmd-8               100           2386990 ns/op