Skip to content

Instantly share code, notes, and snippets.

@CullenShane
Last active February 5, 2018 17:55
Show Gist options
  • Save CullenShane/1dafa928a80dfeea81d4a711fe484549 to your computer and use it in GitHub Desktop.
Save CullenShane/1dafa928a80dfeea81d4a711fe484549 to your computer and use it in GitHub Desktop.
High Throughput Go Wakka generator

High Throughput Wakka Generator

This is a simple program which is setup to serve as many Wakkas as possible.

Client

If you run the client, you can tune the number of goroutine on the client to make it go faster. If you run out of open files, run ulimit -n to find out your current number of openable files, and then double it with ulimit -n <n>. Repeat this until you stop running out of files. If you change the program so that the client closes the connection, you run out of sockets instead, because the sockets stick around in TIME_WAIT state instead of being closed instantly. If you are at a loss for sockets, ensure your clients aren't closing the connection first.

Server

The server spawns a goroutine for every connection it gets, writes "Wakka Wakka!" and closes the connection. Another goroutine prints how many people have gotten two Wakkas every two seconds, and finally, a 3rd goroutine prints the final count before exiting.

How to run

  1. Download Gist
  2. go run server.go
  3. go run client.go
  4. ulimit -n 4196
  5. go run client.go

The ulimit change is limited to your current terminal and will not bring down your system. Once you close that terminal it will go back to the original limit of (usually) 1024.

package main
import "fmt"
import "net"
import "sync/atomic"
import "bufio"
import "time"
var ops uint64
func main() {
print("Connecting")
for i := 0; i < 20; i++ {
print(".")
go func() {
print(".")
var conn net.Conn
var err error
//var status string
for {
err = nil
atomic.AddUint64(&ops, 1)
conn, err = net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Printf(err.Error())
time.Sleep(time.Millisecond * 499)
continue
}
_, _ = bufio.NewReader(conn).ReadString('\n')
conn = nil
}
}()
}
print(".")
time.Sleep(time.Second * 10)
print("operations: ", ops)
}
package main
import "fmt"
import "net"
import "sync/atomic"
import "os"
import "os/signal"
import "syscall"
import "time"
var ops uint64
func main() {
print("Opening :8080.")
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigs
fmt.Println()
fmt.Printf("Did it %v times. <3", ops)
os.Exit(0)
}()
go func() {
for {
time.Sleep(time.Second * 2)
fmt.Printf("%v times so far\n", ops)
}
}()
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Printf(err.Error())
}
print(".")
for {
conn, err := ln.Accept()
if err != nil {
fmt.Printf("err Accept", err.Error())
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
conn.Write([]byte("Wakka wakka!\n"))
atomic.AddUint64(&ops, 1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment