Created
May 26, 2015 19:05
-
-
Save redbo/72af3537b82f73933636 to your computer and use it in GitHub Desktop.
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 ( | |
"bytes" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"net" | |
"net/http" | |
"net/http/httptest" | |
"net/url" | |
"os" | |
"os/exec" | |
"path/filepath" | |
"strconv" | |
"sync" | |
"sync/atomic" | |
"time" | |
"github.com/openstack/swift/go/hummingbird" | |
"github.com/openstack/swift/go/objectserver" | |
) | |
const concurrency = 4 | |
type TestServer struct { | |
*httptest.Server | |
host string | |
port int | |
root string | |
} | |
func (t *TestServer) Close() { | |
t.Server.Close() | |
} | |
func makeObjectServer(driveRoot string) (*TestServer, error) { | |
conf, err := ioutil.TempFile("", "") | |
if err != nil { | |
return nil, err | |
} | |
defer conf.Close() | |
defer os.RemoveAll(conf.Name()) | |
conf.WriteString("[app:object-server]\n") | |
fmt.Fprintf(conf, "devices=%s\n", driveRoot) | |
fmt.Fprintf(conf, "mount_check=false\n") | |
fmt.Fprintf(conf, "log_facility = LOG_LOCAL2\nrecon_cache_path = /var/cache/swift\neventlet_debug = true\nlog_udp_host = 127.0.0.1\n log_udp_port = 514\n") | |
if err := conf.Close(); err != nil { | |
return nil, err | |
} | |
_, _, handler, _, _ := objectserver.GetServer(conf.Name()) | |
ts := httptest.NewServer(handler) | |
u, err := url.Parse(ts.URL) | |
if err != nil { | |
return nil, err | |
} | |
host, ports, err := net.SplitHostPort(u.Host) | |
if err != nil { | |
return nil, err | |
} | |
port, err := strconv.Atoi(ports) | |
if err != nil { | |
return nil, err | |
} | |
return &TestServer{Server: ts, host: host, port: port, root: driveRoot}, nil | |
} | |
func main() { | |
drivePath := "/srv/node/sda" | |
drive := filepath.Base(drivePath) | |
driveRoot := filepath.Dir(drivePath) | |
var id int64 = 0 | |
ts, err := makeObjectServer(driveRoot) | |
if err != nil { | |
panic(fmt.Sprintf("Failed to make object server: %v", err)) | |
} | |
defer ts.Close() | |
/* PUTs */ | |
exec.Command("sudo", "sh", "-c", "echo 3 > /proc/sys/vm/drop_caches").Run() | |
fileBuffer := make([]byte, 1024*1024) | |
contentLength := fmt.Sprintf("%d", len(fileBuffer)) | |
jobch := make(chan int64) | |
wg := sync.WaitGroup{} | |
putFile := func() { | |
wg.Add(1) | |
for thisId := range jobch { | |
timestamp := hummingbird.GetTimestamp() | |
req, err := http.NewRequest("PUT", fmt.Sprintf("http://%s:%d/%s/%d/a/c/o%d", ts.host, ts.port, drive, thisId%1000, thisId), bytes.NewBuffer(fileBuffer)) | |
if err != nil { | |
} | |
req.Header.Set("Content-Type", "application/octet-stream") | |
req.Header.Set("Content-Length", contentLength) | |
req.Header.Set("X-Timestamp", timestamp) | |
resp, err := http.DefaultClient.Do(req) | |
if err != nil { | |
resp.Body.Close() | |
} | |
} | |
wg.Done() | |
} | |
for i := 0; i < concurrency; i++ { | |
go putFile() | |
} | |
start := time.Now() | |
for atomic.LoadInt64(&id) < 500000 { // ~1 TB | |
jobch <- atomic.AddInt64(&id, 1) | |
} | |
close(jobch) | |
wg.Wait() | |
fmt.Println("PUT", id, "objects in", time.Since(start).Seconds()) | |
/* GETs */ | |
exec.Command("sudo", "sh", "-c", "echo 3 > /proc/sys/vm/drop_caches").Run() | |
jobch = make(chan int64) | |
getFile := func() { | |
wg.Add(1) | |
for thisId := range jobch { | |
req, err := http.NewRequest("GET", fmt.Sprintf("http://%s:%d/%s/%d/a/c/o%d", ts.host, ts.port, drive, thisId%1000, thisId), nil) | |
if err != nil { | |
} | |
resp, err := http.DefaultClient.Do(req) | |
if err != nil { | |
} | |
io.Copy(ioutil.Discard, resp.Body) | |
resp.Body.Close() | |
} | |
wg.Done() | |
} | |
for i := 0; i < concurrency; i++ { | |
go getFile() | |
} | |
start = time.Now() | |
for i := int64(0); i < id; i++ { | |
jobch <- i | |
} | |
close(jobch) | |
wg.Wait() | |
fmt.Println("GET", id, "objects in", time.Since(start).Seconds()) | |
/* Filesystem Walk 1 */ | |
exec.Command("sudo", "sh", "-c", "echo 3 > /proc/sys/vm/drop_caches").Run() | |
var walk1 func(string) | |
walk1 = func(path string) { | |
stat, err := os.Stat(path) | |
if err != nil { | |
return | |
} | |
if !stat.Mode().IsDir() { | |
return | |
} | |
files, err := hummingbird.ReadDirNames(path) | |
if err != nil { | |
return | |
} | |
for _, file := range files { | |
walk1(filepath.Join(path, file)) | |
} | |
} | |
start = time.Now() | |
walk1(drivePath) | |
fmt.Println("Filesystem Walk 1", time.Since(start).Seconds()) | |
/* Filesystem Walk 2 */ | |
exec.Command("sudo", "sh", "-c", "echo 3 > /proc/sys/vm/drop_caches").Run() | |
var walk2 func(string) | |
walk2 = func(path string) { | |
files, err := ioutil.ReadDir(path) | |
if err != nil { | |
return | |
} | |
for _, file := range files { | |
if file.Mode().IsDir() { | |
walk2(filepath.Join(path, file.Name())) | |
} | |
} | |
} | |
start = time.Now() | |
walk2(drivePath) | |
fmt.Println("Filesystem Walk 2", time.Since(start).Seconds()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment