maengsanha/instacrawler

socket: too many open files

maengsanha opened this issue · 0 comments

package main

import (
	"fmt"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
)

// check NOFILE Limit
// ulimit -Hn
// ulimit -Sn

// ulimit -n count
// or
// sudo vi /etc/security/limits.conf (in root account)
// * hard nofile 500000
// * soft nofile 500000
// root hard nofile 500000
// root soft nofile 500000

var messages, codes sync.Map

func main() {
	url := fmt.Sprintf("http://%s", os.Args[1])
	count, _ := strconv.Atoi(os.Args[2])

        // since go 1.5, default GOMAXPROCS equals to NumCPU
	// runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Printf("using %d cores\n", runtime.GOMAXPROCS(0))
	fmt.Printf("%s\n\n", strings.Repeat("=", 50))

	var nReq int
	for nReq = 1; nReq <= count; nReq <<= 1 {
		fmt.Printf("sending concurrent requests %d times\n", nReq)
		nFail := stress(url, nReq)
		fmt.Printf("failure rate: %f%% (%d/%d)\n\n", float64(nFail)/float64(nReq), nFail, nReq)
	}
	if nReq != count << 1 {
		fmt.Printf("sending concurrent requests %d times\n", count)
		nFail := stress(url, count)
		fmt.Printf("failure rate: %f%% (%d/%d)\n\n", float64(nFail)/float64(count), nFail, count)
	}
	fmt.Printf("%s\n\n", strings.Repeat("=", 50))

	fmt.Println("error messages\n")
	messages.Range(func(k, v interface{}) bool {
		fmt.Println(k)
		return true
	})
	fmt.Printf("\n%s\n\n", strings.Repeat("=", 50))
	fmt.Println("error codes\n")
	codes.Range(func(k, v interface{}) bool {
		fmt.Println(k)
		return true
	})
}

func stress(url string, nReq int) (nFail int64) {
	var syncer sync.WaitGroup
	syncer.Add(nReq)

	for i := 0; i < nReq; i++ {
		go func() {
			defer syncer.Done()
			resp, err := http.Get(url)
			if err != nil {
				atomic.AddInt64(&nFail, 1)
				messages.Store(err, struct{}{})
				return
			}
        defer resp.Body.Close() /* mistake! should close the response body */
			if resp.StatusCode != http.StatusOK {
				atomic.AddInt64(&nFail, 1)
				codes.Store(resp.StatusCode, struct{}{})
				return
			}
		}()
	}
	syncer.Wait()
	return
}