-
-
Save y1r/dc9ea1d36628c043c5fa7850397f1ff9 to your computer and use it in GitHub Desktop.
sendfile(2)をGoから使う
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
FILENAME=test.img | |
function run_experiment() { | |
listener="$1" | |
handler="$2" | |
./sendfile-benchmark -filepath $FILENAME -listener "$listener" -handler "$handler" & | |
pid=$! | |
sleep 3 | |
LOGNAME="${listener}-${handler}.log" | |
rm -rf "$LOGNAME" | |
for (( i = 0; i < 10; i++ )); do | |
if [[ $listener = "unix" ]]; then | |
curl --unix-socket ./sock localhost/ -o /dev/null -w "%{speed_download}\n" | tee -a "$LOGNAME" | |
else | |
curl localhost:12345 -o /dev/null -w "%{speed_download}\n" | tee -a "$LOGNAME" | |
fi | |
done | |
kill -SIGTERM $pid | |
wait | |
} | |
FILESIZE=$((1024 * 1024 * 1024)) | |
FILESIZE_IN_MB=$((FILESIZE / 1024 / 1024)) | |
dd if=/dev/zero of=$FILENAME bs=1M count=$FILESIZE_IN_MB | |
go build . | |
for listener in "tcp" "unix"; do | |
run_experiment "$listener" "serve-content" | |
for length in "with" "without"; do | |
for abstraction in "with" "without"; do | |
run_experiment "$listener" "${length}-length-${abstraction}-abstraction" | |
done | |
done | |
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"io" | |
"log" | |
"net" | |
"net/http" | |
"os" | |
"strconv" | |
"time" | |
) | |
func main() { | |
filepath := flag.String("filepath", "", "Specify a path to file served") | |
listener := flag.String("listener", "", "Specify a method to listen (tcp, unix)") | |
handler := flag.String("handler", "", "Specify a method to handle (serve-content, with/without-length-with/without-length") | |
flag.Parse() | |
if *filepath == "" { | |
log.Fatal("Please specify filepath") | |
} | |
var listenerObj net.Listener | |
if *listener == "tcp" { | |
listenerObj = tcpListener() | |
} else if *listener == "unix" { | |
listenerObj = unixListener() | |
} else { | |
log.Fatalf("Not supported listener: %s\n", *listener) | |
} | |
var handlerObj http.Handler | |
if *handler == "serve-content" { | |
handlerObj = serveContentHandler(*filepath) | |
} else if *handler == "with-length-with-abstraction" { | |
handlerObj = serveImpl(*filepath, true, true) | |
} else if *handler == "with-length-without-abstraction" { | |
handlerObj = serveImpl(*filepath, true, false) | |
} else if *handler == "without-length-with-abstraction" { | |
handlerObj = serveImpl(*filepath, false, true) | |
} else if *handler == "without-length-without-abstraction" { | |
handlerObj = serveImpl(*filepath, false, false) | |
} else { | |
log.Fatalf("Not supported handler: %s\n", *handler) | |
} | |
http.Serve(listenerObj, handlerObj) | |
} | |
func tcpListener() net.Listener { | |
listener, err := net.Listen("tcp", "localhost:12345") | |
if err != nil { | |
log.Fatalf("error on tcpListener: %v\n", err) | |
} | |
return listener | |
} | |
func unixListener() net.Listener { | |
os.Remove("./sock") | |
socket, _ := net.Listen("unix", "./sock") | |
return socket | |
} | |
func serveContentHandler(file string) http.Handler { | |
mux := http.NewServeMux() | |
mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { | |
http.ServeFile(writer, request, file) | |
}) | |
return mux | |
} | |
func serveImpl(file string, withLength bool, withAbstraction bool) http.Handler { | |
mux := http.NewServeMux() | |
mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { | |
fileObj, err := os.Open(file) | |
if err != nil { | |
log.Fatalf("File %s does not exist", file) | |
} | |
defer fileObj.Close() | |
if withLength { | |
fileinfo, err := fileObj.Stat() | |
if err != nil { | |
log.Fatalf("Failed to get %s info", file) | |
} | |
writer.Header().Set("Content-Length", strconv.FormatInt(fileinfo.Size(), 10)) | |
} | |
var w io.Writer | |
if withAbstraction { | |
w = abstractedWriter{underlying: writer} | |
} else { | |
w = writer | |
} | |
start := time.Now() | |
written, _ := io.Copy(w, fileObj) | |
elapsed := time.Now().Sub(start) | |
log.Printf("%f MB/s\n", float64(written)/1024/1024/elapsed.Seconds()) | |
}) | |
return mux | |
} | |
type abstractedWriter struct { | |
underlying io.Writer | |
} | |
func (w abstractedWriter) Write(p []byte) (n int, err error) { | |
return w.underlying.Write(p) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment