Skip to content

Instantly share code, notes, and snippets.

@nono
Created June 22, 2011 09:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nono/1039785 to your computer and use it in GitHub Desktop.
Save nono/1039785 to your computer and use it in GitHub Desktop.
Long polling with golang... only 282 clients?
% 8g -V
8g version weekly.2011-06-16 8787+
% make && ./long_polling
8g -o _go_.8 long_polling.go
8l -o long_polling _go_.8
(On a second shell: % ab -c 1000 -n 1000 http://localhost:8000/)
New client: 1
New client: 2
New client: 3
New client: 4
[...]
New client: 281
New client: 282
% ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nono 23835 0.6 0.4 3119508 9008 pts/2 Sl+ 11:19 0:00 ./long_polling
package main
import (
"container/vector"
"fmt"
"http"
"io"
"io/ioutil"
"log"
"os"
"os/signal"
"time"
)
func ChannelsKeeper(clients chan chan string, signals chan bool) {
channels := new(vector.Vector)
counter := 0
go func() {
for {
select {
case <-signals:
msg := fmt.Sprintf("%d\n", counter)
for channels.Len() > 0 {
channel := channels.Pop().(chan string)
channel <- msg
close(channel)
}
counter++
case c := <-clients:
channels.Push(c)
fmt.Printf("New client: %d\n", channels.Len())
}
}
}()
}
func InstallSignalHandlers(signals chan bool) {
go func() {
for s := range signal.Incoming {
if s == os.SIGINT {
fmt.Printf("\nCtrl-C signalled\n")
os.Exit(0)
} else if s == os.SIGUSR1 {
signals <- true
}
}
}()
}
func CreatePidfile() {
pid := []byte(fmt.Sprintf("%d", os.Getpid()))
ioutil.WriteFile("long_polling.pid", pid, 0755)
}
func MakeLPHandler(clients chan chan string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
timeout := make(chan bool, 1)
message := make(chan string, 1)
clients <- message
go func () {
time.Sleep(60e9)
timeout <- true
close(timeout)
}()
select {
case <-timeout:
io.WriteString(w, "Timeout!\n")
case msg := <-message:
io.WriteString(w, msg)
}
}
}
func CreateHttpServer(clients chan chan string) {
http.HandleFunc("/", MakeLPHandler(clients))
err := http.ListenAndServe(":8000", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err.String())
}
}
func main() {
clients := make(chan chan string, 1)
signals := make(chan bool, 1)
CreatePidfile()
ChannelsKeeper(clients, signals)
InstallSignalHandlers(signals)
CreateHttpServer(clients)
}
include $(GOROOT)/src/Make.inc
TARG=long_polling
GOFILES=long_polling.go
include $(GOROOT)/src/Make.cmd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment