Merge "namespace: parallelize Glob."
diff --git a/lib/exec/child.go b/lib/exec/child.go
index 80ebfd2..7158ef7 100644
--- a/lib/exec/child.go
+++ b/lib/exec/child.go
@@ -5,6 +5,7 @@
 	"errors"
 	"io"
 	"os"
+	"strconv"
 	"sync"
 )
 
@@ -62,7 +63,7 @@
 
 // SetReady writes a 'ready' status to its parent.
 func (c *ChildHandle) SetReady() error {
-	_, err := c.statusPipe.Write([]byte(readyStatus))
+	_, err := c.statusPipe.Write([]byte(readyStatus + strconv.Itoa(os.Getpid())))
 	c.statusPipe.Close()
 	return err
 }
diff --git a/lib/exec/parent.go b/lib/exec/parent.go
index 612020f..e4d40db 100644
--- a/lib/exec/parent.go
+++ b/lib/exec/parent.go
@@ -7,6 +7,7 @@
 	"io"
 	"os"
 	"os/exec"
+	"strconv"
 	"strings"
 	"sync"
 	"syscall"
@@ -34,6 +35,7 @@
 	waitDone    bool
 	waitErr     error
 	waitLock    sync.Mutex
+	callbackPid int
 }
 
 // ParentHandleOpt is an option for NewParentHandle.
@@ -187,7 +189,12 @@
 			// waitForStatus has closed the channel, but we may not
 			// have read the message from it yet.
 		case st := <-c:
-			if st == readyStatus {
+			if strings.HasPrefix(st, readyStatus) {
+				pid, err := strconv.Atoi(st[len(readyStatus):])
+				if err != nil {
+					return err
+				}
+				p.callbackPid = pid
 				return nil
 			}
 			if strings.HasPrefix(st, failedStatus) {
@@ -253,6 +260,12 @@
 	return 0
 }
 
+// ChildPid returns the pid of a child process as reported by its status
+// callback.
+func (p *ParentHandle) ChildPid() int {
+	return p.callbackPid
+}
+
 // Exists returns true if the child process exists and can be signal'ed
 func (p *ParentHandle) Exists() bool {
 	if p.c.Process != nil {
diff --git a/lib/filelocker/locker_test.go b/lib/filelocker/locker_test.go
index b58bfe2..cf483a7 100644
--- a/lib/filelocker/locker_test.go
+++ b/lib/filelocker/locker_test.go
@@ -42,7 +42,7 @@
 
 func testLockChild(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	// Lock the file
-	unlocker, err := Lock(args[1])
+	unlocker, err := Lock(args[0])
 	if err != nil {
 		return fmt.Errorf("Lock failed: %v", err)
 	}
diff --git a/lib/flags/flags.go b/lib/flags/flags.go
index b2c767e..241420c 100644
--- a/lib/flags/flags.go
+++ b/lib/flags/flags.go
@@ -5,6 +5,7 @@
 	"fmt"
 	"os"
 	"strings"
+	"sync"
 
 	"v.io/core/veyron/lib/flags/consts"
 )
@@ -236,12 +237,40 @@
 	return f
 }
 
+var (
+	defaultProtocol = "wsh" // GUARDED_BY listenMu
+	defaultHostPort = ":0"  // GUARDED_BY listenMu
+	listenMu        sync.RWMutex
+)
+
+// SetDefaultProtocol sets the default protocol used when --veyron.tcp.protocol is
+// not provided. It must be called before flags are parsed for it to take effect.
+func SetDefaultProtocol(protocol string) {
+	listenMu.Lock()
+	defaultProtocol = protocol
+	listenMu.Unlock()
+}
+
+// SetDefaultHostPort sets the default host and port used when --veyron.tcp.address
+// is not provided. It must be called before flags are parsed for it to take effect.
+func SetDefaultHostPort(s string) {
+	listenMu.Lock()
+	defaultHostPort = s
+	listenMu.Unlock()
+}
+
 // createAndRegisterListenFlags creates and registers the ListenFlags
 // group with the supplied flag.FlagSet.
 func createAndRegisterListenFlags(fs *flag.FlagSet) *ListenFlags {
+	listenMu.RLock()
+	defer listenMu.RUnlock()
+	var ipHostPortFlag IPHostPortFlag
+	if err := ipHostPortFlag.Set(defaultHostPort); err != nil {
+		panic(err)
+	}
 	f := &ListenFlags{
-		protocol:  TCPProtocolFlag{"wsh"},
-		addresses: ipHostPortFlagVar{validator: IPHostPortFlag{Port: "0"}},
+		protocol:  TCPProtocolFlag{defaultProtocol},
+		addresses: ipHostPortFlagVar{validator: ipHostPortFlag},
 	}
 	f.addresses.flags = f
 
diff --git a/lib/modules/core/core_test.go b/lib/modules/core/core_test.go
index a0e03e8..9f2b0b5 100644
--- a/lib/modules/core/core_test.go
+++ b/lib/modules/core/core_test.go
@@ -55,7 +55,7 @@
 }
 
 func testArgs(args ...string) []string {
-	var targs = []string{"--", "--veyron.tcp.address=127.0.0.1:0"}
+	var targs = []string{"--veyron.tcp.address=127.0.0.1:0"}
 	return append(targs, args...)
 }
 
diff --git a/lib/modules/core/echo.go b/lib/modules/core/echo.go
index 92160b9..8ba8f5f 100644
--- a/lib/modules/core/echo.go
+++ b/lib/modules/core/echo.go
@@ -50,13 +50,6 @@
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
-	fl, args, err := parseListenFlags(args)
-	if err != nil {
-		return fmt.Errorf("failed to parse args: %s", err)
-	}
-	if err := checkArgs(args, 2, "<message> <name>"); err != nil {
-		return err
-	}
 	id, mp := args[0], args[1]
 	disp := &treeDispatcher{id: id}
 	server, err := veyron2.NewServer(ctx)
@@ -64,7 +57,7 @@
 		return err
 	}
 	defer server.Stop()
-	eps, err := server.Listen(initListenSpec(fl))
+	eps, err := server.Listen(veyron2.GetListenSpec(ctx))
 	if err != nil {
 		return err
 	}
@@ -83,7 +76,6 @@
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
-	args = args[1:]
 	name := args[0]
 	args = args[1:]
 	client := veyron2.GetClient(ctx)
diff --git a/lib/modules/core/mounttable.go b/lib/modules/core/mounttable.go
index 6046c91..00acb04 100644
--- a/lib/modules/core/mounttable.go
+++ b/lib/modules/core/mounttable.go
@@ -34,11 +34,7 @@
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
-	fl, args, err := parseListenFlags(args)
-	if err != nil {
-		return fmt.Errorf("failed to parse args: %s", err)
-	}
-	lspec := initListenSpec(fl)
+	lspec := veyron2.GetListenSpec(ctx)
 	server, err := veyron2.NewServer(ctx, options.ServesMountTable(true))
 	if err != nil {
 		return fmt.Errorf("root failed: %v", err)
@@ -74,7 +70,6 @@
 	defer shutdown()
 
 	details := false
-	args = args[1:] // skip over command name
 	if len(args) > 0 && args[0] == "-l" {
 		details = true
 		args = args[1:]
diff --git a/lib/modules/core/proxy.go b/lib/modules/core/proxy.go
index 79d826b..691d1ca 100644
--- a/lib/modules/core/proxy.go
+++ b/lib/modules/core/proxy.go
@@ -22,18 +22,17 @@
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
-	fl, args, err := parseListenFlags(args)
-	if err != nil {
-		return fmt.Errorf("failed to parse args: %s", err)
-	}
 	expected := len(args)
 	rid, err := naming.NewRoutingID()
 	if err != nil {
 		return err
 	}
-	lf := fl.ListenFlags()
 
-	proxy, err := proxy.New(rid, veyron2.GetPrincipal(ctx), lf.Addrs[0].Protocol, lf.Addrs[0].Address, "")
+	listenSpec := veyron2.GetListenSpec(ctx)
+	protocol := listenSpec.Addrs[0].Protocol
+	addr := listenSpec.Addrs[0].Address
+
+	proxy, err := proxy.New(rid, veyron2.GetPrincipal(ctx), protocol, addr, "")
 	if err != nil {
 		return err
 	}
diff --git a/lib/modules/core/test_identityd.go b/lib/modules/core/test_identityd.go
index f1bc19a..87fe38a 100644
--- a/lib/modules/core/test_identityd.go
+++ b/lib/modules/core/test_identityd.go
@@ -10,7 +10,6 @@
 
 	"v.io/core/veyron2"
 
-	"v.io/core/veyron/lib/flags"
 	"v.io/core/veyron/lib/modules"
 
 	"v.io/core/veyron/services/identity/auditor"
@@ -23,46 +22,40 @@
 )
 
 var (
-	ifs *flag.FlagSet = flag.NewFlagSet("test_identityd", flag.ContinueOnError)
-
-	googleDomain = ifs.String("google_domain", "", "An optional domain name. When set, only email addresses from this domain are allowed to authenticate via Google OAuth")
-	host         = ifs.String("host", "localhost", "Hostname the HTTP server listens on. This can be the name of the host running the webserver, but if running behind a NAT or load balancer, this should be the host name that clients will connect to. For example, if set to 'x.com', Veyron identities will have the IssuerName set to 'x.com' and clients can expect to find the root name and public key of the signer at 'x.com/blessing-root'.")
-	httpaddr     = ifs.String("httpaddr", "localhost:0", "Address on which the HTTP server listens on.")
-	tlsconfig    = ifs.String("tlsconfig", "", "Comma-separated list of TLS certificate and private key files. This must be provided.")
-
-	ifl *flags.Flags = flags.CreateAndRegister(ifs, flags.Listen)
+	host      = flag.CommandLine.String("host", "localhost", "Hostname the HTTP server listens on. This can be the name of the host running the webserver, but if running behind a NAT or load balancer, this should be the host name that clients will connect to. For example, if set to 'x.com', Veyron identities will have the IssuerName set to 'x.com' and clients can expect to find the root name and public key of the signer at 'x.com/blessing-root'.")
+	httpaddr  = flag.CommandLine.String("httpaddr", "localhost:0", "Address on which the HTTP server listens on.")
+	tlsconfig = flag.CommandLine.String("tlsconfig", "", "Comma-separated list of TLS certificate and private key files. This must be provided.")
 )
 
 func init() {
-	modules.RegisterChild(TestIdentitydCommand, usage(ifs), startTestIdentityd)
+	modules.RegisterChild(TestIdentitydCommand, usage(flag.CommandLine), startTestIdentityd)
 }
 
 func startTestIdentityd(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	if err := parseFlags(ifl, args); err != nil {
-		return fmt.Errorf("failed to parse args: %s", err)
-	}
-
 	// Duration to use for tls cert and blessing duration.
 	duration := 365 * 24 * time.Hour
 
+	ctx, shutdown := veyron2.Init()
+	defer shutdown()
+
 	// If no tlsconfig has been provided, generate new cert and key and use them.
-	if ifs.Lookup("tlsconfig").Value.String() == "" {
+	if flag.CommandLine.Lookup("tlsconfig").Value.String() == "" {
 		certFile, keyFile, err := util.WriteCertAndKey(*host, duration)
 		if err != nil {
 			return fmt.Errorf("Could not write cert and key: %v", err)
 		}
-		if err := ifs.Set("tlsconfig", certFile+","+keyFile); err != nil {
+		if err := flag.CommandLine.Set("tlsconfig", certFile+","+keyFile); err != nil {
 			return fmt.Errorf("Could not set tlsconfig: %v", err)
 		}
 	}
 
 	// Pick a free port if httpaddr flag is not set.
-	// We can't use :0 here, because the identity server calles
-	// http.ListenAndServeTLS, which block, leaving us with no way to tell
+	// We can't use :0 here, because the identity server calls
+	// http.ListenAndServeTLS, which blocks, leaving us with no way to tell
 	// what port the server is running on.  Hence, we must pass in an
 	// actual port so we know where the server is running.
-	if ifs.Lookup("httpaddr").Value.String() == ifs.Lookup("httpaddr").DefValue {
-		if err := ifs.Set("httpaddr", "localhost:"+freePort()); err != nil {
+	if flag.CommandLine.Lookup("httpaddr").Value.String() == flag.CommandLine.Lookup("httpaddr").DefValue {
+		if err := flag.CommandLine.Set("httpaddr", "localhost:"+freePort()); err != nil {
 			return fmt.Errorf("Could not set httpaddr: %v", err)
 		}
 	}
@@ -74,7 +67,6 @@
 	params := blesser.OAuthBlesserParams{
 		OAuthProvider:     oauthProvider,
 		BlessingDuration:  duration,
-		DomainRestriction: *googleDomain,
 		RevocationManager: revocationManager,
 	}
 
@@ -84,12 +76,10 @@
 		reader,
 		revocationManager,
 		params,
-		caveats.NewMockCaveatSelector())
+		caveats.NewMockCaveatSelector(),
+		nil)
 
-	l := initListenSpec(ifl)
-
-	ctx, shutdown := veyron2.Init()
-	defer shutdown()
+	l := veyron2.GetListenSpec(ctx)
 
 	_, veyronEPs, externalHttpaddress := s.Listen(ctx, &l, *host, *httpaddr, *tlsconfig)
 
diff --git a/lib/modules/core/util.go b/lib/modules/core/util.go
index 3d16bb7..08c53f3 100644
--- a/lib/modules/core/util.go
+++ b/lib/modules/core/util.go
@@ -4,36 +4,8 @@
 	"flag"
 	"fmt"
 	"strings"
-
-	"v.io/core/veyron2/ipc"
-
-	"v.io/core/veyron/lib/flags"
 )
 
-func parseFlags(fl *flags.Flags, args []string) error {
-	if len(args) == 0 {
-		return nil
-	}
-	return fl.Parse(args[1:], nil)
-}
-
-// parseListenFlags parses the given args using just the flags and env vars
-// defined in the veyron/lib/flags package.
-func parseListenFlags(args []string) (*flags.Flags, []string, error) {
-	fs := flag.NewFlagSet("modules/core", flag.ContinueOnError)
-	fl := flags.CreateAndRegister(fs, flags.Listen)
-	err := parseFlags(fl, args)
-	return fl, fl.Args(), err
-}
-
-func initListenSpec(fl *flags.Flags) ipc.ListenSpec {
-	lf := fl.ListenFlags()
-	return ipc.ListenSpec{
-		Addrs: ipc.ListenAddrs(lf.Addrs),
-		Proxy: lf.ListenProxy,
-	}
-}
-
 // checkArgs checks for the expected number of args in args. A negative
 // value means at least that number of args are expected.
 func checkArgs(args []string, expected int, usage string) error {
diff --git a/lib/modules/core/wspr.go b/lib/modules/core/wspr.go
index 42db213..8e38a84 100644
--- a/lib/modules/core/wspr.go
+++ b/lib/modules/core/wspr.go
@@ -5,7 +5,6 @@
 	"fmt"
 	"io"
 
-	"v.io/core/veyron/lib/flags"
 	"v.io/core/veyron/lib/modules"
 	"v.io/wspr/veyron/services/wsprd/wspr"
 
@@ -13,29 +12,19 @@
 )
 
 var (
-	// TODO(sadovsky): We should restructure things so that we can avoid
-	// duplicating code between subprocess command impls and actual main()'s.
-	fs *flag.FlagSet = flag.NewFlagSet("wspr", flag.ContinueOnError)
-
-	port   *int    = fs.Int("port", 0, "Port to listen on.")
-	identd *string = fs.String("identd", "", "identd server name. Must be set.")
-
-	fl *flags.Flags = flags.CreateAndRegister(fs, flags.Listen)
+	port   *int    = flag.CommandLine.Int("port", 0, "Port to listen on.")
+	identd *string = flag.CommandLine.String("identd", "", "identd server name. Must be set.")
 )
 
 func init() {
-	modules.RegisterChild(WSPRCommand, usage(fs), startWSPR)
+	modules.RegisterChild(WSPRCommand, usage(flag.CommandLine), startWSPR)
 }
 
 func startWSPR(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	if err := parseFlags(fl, args); err != nil {
-		return fmt.Errorf("failed to parse args: %s", err)
-	}
-
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
-	l := initListenSpec(fl)
+	l := veyron2.GetListenSpec(ctx)
 	proxy := wspr.NewWSPR(ctx, *port, &l, *identd, nil)
 	defer proxy.Shutdown()
 
diff --git a/lib/modules/examples_test.go b/lib/modules/examples_test.go
index cb97b64..e4ab42a 100644
--- a/lib/modules/examples_test.go
+++ b/lib/modules/examples_test.go
@@ -36,9 +36,8 @@
 	h, _ := sh.Start("echo", nil, "a", "b")
 	h.Shutdown(os.Stdout, os.Stderr)
 	// Output:
-	// 0: echo
-	// 1: a
-	// 2: b
+	// 0: a
+	// 1: b
 }
 
 func ExampleDispatchAndExit() {
@@ -51,7 +50,6 @@
 	h, _ := sh.Start("echo", nil, "c", "d")
 	h.Shutdown(os.Stdout, os.Stderr)
 	// Output:
-	// 0: echo
-	// 1: c
-	// 2: d
+	// 0: c
+	// 1: d
 }
diff --git a/lib/modules/func.go b/lib/modules/func.go
index 5c5bc4c..24f1fde 100644
--- a/lib/modules/func.go
+++ b/lib/modules/func.go
@@ -88,7 +88,7 @@
 		cenv := envSliceToMap(env)
 		vlog.VI(1).Infof("Start: %q args: %v", fh.name, args)
 		vlog.VI(2).Infof("Start: %q env: %v", fh.name, cenv)
-		err := main(stdin, stdout, stderr, cenv, args...)
+		err := main(stdin, stdout, stderr, cenv, args[1:]...)
 		if err != nil {
 			fmt.Fprintf(stderr, "%s\n", err)
 		}
diff --git a/lib/modules/modules_test.go b/lib/modules/modules_test.go
index 277fb2f..a5c989d 100644
--- a/lib/modules/modules_test.go
+++ b/lib/modules/modules_test.go
@@ -62,7 +62,7 @@
 }
 
 func PrintFromEnv(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	for _, a := range args[1:] {
+	for _, a := range args {
 		if v := env[a]; len(v) > 0 {
 			fmt.Fprintf(stdout, "%s\n", a+"="+v)
 		} else {
@@ -286,7 +286,7 @@
 	var stdoutBuf bytes.Buffer
 	var stderrBuf bytes.Buffer
 	sh.Cleanup(&stdoutBuf, &stderrBuf)
-	stdoutOutput, stderrOutput := "stdout: "+command+"\n", "stderr: "+command+"\n"
+	var stdoutOutput, stderrOutput string
 	for _, a := range args {
 		stdoutOutput += fmt.Sprintf("stdout: %s\n", a)
 		stderrOutput += fmt.Sprintf("stderr: %s\n", a)
diff --git a/lib/modules/registry.go b/lib/modules/registry.go
index 8331f9c..f473d14 100644
--- a/lib/modules/registry.go
+++ b/lib/modules/registry.go
@@ -200,8 +200,8 @@
 		}
 	}(os.Getppid())
 
-	args := append([]string{command}, flag.Args()...)
-	return m.main(os.Stdin, os.Stdout, os.Stderr, envSliceToMap(os.Environ()), args...)
+	flag.Parse()
+	return m.main(os.Stdin, os.Stdout, os.Stderr, envSliceToMap(os.Environ()), flag.Args()...)
 }
 
 // WaitForEOF returns when a read on its io.Reader parameter returns io.EOF
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index cc14137..85f8194 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -190,14 +190,12 @@
 		if err != nil {
 			return nil, err
 		}
-		// We store this blessing as the one to use with a pattern that matches
-		// the root's name.
-		// TODO(cnicolaou,caprita): at some point there will be a nicer API
-		// for getting the name of a blessing.
-		ctx := security.NewContext(&security.ContextParams{LocalPrincipal: root})
-		rootName := root.BlessingStore().Default().ForContext(ctx)[0]
-		if _, err := p.BlessingStore().Set(blessingFromChild, security.BlessingPattern(rootName)); err != nil {
-			return nil, err
+		// We store this blessing as the one to use with the patterns that match
+		// the root's names.
+		for rootName, _ := range root.BlessingsInfo(root.BlessingStore().Default()) {
+			if _, err := p.BlessingStore().Set(blessingFromChild, security.BlessingPattern(rootName)); err != nil {
+				return nil, err
+			}
 		}
 
 		if err := p.AddToRoots(blessingFromChild); err != nil {
diff --git a/lib/testutil/glob.go b/lib/testutil/glob.go
index 84d7ec7..0c6fd23 100644
--- a/lib/testutil/glob.go
+++ b/lib/testutil/glob.go
@@ -35,5 +35,6 @@
 	if ferr := call.Finish(&err); ferr != nil {
 		err = ferr
 	}
+
 	return results, err
 }
diff --git a/lib/testutil/integration/testdata/integration_test.go b/lib/testutil/integration/testdata/integration_test.go
new file mode 100644
index 0000000..97308d7
--- /dev/null
+++ b/lib/testutil/integration/testdata/integration_test.go
@@ -0,0 +1,28 @@
+package testdata
+
+import (
+	"testing"
+
+	"v.io/core/veyron/lib/modules"
+	"v.io/core/veyron/lib/testutil/integration"
+	_ "v.io/core/veyron/profiles"
+)
+
+func TestHelperProcess(t *testing.T) {
+	modules.DispatchInTest()
+}
+
+func TestBinaryFromPath(t *testing.T) {
+	env := integration.NewTestEnvironment(t)
+	defer env.Cleanup()
+
+	bash := env.BinaryFromPath("/bin/bash")
+	if want, got := "hello world\n", bash.Start("-c", "echo hello world").Output(); want != got {
+		t.Fatalf("unexpected output, want %s, got %s", want, got)
+	}
+
+	// TODO(sjr): revive this once stderr handling is fixed.
+	// if want, got := "hello world\n", bash.Start("-c", "echo hello world 1>&2").ErrorOutput(); want != got {
+	//	t.Fatalf("unexpected output, want %s, got %s", want, got)
+	// }
+}
diff --git a/lib/testutil/integration/util.go b/lib/testutil/integration/util.go
index 208fad1..8f5b314 100644
--- a/lib/testutil/integration/util.go
+++ b/lib/testutil/integration/util.go
@@ -79,6 +79,12 @@
 	// Cleanup cleans up the environment and deletes all its artifacts.
 	Cleanup()
 
+	// BinaryFromPath returns a new TestBinary that, when started, will
+	// execute the executable or script at the given path.
+	//
+	// E.g. env.BinaryFromPath("/bin/bash").Start("-c", "echo hello world").Output() -> "hello world"
+	BinaryFromPath(path string) TestBinary
+
 	// BuildGoPkg expects a Go package path that identifies a "main"
 	// package and returns a TestBinary representing the newly built
 	// binary.
@@ -355,9 +361,12 @@
 	writeStringOrDie(e.t, file, fmt.Sprintf("Root mounttable endpoint: %s\n", e.RootMT()))
 
 	shellPath := "/bin/sh"
+	if shellPathFromEnv := os.Getenv("SHELL"); shellPathFromEnv != "" {
+		shellPath = shellPathFromEnv
+	}
 	proc, err := os.StartProcess(shellPath, []string{}, &attr)
 	if err != nil {
-		e.t.Fatalf("StartProcess(%v) failed: %v", shellPath, err)
+		e.t.Fatalf("StartProcess(%q) failed: %v", shellPath, err)
 	}
 
 	// Wait until user exits the shell
@@ -369,6 +378,15 @@
 	writeStringOrDie(e.t, file, fmt.Sprintf("<< Exited shell: %s\n", state.String()))
 }
 
+func (e *integrationTestEnvironment) BinaryFromPath(path string) TestBinary {
+	return &integrationTestBinary{
+		env:         e,
+		envVars:     nil,
+		path:        path,
+		cleanupFunc: func() {},
+	}
+}
+
 func (e *integrationTestEnvironment) BuildGoPkg(binary_path string) TestBinary {
 	e.t.Logf("building %s...", binary_path)
 	if cached_binary := e.builtBinaries[binary_path]; cached_binary != nil {
@@ -503,7 +521,7 @@
 // returns a handle for the started command along with the object name
 // of the mount table.
 func startRootMT(shell *modules.Shell) (modules.Handle, string, error) {
-	handle, err := shell.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0")
+	handle, err := shell.Start(core.RootMTCommand, nil, "--veyron.tcp.address=127.0.0.1:0")
 	if err != nil {
 		return nil, "", err
 	}
diff --git a/profiles/genericinit.go b/profiles/genericinit.go
index b071c31..936cd2f 100644
--- a/profiles/genericinit.go
+++ b/profiles/genericinit.go
@@ -24,7 +24,9 @@
 func init() {
 	veyron2.RegisterProfileInit(Init)
 	stream.RegisterUnknownProtocol("wsh", websocket.HybridDial, websocket.HybridListener)
-	commonFlags = flags.CreateAndRegister(flag.CommandLine, flags.Runtime)
+	flags.SetDefaultProtocol("tcp")
+	flags.SetDefaultHostPort("127.0.0.1:0")
+	commonFlags = flags.CreateAndRegister(flag.CommandLine, flags.Runtime, flags.Listen)
 }
 
 func Init(ctx *context.T) (veyron2.Runtime, *context.T, veyron2.Shutdown, error) {
@@ -34,13 +36,17 @@
 
 	ac := appcycle.New()
 
+	lf := commonFlags.ListenFlags()
+	listenSpec := ipc.ListenSpec{
+		Addrs:          ipc.ListenAddrs(lf.Addrs),
+		AddressChooser: internal.IPAddressChooser,
+		Proxy:          lf.ListenProxy,
+	}
+
 	runtime, ctx, shutdown, err := grt.Init(ctx,
 		ac,
 		nil,
-		&ipc.ListenSpec{
-			Addrs:          ipc.ListenAddrs{{"tcp", "127.0.0.1:0"}},
-			AddressChooser: internal.IPAddressChooser,
-		},
+		&listenSpec,
 		commonFlags.RuntimeFlags(),
 		nil)
 	if err != nil {
diff --git a/runtimes/google/ipc/benchmark/RESULTS.txt b/runtimes/google/ipc/benchmark/RESULTS.txt
index b884698..95a44bf 100644
--- a/runtimes/google/ipc/benchmark/RESULTS.txt
+++ b/runtimes/google/ipc/benchmark/RESULTS.txt
@@ -8,1525 +8,1599 @@
   continuously in the same process.
 
 ================================================================================
-Date: 01/06/2015
+Date: 02/02/2015
 Platform: Intel(R) Xeon(R) CPU E5-2689 0 @ 2.60GHz,  66114888KB Memory
 
-Benchmark____1B	    2000	   5135719 ns/op	   0.00 MB/s
+Benchmark____1B	    5000	   1941933 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 6  Avg: 4.50
+	Count: 5000  Min: 1  Max: 4  Avg: 1.35
 	------------------------------------------------------------
-	[  4,   5)  1077   53.9%   53.9%  #####
-	[  5,   6)   843   42.2%   96.0%  ####
-	[  6, inf)    80    4.0%  100.0%  
-Benchmark____1B-2	    2000	   4968273 ns/op	   0.00 MB/s
+	[  1,   2)  3792   75.8%   75.8%  ########
+	[  2,   3)   734   14.7%   90.5%  #
+	[  3,   4)   397    7.9%   98.5%  #
+	[  4, inf)    77    1.5%  100.0%  
+Benchmark____1B-2	    5000	   1744191 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 6  Avg: 4.32
+	Count: 5000  Min: 1  Max: 3  Avg: 1.17
 	------------------------------------------------------------
-	[  4,   5)  1364   68.2%   68.2%  #######
-	[  5,   6)   628   31.4%   99.6%  ###
-	[  6, inf)     8    0.4%  100.0%  
-Benchmark___10B	    2000	   5207706 ns/op	   0.00 MB/s
+	[  1,   2)  4518   90.4%   90.4%  #########
+	[  2,   3)    91    1.8%   92.2%  
+	[  3, inf)   391    7.8%  100.0%  #
+Benchmark___10B	    5000	   2015671 ns/op	   0.01 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.58
+	Count: 5000  Min: 1  Max: 9  Avg: 1.39
 	------------------------------------------------------------
-	[  4,   5)  1380   69.0%   69.0%  #######
-	[  5,   6)   137    6.9%   75.9%  #
-	[  6,   7)   424   21.2%   97.1%  ##
-	[  7, inf)    59    3.0%  100.0%  
-Benchmark___10B-2	    2000	   5012485 ns/op	   0.00 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.35
-	------------------------------------------------------------
-	[  4,   5)  1541   77.1%   77.1%  ########
-	[  5,   6)   221   11.1%   88.1%  #
-	[  6,   7)   236   11.8%   99.9%  #
-	[  7, inf)     2    0.1%  100.0%  
-Benchmark__100B	    2000	   5313342 ns/op	   0.04 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 10  Avg: 4.62
-	------------------------------------------------------------
-	[  4,   5)  1505   75.2%   75.2%  ########
-	[  5,   6)   122    6.1%   81.4%  #
-	[  6,   7)    56    2.8%   84.2%  
-	[  7,   8)   259   13.0%   97.1%  #
-	[  8,   9)    57    2.9%  100.0%  
-	[  9,  10)     0    0.0%  100.0%  
-	[ 10, inf)     1    0.1%  100.0%  
-Benchmark__100B-2	    2000	   4997534 ns/op	   0.04 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.34
-	------------------------------------------------------------
-	[  4,   5)  1649   82.5%   82.5%  ########
-	[  5,   6)    18    0.9%   83.4%  
-	[  6,   7)   332   16.6%  100.0%  ##
-	[  7, inf)     1    0.1%  100.0%  
-Benchmark___1KB	    2000	   5247848 ns/op	   0.38 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 9  Avg: 4.62
-	------------------------------------------------------------
-	[  4,   5)  1626   81.3%   81.3%  ########
-	[  5,   6)    67    3.4%   84.7%  
-	[  6,   7)    12    0.6%   85.2%  
-	[  7,   8)    64    3.2%   88.5%  
-	[  8,   9)   196    9.8%   98.2%  #
-	[  9, inf)    35    1.8%  100.0%  
-Benchmark___1KB-2	    2000	   4925061 ns/op	   0.41 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.31
-	------------------------------------------------------------
-	[  4,   5)  1720   86.0%   86.0%  #########
-	[  5,   6)    12    0.6%   86.6%  
-	[  6,   7)   198    9.9%   96.5%  #
-	[  7, inf)    70    3.5%  100.0%  
-Benchmark__10KB	    2000	   5498704 ns/op	   3.64 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 11  Avg: 4.79
-	------------------------------------------------------------
-	[  4,   5)  1577   78.9%   78.9%  ########
-	[  5,   6)    94    4.7%   83.6%  
-	[  6,   7)    47    2.4%   85.9%  
-	[  7,   8)     0    0.0%   85.9%  
-	[  8,   9)    89    4.5%   90.4%  
-	[  9,  10)   123    6.2%   96.5%  #
-	[ 10,  12)    70    3.5%  100.0%  
+	[  1,   2)  4554   91.1%   91.1%  #########
+	[  2,   3)    17    0.3%   91.4%  
+	[  3,   4)   102    2.0%   93.5%  
+	[  4,   5)    21    0.4%   93.9%  
+	[  5,   6)    60    1.2%   95.1%  
+	[  6,   8)   180    3.6%   98.7%  
+	[  8,  10)    66    1.3%  100.0%  
+	[ 10,  12)     0    0.0%  100.0%  
 	[ 12, inf)     0    0.0%  100.0%  
-Benchmark__10KB-2	    2000	   5046850 ns/op	   3.96 MB/s
+Benchmark___10B-2	    5000	   1830436 ns/op	   0.01 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 9  Avg: 4.42
+	Count: 5000  Min: 1  Max: 6  Avg: 1.20
 	------------------------------------------------------------
-	[  4,   5)  1689   84.5%   84.5%  ########
-	[  5,   6)    50    2.5%   87.0%  
-	[  6,   7)     0    0.0%   87.0%  
-	[  7,   8)   251   12.6%   99.5%  #
-	[  8,   9)     7    0.4%   99.9%  
-	[  9, inf)     3    0.2%  100.0%  
-Benchmark_100KB	    1000	   7995692 ns/op	  25.01 MB/s
+	[  1,   2)  4731   94.6%   94.6%  #########
+	[  2,   3)    21    0.4%   95.0%  
+	[  3,   4)     0    0.0%   95.0%  
+	[  4,   5)    47    0.9%   96.0%  
+	[  5,   6)   161    3.2%   99.2%  
+	[  6, inf)    40    0.8%  100.0%  
+Benchmark__100B	    3000	   2140626 ns/op	   0.09 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 6  Max: 13  Avg: 7.50
+	Count: 3000  Min: 1  Max: 15  Avg: 1.47
 	------------------------------------------------------------
-	[  6,   7)   685   68.5%   68.5%  #######
-	[  7,   8)    55    5.5%   74.0%  #
-	[  8,   9)    17    1.7%   75.7%  
-	[  9,  10)     0    0.0%   75.7%  
-	[ 10,  11)     0    0.0%   75.7%  
-	[ 11,  12)    63    6.3%   82.0%  #
-	[ 12,  14)   180   18.0%  100.0%  ##
-	[ 14, inf)     0    0.0%  100.0%  
-Benchmark_100KB-2	    1000	   6064046 ns/op	  32.98 MB/s
+	[  1,   2)  2811   93.7%   93.7%  #########
+	[  2,   3)     6    0.2%   93.9%  
+	[  3,   4)     5    0.2%   94.1%  
+	[  4,   5)    17    0.6%   94.6%  
+	[  5,   7)    36    1.2%   95.8%  
+	[  7,   9)    19    0.6%   96.5%  
+	[  9,  11)    38    1.3%   97.7%  
+	[ 11,  14)    62    2.1%   99.8%  
+	[ 14,  18)     6    0.2%  100.0%  
+	[ 18,  22)     0    0.0%  100.0%  
+	[ 22,  27)     0    0.0%  100.0%  
+	[ 27,  33)     0    0.0%  100.0%  
+	[ 33,  41)     0    0.0%  100.0%  
+	[ 41,  50)     0    0.0%  100.0%  
+	[ 50, inf)     0    0.0%  100.0%  
+Benchmark__100B-2	    5000	   1852904 ns/op	   0.11 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 9  Avg: 5.77
+	Count: 5000  Min: 1  Max: 11  Avg: 1.21
 	------------------------------------------------------------
-	[  5,   6)   762   76.2%   76.2%  ########
-	[  6,   7)     3    0.3%   76.5%  
-	[  7,   8)     0    0.0%   76.5%  
-	[  8,   9)   173   17.3%   93.8%  ##
-	[  9, inf)    62    6.2%  100.0%  #
-
-Benchmark____1_chunk_____1B	    2000	   5445727 ns/op	   0.00 MB/s
+	[  1,   2)  4803   96.1%   96.1%  ##########
+	[  2,   3)    20    0.4%   96.5%  
+	[  3,   4)     0    0.0%   96.5%  
+	[  4,   5)     0    0.0%   96.5%  
+	[  5,   6)     0    0.0%   96.5%  
+	[  6,   8)   160    3.2%   99.7%  
+	[  8,  10)     9    0.2%   99.8%  
+	[ 10,  12)     8    0.2%  100.0%  
+	[ 12,  15)     0    0.0%  100.0%  
+	[ 15,  18)     0    0.0%  100.0%  
+	[ 18, inf)     0    0.0%  100.0%  
+Benchmark___1KB	    3000	   2231959 ns/op	   0.90 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.87
+	Count: 3000  Min: 1  Max: 19  Avg: 1.53
 	------------------------------------------------------------
-	[  4,   5)   664   33.2%   33.2%  ###
-	[  5,   6)   940   47.0%   80.2%  #####
-	[  6,   7)   395   19.8%  100.0%  ##
-	[  7, inf)     1    0.1%  100.0%  
-Benchmark____1_chunk_____1B-2	    2000	   5178446 ns/op	   0.00 MB/s
+	[  1,   2)  2875   95.8%   95.8%  ##########
+	[  2,   3)     1    0.0%   95.9%  
+	[  3,   4)     0    0.0%   95.9%  
+	[  4,   5)     0    0.0%   95.9%  
+	[  5,   7)     8    0.3%   96.1%  
+	[  7,   9)    21    0.7%   96.8%  
+	[  9,  12)     0    0.0%   96.8%  
+	[ 12,  15)    29    1.0%   97.8%  
+	[ 15,  19)    56    1.9%   99.7%  
+	[ 19,  24)    10    0.3%  100.0%  
+	[ 24,  30)     0    0.0%  100.0%  
+	[ 30,  38)     0    0.0%  100.0%  
+	[ 38,  48)     0    0.0%  100.0%  
+	[ 48,  60)     0    0.0%  100.0%  
+	[ 60,  74)     0    0.0%  100.0%  
+	[ 74,  91)     0    0.0%  100.0%  
+	[ 91, inf)     0    0.0%  100.0%  
+Benchmark___1KB-2	    3000	   2078680 ns/op	   0.96 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 6  Avg: 4.46
+	Count: 3000  Min: 1  Max: 12  Avg: 1.35
 	------------------------------------------------------------
-	[  4,   5)  1130   56.5%   56.5%  ######
-	[  5,   6)   825   41.2%   97.8%  ####
-	[  6, inf)    45    2.2%  100.0%  
-Benchmark____1_chunk____10B	    2000	   5545419 ns/op	   0.00 MB/s
+	[  1,   2)  2699   90.0%   90.0%  #########
+	[  2,   3)   213    7.1%   97.1%  #
+	[  3,   4)     0    0.0%   97.1%  
+	[  4,   5)     0    0.0%   97.1%  
+	[  5,   6)     0    0.0%   97.1%  
+	[  6,   8)     0    0.0%   97.1%  
+	[  8,  10)    20    0.7%   97.7%  
+	[ 10,  13)    68    2.3%  100.0%  
+	[ 13,  16)     0    0.0%  100.0%  
+	[ 16,  20)     0    0.0%  100.0%  
+	[ 20,  24)     0    0.0%  100.0%  
+	[ 24, inf)     0    0.0%  100.0%  
+Benchmark__10KB	    3000	   2548055 ns/op	   7.85 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.89
+	Count: 3000  Min: 1  Max: 24  Avg: 1.73
 	------------------------------------------------------------
-	[  4,   5)   985   49.2%   49.2%  #####
-	[  5,   6)   473   23.7%   72.9%  ##
-	[  6,   7)   321   16.1%   89.0%  ##
-	[  7, inf)   221   11.1%  100.0%  #
-Benchmark____1_chunk____10B-2	    2000	   5217440 ns/op	   0.00 MB/s
+	[  1,   2)  2665   88.8%   88.8%  #########
+	[  2,   3)   196    6.5%   95.4%  #
+	[  3,   4)     0    0.0%   95.4%  
+	[  4,   5)     0    0.0%   95.4%  
+	[  5,   7)     0    0.0%   95.4%  
+	[  7,   9)    42    1.4%   96.8%  
+	[  9,  12)     0    0.0%   96.8%  
+	[ 12,  16)    30    1.0%   97.8%  
+	[ 16,  21)    19    0.6%   98.4%  
+	[ 21,  27)    48    1.6%  100.0%  
+	[ 27,  35)     0    0.0%  100.0%  
+	[ 35,  44)     0    0.0%  100.0%  
+	[ 44,  56)     0    0.0%  100.0%  
+	[ 56,  71)     0    0.0%  100.0%  
+	[ 71,  89)     0    0.0%  100.0%  
+	[ 89, 111)     0    0.0%  100.0%  
+	[111, inf)     0    0.0%  100.0%  
+Benchmark__10KB-2	    3000	   2242089 ns/op	   8.92 MB/s
 --- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 6  Avg: 4.55
+	Count: 3000  Min: 1  Max: 14  Avg: 1.53
 	------------------------------------------------------------
-	[  4,   5)  1311   65.5%   65.5%  #######
-	[  5,   6)   279   14.0%   79.5%  #
-	[  6, inf)   410   20.5%  100.0%  ##
-Benchmark____1_chunk___100B	    2000	   5607749 ns/op	   0.04 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 9  Avg: 5.00
-	------------------------------------------------------------
-	[  4,   5)   981   49.1%   49.1%  #####
-	[  5,   6)   614   30.7%   79.8%  ###
-	[  6,   7)    10    0.5%   80.2%  
-	[  7,   8)   216   10.8%   91.1%  #
-	[  8,   9)   178    8.9%  100.0%  #
-	[  9, inf)     1    0.1%  100.0%  
-Benchmark____1_chunk___100B-2	    2000	   5221803 ns/op	   0.04 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.48
-	------------------------------------------------------------
-	[  4,   5)  1421   71.0%   71.0%  #######
-	[  5,   6)   223   11.2%   82.2%  #
-	[  6,   7)   329   16.4%   98.7%  ##
-	[  7, inf)    27    1.4%  100.0%  
-Benchmark____1_chunk____1KB	    2000	   5499778 ns/op	   0.36 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 10  Avg: 4.74
-	------------------------------------------------------------
-	[  4,   5)  1456   72.8%   72.8%  #######
-	[  5,   6)   214   10.7%   83.5%  #
-	[  6,   7)    12    0.6%   84.1%  
-	[  7,   8)    72    3.6%   87.7%  
-	[  8,   9)   205   10.2%   98.0%  #
-	[  9,  10)    40    2.0%  100.0%  
-	[ 10, inf)     1    0.1%  100.0%  
-Benchmark____1_chunk____1KB-2	    2000	   5131389 ns/op	   0.39 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 7  Avg: 4.41
-	------------------------------------------------------------
-	[  4,   5)  1621   81.1%   81.1%  ########
-	[  5,   6)    89    4.5%   85.5%  
-	[  6,   7)   149    7.5%   93.0%  #
-	[  7, inf)   141    7.1%  100.0%  #
-Benchmark____1_chunk___10KB	    2000	   5747560 ns/op	   3.48 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 11  Avg: 5.12
-	------------------------------------------------------------
-	[  4,   5)  1023   51.2%   51.2%  #####
-	[  5,   6)   598   29.9%   81.1%  ###
-	[  6,   7)    78    3.9%   85.0%  
-	[  7,   8)     1    0.1%   85.0%  
-	[  8,   9)    72    3.6%   88.6%  
-	[  9,  10)   164    8.2%   96.8%  #
-	[ 10,  12)    64    3.2%  100.0%  
-	[ 12, inf)     0    0.0%  100.0%  
-Benchmark____1_chunk___10KB-2	    2000	   5240887 ns/op	   3.82 MB/s
---- Histogram (unit: ms)
-	Count: 2000  Min: 4  Max: 10  Avg: 4.55
-	------------------------------------------------------------
-	[  4,   5)  1515   75.8%   75.8%  ########
-	[  5,   6)   208   10.4%   86.2%  #
-	[  6,   7)     0    0.0%   86.2%  
-	[  7,   8)   231   11.6%   97.7%  #
-	[  8,   9)    29    1.5%   99.2%  
-	[  9,  10)    16    0.8%  100.0%  
-	[ 10, inf)     1    0.1%  100.0%  
-Benchmark____1_chunk__100KB	    1000	   8096470 ns/op	  24.70 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 6  Max: 13  Avg: 7.54
-	------------------------------------------------------------
-	[  6,   7)   687   68.7%   68.7%  #######
-	[  7,   8)    64    6.4%   75.1%  #
-	[  8,   9)     1    0.1%   75.2%  
-	[  9,  10)     0    0.0%   75.2%  
-	[ 10,  11)     0    0.0%   75.2%  
-	[ 11,  12)    24    2.4%   77.6%  
-	[ 12,  14)   224   22.4%  100.0%  ##
-	[ 14, inf)     0    0.0%  100.0%  
-Benchmark____1_chunk__100KB-2	    1000	   6401830 ns/op	  31.24 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 11  Avg: 5.91
-	------------------------------------------------------------
-	[  5,   6)   748   74.8%   74.8%  #######
-	[  6,   7)    14    1.4%   76.2%  
-	[  7,   8)     1    0.1%   76.3%  
-	[  8,   9)   106   10.6%   86.9%  #
-	[  9,  10)    81    8.1%   95.0%  #
-	[ 10,  11)    46    4.6%   99.6%  
-	[ 11, inf)     4    0.4%  100.0%  
-Benchmark___10_chunk_____1B	    1000	   7091901 ns/op	   0.00 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 14  Avg: 6.78
-	------------------------------------------------------------
-	[  5,   6)    28    2.8%    2.8%  
-	[  6,   7)   819   81.9%   84.7%  ########
-	[  7,   8)    10    1.0%   85.7%  
-	[  8,   9)    25    2.5%   88.2%  
-	[  9,  10)     0    0.0%   88.2%  
-	[ 10,  12)    30    3.0%   91.2%  
-	[ 12,  14)    86    8.6%   99.8%  #
-	[ 14,  16)     2    0.2%  100.0%  
-	[ 16,  19)     0    0.0%  100.0%  
-	[ 19, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk_____1B-2	    1000	   6297751 ns/op	   0.00 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 11  Avg: 5.68
-	------------------------------------------------------------
-	[  5,   6)   759   75.9%   75.9%  ########
-	[  6,   7)   118   11.8%   87.7%  #
-	[  7,   8)     0    0.0%   87.7%  
-	[  8,   9)    14    1.4%   89.1%  
-	[  9,  10)    40    4.0%   93.1%  
-	[ 10,  11)    51    5.1%   98.2%  #
-	[ 11, inf)    18    1.8%  100.0%  
-Benchmark___10_chunk____10B	    1000	   7358008 ns/op	   0.03 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 6  Max: 16  Avg: 6.88
-	------------------------------------------------------------
-	[  6,   7)   845   84.5%   84.5%  ########
-	[  7,   8)     9    0.9%   85.4%  
-	[  8,   9)    28    2.8%   88.2%  
-	[  9,  10)     0    0.0%   88.2%  
-	[ 10,  11)     0    0.0%   88.2%  
-	[ 11,  13)    29    2.9%   91.1%  
-	[ 13,  15)    86    8.6%   99.7%  #
-	[ 15,  17)     3    0.3%  100.0%  
-	[ 17,  20)     0    0.0%  100.0%  
-	[ 20,  23)     0    0.0%  100.0%  
-	[ 23, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk____10B-2	    1000	   6307487 ns/op	   0.03 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 12  Avg: 5.67
-	------------------------------------------------------------
-	[  5,   6)   779   77.9%   77.9%  ########
-	[  6,   7)   103   10.3%   88.2%  #
-	[  7,   8)     2    0.2%   88.4%  
-	[  8,   9)     9    0.9%   89.3%  
-	[  9,  10)    40    4.0%   93.3%  
-	[ 10,  11)    32    3.2%   96.5%  
-	[ 11,  13)    35    3.5%  100.0%  
-	[ 13, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk___100B	    1000	   7583639 ns/op	   0.26 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 6  Max: 16  Avg: 6.96
-	------------------------------------------------------------
-	[  6,   7)   833   83.3%   83.3%  ########
-	[  7,   8)    27    2.7%   86.0%  
-	[  8,   9)    22    2.2%   88.2%  
-	[  9,  10)     5    0.5%   88.7%  
-	[ 10,  11)     0    0.0%   88.7%  
-	[ 11,  13)    26    2.6%   91.3%  
-	[ 13,  15)    68    6.8%   98.1%  #
-	[ 15,  17)    19    1.9%  100.0%  
-	[ 17,  20)     0    0.0%  100.0%  
-	[ 20,  23)     0    0.0%  100.0%  
-	[ 23, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk___100B-2	    1000	   6213319 ns/op	   0.32 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 11  Avg: 5.56
-	------------------------------------------------------------
-	[  5,   6)   831   83.1%   83.1%  ########
-	[  6,   7)    58    5.8%   88.9%  #
-	[  7,   8)     0    0.0%   88.9%  
-	[  8,   9)     0    0.0%   88.9%  
-	[  9,  10)    58    5.8%   94.7%  #
-	[ 10,  11)    52    5.2%   99.9%  #
-	[ 11, inf)     1    0.1%  100.0%  
-Benchmark___10_chunk____1KB	    1000	   7839146 ns/op	   2.55 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 6  Max: 17  Avg: 7.15
-	------------------------------------------------------------
-	[  6,   7)   793   79.3%   79.3%  ########
-	[  7,   8)    60    6.0%   85.3%  #
-	[  8,   9)     4    0.4%   85.7%  
-	[  9,  10)    26    2.6%   88.3%  
-	[ 10,  11)     1    0.1%   88.4%  
-	[ 11,  13)     0    0.0%   88.4%  
-	[ 13,  15)    31    3.1%   91.5%  
-	[ 15,  18)    85    8.5%  100.0%  #
-	[ 18,  21)     0    0.0%  100.0%  
-	[ 21,  25)     0    0.0%  100.0%  
-	[ 25,  29)     0    0.0%  100.0%  
-	[ 29, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk____1KB-2	    1000	   6437679 ns/op	   3.11 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 13  Avg: 5.79
-	------------------------------------------------------------
-	[  5,   6)   757   75.7%   75.7%  ########
-	[  6,   7)   129   12.9%   88.6%  #
-	[  7,   8)     1    0.1%   88.7%  
-	[  8,   9)     0    0.0%   88.7%  
-	[  9,  10)    17    1.7%   90.4%  
-	[ 10,  12)    51    5.1%   95.5%  #
-	[ 12,  14)    45    4.5%  100.0%  
-	[ 14,  16)     0    0.0%  100.0%  
-	[ 16, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk___10KB	    1000	  10124684 ns/op	  19.75 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 8  Max: 20  Avg: 9.76
-	------------------------------------------------------------
-	[  8,   9)   746   74.6%   74.6%  #######
-	[  9,  10)     6    0.6%   75.2%  
-	[ 10,  11)    53    5.3%   80.5%  #
-	[ 11,  12)     3    0.3%   80.8%  
-	[ 12,  13)     0    0.0%   80.8%  
-	[ 13,  15)     0    0.0%   80.8%  
-	[ 15,  17)    56    5.6%   86.4%  #
-	[ 17,  20)   135   13.5%   99.9%  #
-	[ 20,  23)     1    0.1%  100.0%  
-	[ 23,  27)     0    0.0%  100.0%  
-	[ 27,  32)     0    0.0%  100.0%  
-	[ 32,  38)     0    0.0%  100.0%  
+	[  1,   2)  2328   77.6%   77.6%  ########
+	[  2,   3)   581   19.4%   97.0%  ##
+	[  3,   4)     0    0.0%   97.0%  
+	[  4,   5)     0    0.0%   97.0%  
+	[  5,   6)     0    0.0%   97.0%  
+	[  6,   8)     0    0.0%   97.0%  
+	[  8,  10)     0    0.0%   97.0%  
+	[ 10,  13)    45    1.5%   98.5%  
+	[ 13,  16)    46    1.5%  100.0%  
+	[ 16,  20)     0    0.0%  100.0%  
+	[ 20,  25)     0    0.0%  100.0%  
+	[ 25,  31)     0    0.0%  100.0%  
+	[ 31,  38)     0    0.0%  100.0%  
 	[ 38, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk___10KB-2	    1000	   7345578 ns/op	  27.23 MB/s
+Benchmark_100KB	    2000	   5112233 ns/op	  39.12 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 14  Avg: 6.95
+	Count: 2000  Min: 3  Max: 26  Avg: 4.49
 	------------------------------------------------------------
-	[  5,   6)   153   15.3%   15.3%  ##
-	[  6,   7)   616   61.6%   76.9%  ######
-	[  7,   8)    43    4.3%   81.2%  
-	[  8,   9)     2    0.2%   81.4%  
-	[  9,  10)     1    0.1%   81.5%  
-	[ 10,  12)    73    7.3%   88.8%  #
-	[ 12,  14)   104   10.4%   99.2%  #
-	[ 14,  16)     8    0.8%  100.0%  
-	[ 16,  19)     0    0.0%  100.0%  
-	[ 19, inf)     0    0.0%  100.0%  
-Benchmark___10_chunk__100KB	     200	  31538364 ns/op	  63.41 MB/s
+	[  3,   4)  1819   91.0%   91.0%  #########
+	[  4,   5)     0    0.0%   91.0%  
+	[  5,   6)     0    0.0%   91.0%  
+	[  6,   7)     0    0.0%   91.0%  
+	[  7,   9)    44    2.2%   93.2%  
+	[  9,  11)     1    0.1%   93.2%  
+	[ 11,  14)     0    0.0%   93.2%  
+	[ 14,  18)     0    0.0%   93.2%  
+	[ 18,  23)    45    2.2%   95.5%  
+	[ 23,  29)    91    4.5%  100.0%  
+	[ 29,  37)     0    0.0%  100.0%  
+	[ 37,  46)     0    0.0%  100.0%  
+	[ 46,  58)     0    0.0%  100.0%  
+	[ 58,  73)     0    0.0%  100.0%  
+	[ 73,  91)     0    0.0%  100.0%  
+	[ 91, 113)     0    0.0%  100.0%  
+	[113, inf)     0    0.0%  100.0%  
+Benchmark_100KB-2	    2000	   3661880 ns/op	  54.62 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 24  Max: 37  Avg: 31.07
+	Count: 2000  Min: 2  Max: 19  Avg: 3.00
 	------------------------------------------------------------
-	[ 24,  25)    5    2.5%    2.5%  
-	[ 25,  26)   60   30.0%   32.5%  ###
-	[ 26,  27)    2    1.0%   33.5%  
-	[ 27,  28)    0    0.0%   33.5%  
-	[ 28,  29)    0    0.0%   33.5%  
-	[ 29,  31)    0    0.0%   33.5%  
-	[ 31,  33)    0    0.0%   33.5%  
-	[ 33,  36)  129   64.5%   98.0%  ######
-	[ 36,  39)    4    2.0%  100.0%  
-	[ 39,  43)    0    0.0%  100.0%  
-	[ 43,  48)    0    0.0%  100.0%  
-	[ 48,  54)    0    0.0%  100.0%  
-	[ 54,  61)    0    0.0%  100.0%  
-	[ 61, inf)    0    0.0%  100.0%  
-Benchmark___10_chunk__100KB-2	     500	  19099352 ns/op	 104.72 MB/s
+	[  2,   3)  1657   82.9%   82.9%  ########
+	[  3,   4)   143    7.2%   90.0%  #
+	[  4,   5)    67    3.4%   93.4%  
+	[  5,   6)     1    0.1%   93.4%  
+	[  6,   8)     0    0.0%   93.4%  
+	[  8,  10)     0    0.0%   93.4%  
+	[ 10,  13)    13    0.7%   94.1%  
+	[ 13,  16)    48    2.4%   96.5%  
+	[ 16,  20)    71    3.6%  100.0%  
+	[ 20,  25)     0    0.0%  100.0%  
+	[ 25,  31)     0    0.0%  100.0%  
+	[ 31,  38)     0    0.0%  100.0%  
+	[ 38,  47)     0    0.0%  100.0%  
+	[ 47,  58)     0    0.0%  100.0%  
+	[ 58,  72)     0    0.0%  100.0%  
+	[ 72,  89)     0    0.0%  100.0%  
+	[ 89, inf)     0    0.0%  100.0%  
+
+Benchmark____1_chunk_____1B	    3000	   2154678 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 500  Min: 14  Max: 27  Avg: 18.58
+	Count: 3000  Min: 1  Max: 4  Avg: 1.42
 	------------------------------------------------------------
-	[ 14,  15)   53   10.6%   10.6%  #
-	[ 15,  16)  109   21.8%   32.4%  ##
-	[ 16,  17)   15    3.0%   35.4%  
-	[ 17,  18)    0    0.0%   35.4%  
-	[ 18,  19)    2    0.4%   35.8%  
-	[ 19,  21)  161   32.2%   68.0%  ###
-	[ 21,  23)  141   28.2%   96.2%  ###
-	[ 23,  26)   18    3.6%   99.8%  
-	[ 26,  29)    1    0.2%  100.0%  
-	[ 29,  33)    0    0.0%  100.0%  
-	[ 33,  38)    0    0.0%  100.0%  
-	[ 38,  44)    0    0.0%  100.0%  
-	[ 44,  51)    0    0.0%  100.0%  
-	[ 51, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk_____1B	     500	  19824819 ns/op	   0.01 MB/s
+	[  1,   2)  2069   69.0%   69.0%  #######
+	[  2,   3)   599   20.0%   88.9%  ##
+	[  3,   4)   331   11.0%  100.0%  #
+	[  4, inf)     1    0.0%  100.0%  
+Benchmark____1_chunk_____1B-2	    5000	   1907902 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 500  Min: 16  Max: 34  Avg: 19.44
+	Count: 5000  Min: 1  Max: 4  Avg: 1.21
 	------------------------------------------------------------
-	[ 16,  17)  272   54.4%   54.4%  #####
-	[ 17,  18)   15    3.0%   57.4%  
-	[ 18,  19)    2    0.4%   57.8%  
-	[ 19,  20)   38    7.6%   65.4%  #
-	[ 20,  22)   33    6.6%   72.0%  #
-	[ 22,  24)   23    4.6%   76.6%  
-	[ 24,  27)   41    8.2%   84.8%  #
-	[ 27,  30)   64   12.8%   97.6%  #
-	[ 30,  34)   11    2.2%   99.8%  
-	[ 34,  39)    1    0.2%  100.0%  
-	[ 39,  45)    0    0.0%  100.0%  
-	[ 45,  53)    0    0.0%  100.0%  
-	[ 53,  63)    0    0.0%  100.0%  
-	[ 63,  75)    0    0.0%  100.0%  
-	[ 75,  89)    0    0.0%  100.0%  
-	[ 89, 106)    0    0.0%  100.0%  
-	[106, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk_____1B-2	     500	  14793583 ns/op	   0.01 MB/s
+	[  1,   2)  4345   86.9%   86.9%  #########
+	[  2,   3)   275    5.5%   92.4%  #
+	[  3,   4)   377    7.5%   99.9%  #
+	[  4, inf)     3    0.1%  100.0%  
+Benchmark____1_chunk____10B	    3000	   2234222 ns/op	   0.01 MB/s
 --- Histogram (unit: ms)
-	Count: 500  Min: 11  Max: 23  Avg: 14.28
+	Count: 3000  Min: 1  Max: 7  Avg: 1.44
 	------------------------------------------------------------
-	[ 11,  12)   15    3.0%    3.0%  
-	[ 12,  13)  210   42.0%   45.0%  ####
-	[ 13,  14)  107   21.4%   66.4%  ##
-	[ 14,  15)   19    3.8%   70.2%  
-	[ 15,  16)    1    0.2%   70.4%  
-	[ 16,  18)   23    4.6%   75.0%  
-	[ 18,  20)   91   18.2%   93.2%  ##
-	[ 20,  23)   31    6.2%   99.4%  #
-	[ 23,  26)    3    0.6%  100.0%  
-	[ 26,  30)    0    0.0%  100.0%  
-	[ 30,  35)    0    0.0%  100.0%  
-	[ 35,  41)    0    0.0%  100.0%  
-	[ 41, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk____10B	     300	  24818102 ns/op	   0.08 MB/s
+	[  1,   2)  2603   86.8%   86.8%  #########
+	[  2,   3)    65    2.2%   88.9%  
+	[  3,   4)    77    2.6%   91.5%  
+	[  4,   5)    50    1.7%   93.2%  
+	[  5,   6)    87    2.9%   96.1%  
+	[  6,   7)   117    3.9%  100.0%  
+	[  7, inf)     1    0.0%  100.0%  
+Benchmark____1_chunk____10B-2	    5000	   1920770 ns/op	   0.01 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 20  Max: 35  Avg: 24.38
+	Count: 5000  Min: 1  Max: 5  Avg: 1.21
 	------------------------------------------------------------
-	[ 20,  21)    7    2.3%    2.3%  
-	[ 21,  22)  145   48.3%   50.7%  #####
-	[ 22,  23)   29    9.7%   60.3%  #
-	[ 23,  24)    4    1.3%   61.7%  
-	[ 24,  26)   25    8.3%   70.0%  #
-	[ 26,  28)    4    1.3%   71.3%  
-	[ 28,  30)   24    8.0%   79.3%  #
-	[ 30,  33)   43   14.3%   93.7%  #
-	[ 33,  37)   19    6.3%  100.0%  #
-	[ 37,  42)    0    0.0%  100.0%  
-	[ 42,  48)    0    0.0%  100.0%  
-	[ 48,  55)    0    0.0%  100.0%  
-	[ 55,  63)    0    0.0%  100.0%  
-	[ 63,  73)    0    0.0%  100.0%  
-	[ 73,  85)    0    0.0%  100.0%  
-	[ 85, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk____10B-2	     500	  15081537 ns/op	   0.13 MB/s
+	[  1,   2)  4571   91.4%   91.4%  #########
+	[  2,   3)   106    2.1%   93.5%  
+	[  3,   4)    23    0.5%   94.0%  
+	[  4,   5)   284    5.7%   99.7%  #
+	[  5, inf)    16    0.3%  100.0%  
+Benchmark____1_chunk___100B	    3000	   2296619 ns/op	   0.09 MB/s
 --- Histogram (unit: ms)
-	Count: 500  Min: 11  Max: 25  Avg: 14.57
+	Count: 3000  Min: 1  Max: 12  Avg: 1.49
 	------------------------------------------------------------
-	[ 11,  12)    1    0.2%    0.2%  
-	[ 12,  13)  182   36.4%   36.6%  ####
-	[ 13,  14)  143   28.6%   65.2%  ###
-	[ 14,  15)   23    4.6%   69.8%  
-	[ 15,  17)    7    1.4%   71.2%  
-	[ 17,  19)   51   10.2%   81.4%  #
-	[ 19,  21)   55   11.0%   92.4%  #
-	[ 21,  24)   34    6.8%   99.2%  #
-	[ 24,  28)    4    0.8%  100.0%  
-	[ 28,  32)    0    0.0%  100.0%  
-	[ 32,  37)    0    0.0%  100.0%  
-	[ 37,  43)    0    0.0%  100.0%  
-	[ 43,  51)    0    0.0%  100.0%  
-	[ 51,  60)    0    0.0%  100.0%  
-	[ 60, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk___100B	     300	  27491526 ns/op	   0.73 MB/s
+	[  1,   2)  2680   89.3%   89.3%  #########
+	[  2,   3)    98    3.3%   92.6%  
+	[  3,   4)    10    0.3%   92.9%  
+	[  4,   5)    53    1.8%   94.7%  
+	[  5,   6)     2    0.1%   94.8%  
+	[  6,   8)    57    1.9%   96.7%  
+	[  8,  10)    55    1.8%   98.5%  
+	[ 10,  13)    45    1.5%  100.0%  
+	[ 13,  16)     0    0.0%  100.0%  
+	[ 16,  20)     0    0.0%  100.0%  
+	[ 20,  24)     0    0.0%  100.0%  
+	[ 24, inf)     0    0.0%  100.0%  
+Benchmark____1_chunk___100B-2	    5000	   1971568 ns/op	   0.10 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 23  Max: 38  Avg: 26.94
+	Count: 5000  Min: 1  Max: 7  Avg: 1.26
 	------------------------------------------------------------
-	[ 23,  24)  104   34.7%   34.7%  ###
-	[ 24,  25)   67   22.3%   57.0%  ##
-	[ 25,  26)   10    3.3%   60.3%  
-	[ 26,  27)    8    2.7%   63.0%  
-	[ 27,  29)   23    7.7%   70.7%  #
-	[ 29,  31)    0    0.0%   70.7%  
-	[ 31,  33)   22    7.3%   78.0%  #
-	[ 33,  36)   57   19.0%   97.0%  ##
-	[ 36,  40)    9    3.0%  100.0%  
-	[ 40,  45)    0    0.0%  100.0%  
-	[ 45,  51)    0    0.0%  100.0%  
-	[ 51,  58)    0    0.0%  100.0%  
-	[ 58,  66)    0    0.0%  100.0%  
-	[ 66,  76)    0    0.0%  100.0%  
-	[ 76,  88)    0    0.0%  100.0%  
-	[ 88, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk___100B-2	     500	  15897395 ns/op	   1.26 MB/s
+	[  1,   2)  4521   90.4%   90.4%  #########
+	[  2,   3)   257    5.1%   95.6%  #
+	[  3,   4)     0    0.0%   95.6%  
+	[  4,   5)     0    0.0%   95.6%  
+	[  5,   6)    66    1.3%   96.9%  
+	[  6,   7)   155    3.1%  100.0%  
+	[  7, inf)     1    0.0%  100.0%  
+Benchmark____1_chunk____1KB	    3000	   2399265 ns/op	   0.83 MB/s
 --- Histogram (unit: ms)
-	Count: 500  Min: 12  Max: 24  Avg: 15.40
+	Count: 3000  Min: 1  Max: 17  Avg: 1.56
 	------------------------------------------------------------
-	[ 12,  13)    5    1.0%    1.0%  
-	[ 13,  14)  226   45.2%   46.2%  #####
-	[ 14,  15)  107   21.4%   67.6%  ##
-	[ 15,  16)   16    3.2%   70.8%  
-	[ 16,  17)    0    0.0%   70.8%  
-	[ 17,  19)   12    2.4%   73.2%  
-	[ 19,  21)   92   18.4%   91.6%  ##
-	[ 21,  24)   35    7.0%   98.6%  #
-	[ 24,  27)    7    1.4%  100.0%  
-	[ 27,  31)    0    0.0%  100.0%  
-	[ 31,  36)    0    0.0%  100.0%  
-	[ 36,  42)    0    0.0%  100.0%  
-	[ 42, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk____1KB	     200	  30390593 ns/op	   6.58 MB/s
+	[  1,   2)  2695   89.8%   89.8%  #########
+	[  2,   3)   146    4.9%   94.7%  
+	[  3,   4)     3    0.1%   94.8%  
+	[  4,   5)     1    0.0%   94.8%  
+	[  5,   7)    42    1.4%   96.2%  
+	[  7,   9)     0    0.0%   96.2%  
+	[  9,  12)    43    1.4%   97.7%  
+	[ 12,  15)    42    1.4%   99.1%  
+	[ 15,  19)    28    0.9%  100.0%  
+	[ 19,  24)     0    0.0%  100.0%  
+	[ 24,  30)     0    0.0%  100.0%  
+	[ 30,  37)     0    0.0%  100.0%  
+	[ 37,  46)     0    0.0%  100.0%  
+	[ 46,  57)     0    0.0%  100.0%  
+	[ 57,  70)     0    0.0%  100.0%  
+	[ 70,  86)     0    0.0%  100.0%  
+	[ 86, inf)     0    0.0%  100.0%  
+Benchmark____1_chunk____1KB-2	    5000	   2143186 ns/op	   0.93 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 25  Max: 41  Avg: 29.77
+	Count: 5000  Min: 1  Max: 12  Avg: 1.47
 	------------------------------------------------------------
-	[ 25,  26)   68   34.0%   34.0%  ###
-	[ 26,  27)   26   13.0%   47.0%  #
-	[ 27,  28)    8    4.0%   51.0%  
-	[ 28,  29)    9    4.5%   55.5%  
-	[ 29,  31)   18    9.0%   64.5%  #
-	[ 31,  33)    1    0.5%   65.0%  
-	[ 33,  36)   24   12.0%   77.0%  #
-	[ 36,  39)   39   19.5%   96.5%  ##
-	[ 39,  43)    7    3.5%  100.0%  
-	[ 43,  48)    0    0.0%  100.0%  
-	[ 48,  54)    0    0.0%  100.0%  
-	[ 54,  61)    0    0.0%  100.0%  
-	[ 61,  70)    0    0.0%  100.0%  
-	[ 70,  81)    0    0.0%  100.0%  
-	[ 81,  94)    0    0.0%  100.0%  
-	[ 94, 110)    0    0.0%  100.0%  
-	[110, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk____1KB-2	     500	  17949156 ns/op	  11.14 MB/s
+	[  1,   2)  3732   74.6%   74.6%  #######
+	[  2,   3)  1100   22.0%   96.6%  ##
+	[  3,   4)     0    0.0%   96.6%  
+	[  4,   5)     0    0.0%   96.6%  
+	[  5,   6)     0    0.0%   96.6%  
+	[  6,   8)    52    1.0%   97.7%  
+	[  8,  10)    62    1.2%   98.9%  
+	[ 10,  13)    54    1.1%  100.0%  
+	[ 13,  16)     0    0.0%  100.0%  
+	[ 16,  20)     0    0.0%  100.0%  
+	[ 20,  24)     0    0.0%  100.0%  
+	[ 24, inf)     0    0.0%  100.0%  
+Benchmark____1_chunk___10KB	    3000	   2829279 ns/op	   7.07 MB/s
 --- Histogram (unit: ms)
-	Count: 500  Min: 14  Max: 26  Avg: 17.41
+	Count: 3000  Min: 1  Max: 26  Avg: 2.72
 	------------------------------------------------------------
-	[ 14,  15)  120   24.0%   24.0%  ##
-	[ 15,  16)  169   33.8%   57.8%  ###
-	[ 16,  17)   28    5.6%   63.4%  #
-	[ 17,  18)    6    1.2%   64.6%  
-	[ 18,  19)    2    0.4%   65.0%  
-	[ 19,  21)   19    3.8%   68.8%  
-	[ 21,  23)   87   17.4%   86.2%  ##
-	[ 23,  26)   66   13.2%   99.4%  #
-	[ 26,  29)    3    0.6%  100.0%  
-	[ 29,  33)    0    0.0%  100.0%  
-	[ 33,  38)    0    0.0%  100.0%  
-	[ 38,  44)    0    0.0%  100.0%  
-	[ 44, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk___10KB	     100	  51722516 ns/op	  38.67 MB/s
+	[  1,   2)     2    0.1%    0.1%  
+	[  2,   3)  2859   95.3%   95.4%  ##########
+	[  3,   4)     0    0.0%   95.4%  
+	[  4,   5)     0    0.0%   95.4%  
+	[  5,   7)     0    0.0%   95.4%  
+	[  7,   9)    27    0.9%   96.3%  
+	[  9,  12)     5    0.2%   96.4%  
+	[ 12,  16)     5    0.2%   96.6%  
+	[ 16,  21)    37    1.2%   97.8%  
+	[ 21,  27)    65    2.2%  100.0%  
+	[ 27,  35)     0    0.0%  100.0%  
+	[ 35,  45)     0    0.0%  100.0%  
+	[ 45,  58)     0    0.0%  100.0%  
+	[ 58,  74)     0    0.0%  100.0%  
+	[ 74,  94)     0    0.0%  100.0%  
+	[ 94, 118)     0    0.0%  100.0%  
+	[118, inf)     0    0.0%  100.0%  
+Benchmark____1_chunk___10KB-2	    3000	   2402468 ns/op	   8.32 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 42  Max: 57  Avg: 51.22
+	Count: 3000  Min: 1  Max: 13  Avg: 2.00
 	------------------------------------------------------------
-	[ 42,  43)    1    1.0%    1.0%  
-	[ 43,  44)    0    0.0%    1.0%  
-	[ 44,  45)   14   14.0%   15.0%  #
-	[ 45,  46)    1    1.0%   16.0%  
-	[ 46,  48)    2    2.0%   18.0%  
-	[ 48,  50)    0    0.0%   18.0%  
-	[ 50,  52)   17   17.0%   35.0%  ##
-	[ 52,  55)   58   58.0%   93.0%  ######
-	[ 55,  59)    7    7.0%  100.0%  #
-	[ 59,  64)    0    0.0%  100.0%  
-	[ 64,  70)    0    0.0%  100.0%  
-	[ 70,  77)    0    0.0%  100.0%  
-	[ 77,  85)    0    0.0%  100.0%  
-	[ 85,  95)    0    0.0%  100.0%  
-	[ 95, 107)    0    0.0%  100.0%  
-	[107, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk___10KB-2	     300	  28968863 ns/op	  69.04 MB/s
+	[  1,   2)   879   29.3%   29.3%  ###
+	[  2,   3)  2021   67.4%   96.7%  #######
+	[  3,   4)     0    0.0%   96.7%  
+	[  4,   5)     0    0.0%   96.7%  
+	[  5,   6)     0    0.0%   96.7%  
+	[  6,   8)     0    0.0%   96.7%  
+	[  8,  10)    24    0.8%   97.5%  
+	[ 10,  13)    49    1.6%   99.1%  
+	[ 13,  16)    27    0.9%  100.0%  
+	[ 16,  20)     0    0.0%  100.0%  
+	[ 20,  25)     0    0.0%  100.0%  
+	[ 25,  31)     0    0.0%  100.0%  
+	[ 31, inf)     0    0.0%  100.0%  
+Benchmark____1_chunk__100KB	    2000	   5417885 ns/op	  36.91 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 22  Max: 34  Avg: 28.47
+	Count: 2000  Min: 3  Max: 29  Avg: 4.65
 	------------------------------------------------------------
-	[ 22,  23)   30   10.0%   10.0%  #
-	[ 23,  24)   18    6.0%   16.0%  #
-	[ 24,  25)    6    2.0%   18.0%  
-	[ 25,  26)    0    0.0%   18.0%  
-	[ 26,  27)    0    0.0%   18.0%  
-	[ 27,  29)   63   21.0%   39.0%  ##
-	[ 29,  31)  102   34.0%   73.0%  ###
-	[ 31,  34)   77   25.7%   98.7%  ###
-	[ 34,  37)    4    1.3%  100.0%  
-	[ 37,  41)    0    0.0%  100.0%  
-	[ 41,  46)    0    0.0%  100.0%  
-	[ 46,  52)    0    0.0%  100.0%  
-	[ 52, inf)    0    0.0%  100.0%  
-Benchmark__100_chunk__100KB	      30	 251752470 ns/op	  79.44 MB/s
+	[  3,   4)  1730   86.5%   86.5%  #########
+	[  4,   5)    54    2.7%   89.2%  
+	[  5,   6)     0    0.0%   89.2%  
+	[  6,   7)     0    0.0%   89.2%  
+	[  7,   9)    27    1.4%   90.6%  
+	[  9,  11)    45    2.2%   92.8%  
+	[ 11,  14)     0    0.0%   92.8%  
+	[ 14,  18)     0    0.0%   92.8%  
+	[ 18,  23)    69    3.5%   96.2%  
+	[ 23,  30)    75    3.8%  100.0%  
+	[ 30,  38)     0    0.0%  100.0%  
+	[ 38,  48)     0    0.0%  100.0%  
+	[ 48,  61)     0    0.0%  100.0%  
+	[ 61,  77)     0    0.0%  100.0%  
+	[ 77,  97)     0    0.0%  100.0%  
+	[ 97, 122)     0    0.0%  100.0%  
+	[122, inf)     0    0.0%  100.0%  
+Benchmark____1_chunk__100KB-2	    2000	   3784105 ns/op	  52.85 MB/s
 --- Histogram (unit: ms)
-	Count: 30  Min: 243  Max: 257  Avg: 251.23
+	Count: 2000  Min: 2  Max: 20  Avg: 3.10
 	------------------------------------------------------------
-	[243, 244)   5   16.7%   16.7%  ##
-	[244, 245)   1    3.3%   20.0%  
-	[245, 246)   4   13.3%   33.3%  #
-	[246, 247)   0    0.0%   33.3%  
-	[247, 249)   0    0.0%   33.3%  
-	[249, 251)   0    0.0%   33.3%  
-	[251, 253)   0    0.0%   33.3%  
-	[253, 256)  14   46.7%   80.0%  #####
-	[256, 260)   6   20.0%  100.0%  ##
-	[260, 264)   0    0.0%  100.0%  
-	[264, 269)   0    0.0%  100.0%  
-	[269, 275)   0    0.0%  100.0%  
-	[275, 283)   0    0.0%  100.0%  
-	[283, 292)   0    0.0%  100.0%  
-	[292, inf)   0    0.0%  100.0%  
-Benchmark__100_chunk__100KB-2	      50	 131868524 ns/op	 151.67 MB/s
+	[  2,   3)  1356   67.8%   67.8%  #######
+	[  3,   4)   448   22.4%   90.2%  ##
+	[  4,   5)    57    2.9%   93.1%  
+	[  5,   6)     0    0.0%   93.1%  
+	[  6,   8)     0    0.0%   93.1%  
+	[  8,  10)     0    0.0%   93.1%  
+	[ 10,  13)    55    2.8%   95.8%  
+	[ 13,  16)    59    3.0%   98.8%  
+	[ 16,  20)    24    1.2%  100.0%  
+	[ 20,  25)     1    0.1%  100.0%  
+	[ 25,  31)     0    0.0%  100.0%  
+	[ 31,  39)     0    0.0%  100.0%  
+	[ 39,  49)     0    0.0%  100.0%  
+	[ 49,  61)     0    0.0%  100.0%  
+	[ 61,  75)     0    0.0%  100.0%  
+	[ 75,  92)     0    0.0%  100.0%  
+	[ 92, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk_____1B	    2000	   3738398 ns/op	   0.01 MB/s
 --- Histogram (unit: ms)
-	Count: 50  Min: 127  Max: 137  Avg: 131.44
+	Count: 2000  Min: 2  Max: 30  Avg: 3.18
 	------------------------------------------------------------
-	[127, 128)   3    6.0%    6.0%  #
-	[128, 129)  13   26.0%   32.0%  ###
-	[129, 130)   9   18.0%   50.0%  ##
-	[130, 131)   1    2.0%   52.0%  
-	[131, 132)   1    2.0%   54.0%  
-	[132, 134)   2    4.0%   58.0%  
-	[134, 136)  14   28.0%   86.0%  ###
-	[136, 138)   7   14.0%  100.0%  #
-	[138, 141)   0    0.0%  100.0%  
-	[141, 144)   0    0.0%  100.0%  
-	[144, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk_____1B	      50	 147894706 ns/op	   0.01 MB/s
+	[  2,   3)  1091   54.6%   54.6%  #####
+	[  3,   4)   828   41.4%   96.0%  ####
+	[  4,   5)     0    0.0%   96.0%  
+	[  5,   6)     0    0.0%   96.0%  
+	[  6,   8)     1    0.1%   96.0%  
+	[  8,  11)     0    0.0%   96.0%  
+	[ 11,  14)    19    1.0%   97.0%  
+	[ 14,  18)     0    0.0%   97.0%  
+	[ 18,  23)    19    1.0%   97.9%  
+	[ 23,  30)    41    2.1%  100.0%  
+	[ 30,  39)     1    0.1%  100.0%  
+	[ 39,  50)     0    0.0%  100.0%  
+	[ 50,  64)     0    0.0%  100.0%  
+	[ 64,  81)     0    0.0%  100.0%  
+	[ 81, 103)     0    0.0%  100.0%  
+	[103, 130)     0    0.0%  100.0%  
+	[130, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk_____1B-2	    3000	   2838899 ns/op	   0.01 MB/s
 --- Histogram (unit: ms)
-	Count: 50  Min: 123  Max: 195  Avg: 147.42
+	Count: 3000  Min: 2  Max: 17  Avg: 2.42
+	------------------------------------------------------------
+	[  2,   3)  2705   90.2%   90.2%  #########
+	[  3,   4)   206    6.9%   97.0%  #
+	[  4,   5)     1    0.0%   97.1%  
+	[  5,   6)     0    0.0%   97.1%  
+	[  6,   8)     0    0.0%   97.1%  
+	[  8,  10)     0    0.0%   97.1%  
+	[ 10,  12)     4    0.1%   97.2%  
+	[ 12,  15)    43    1.4%   98.6%  
+	[ 15,  19)    41    1.4%  100.0%  
+	[ 19,  24)     0    0.0%  100.0%  
+	[ 24,  30)     0    0.0%  100.0%  
+	[ 30,  37)     0    0.0%  100.0%  
+	[ 37,  45)     0    0.0%  100.0%  
+	[ 45,  55)     0    0.0%  100.0%  
+	[ 55,  67)     0    0.0%  100.0%  
+	[ 67, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk____10B	    2000	   3750396 ns/op	   0.05 MB/s
+--- Histogram (unit: ms)
+	Count: 2000  Min: 2  Max: 31  Avg: 3.15
+	------------------------------------------------------------
+	[  2,   3)  1179   59.0%   59.0%  ######
+	[  3,   4)   747   37.4%   96.3%  ####
+	[  4,   5)     0    0.0%   96.3%  
+	[  5,   6)     0    0.0%   96.3%  
+	[  6,   8)     0    0.0%   96.3%  
+	[  8,  11)     0    0.0%   96.3%  
+	[ 11,  14)    18    0.9%   97.2%  
+	[ 14,  18)     0    0.0%   97.2%  
+	[ 18,  24)    19    1.0%   98.2%  
+	[ 24,  31)    32    1.6%   99.8%  
+	[ 31,  40)     5    0.2%  100.0%  
+	[ 40,  51)     0    0.0%  100.0%  
+	[ 51,  65)     0    0.0%  100.0%  
+	[ 65,  83)     0    0.0%  100.0%  
+	[ 83, 106)     0    0.0%  100.0%  
+	[106, 134)     0    0.0%  100.0%  
+	[134, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk____10B-2	    3000	   2669872 ns/op	   0.07 MB/s
+--- Histogram (unit: ms)
+	Count: 3000  Min: 2  Max: 14  Avg: 2.37
+	------------------------------------------------------------
+	[  2,   3)  2712   90.4%   90.4%  #########
+	[  3,   4)   208    6.9%   97.3%  #
+	[  4,   5)     0    0.0%   97.3%  
+	[  5,   6)     0    0.0%   97.3%  
+	[  6,   7)     0    0.0%   97.3%  
+	[  7,   9)     0    0.0%   97.3%  
+	[  9,  11)     0    0.0%   97.3%  
+	[ 11,  14)    52    1.7%   99.1%  
+	[ 14,  17)    28    0.9%  100.0%  
+	[ 17,  21)     0    0.0%  100.0%  
+	[ 21,  26)     0    0.0%  100.0%  
+	[ 26,  32)     0    0.0%  100.0%  
+	[ 32, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk___100B	    2000	   3830903 ns/op	   0.52 MB/s
+--- Histogram (unit: ms)
+	Count: 2000  Min: 2  Max: 43  Avg: 3.34
+	------------------------------------------------------------
+	[  2,   3)   880   44.0%   44.0%  ####
+	[  3,   4)  1052   52.6%   96.6%  #####
+	[  4,   5)     3    0.2%   96.8%  
+	[  5,   7)     0    0.0%   96.8%  
+	[  7,   9)     0    0.0%   96.8%  
+	[  9,  12)     0    0.0%   96.8%  
+	[ 12,  16)    17    0.9%   97.6%  
+	[ 16,  21)     0    0.0%   97.6%  
+	[ 21,  28)    17    0.9%   98.5%  
+	[ 28,  37)    27    1.4%   99.8%  
+	[ 37,  48)     4    0.2%  100.0%  
+	[ 48,  63)     0    0.0%  100.0%  
+	[ 63,  82)     0    0.0%  100.0%  
+	[ 82, 106)     0    0.0%  100.0%  
+	[106, 138)     0    0.0%  100.0%  
+	[138, 178)     0    0.0%  100.0%  
+	[178, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk___100B-2	    3000	   2793961 ns/op	   0.72 MB/s
+--- Histogram (unit: ms)
+	Count: 3000  Min: 2  Max: 21  Avg: 2.41
+	------------------------------------------------------------
+	[  2,   3)  2717   90.6%   90.6%  #########
+	[  3,   4)   211    7.0%   97.6%  #
+	[  4,   5)     0    0.0%   97.6%  
+	[  5,   6)     0    0.0%   97.6%  
+	[  6,   8)     0    0.0%   97.6%  
+	[  8,  10)     0    0.0%   97.6%  
+	[ 10,  13)     0    0.0%   97.6%  
+	[ 13,  16)    48    1.6%   99.2%  
+	[ 16,  20)    11    0.4%   99.6%  
+	[ 20,  25)    13    0.4%  100.0%  
+	[ 25,  32)     0    0.0%  100.0%  
+	[ 32,  40)     0    0.0%  100.0%  
+	[ 40,  50)     0    0.0%  100.0%  
+	[ 50,  62)     0    0.0%  100.0%  
+	[ 62,  77)     0    0.0%  100.0%  
+	[ 77,  95)     0    0.0%  100.0%  
+	[ 95, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk____1KB	    2000	   4349817 ns/op	   4.60 MB/s
+--- Histogram (unit: ms)
+	Count: 2000  Min: 3  Max: 48  Avg: 4.07
+	------------------------------------------------------------
+	[  3,   4)  1907   95.4%   95.4%  ##########
+	[  4,   5)    11    0.6%   95.9%  
+	[  5,   6)    12    0.6%   96.5%  
+	[  6,   8)     0    0.0%   96.5%  
+	[  8,  10)     0    0.0%   96.5%  
+	[ 10,  13)     0    0.0%   96.5%  
+	[ 13,  17)     0    0.0%   96.5%  
+	[ 17,  22)    21    1.1%   97.6%  
+	[ 22,  29)     0    0.0%   97.6%  
+	[ 29,  38)    21    1.1%   98.6%  
+	[ 38,  50)    28    1.4%  100.0%  
+	[ 50,  66)     0    0.0%  100.0%  
+	[ 66,  87)     0    0.0%  100.0%  
+	[ 87, 114)     0    0.0%  100.0%  
+	[114, 148)     0    0.0%  100.0%  
+	[148, 192)     0    0.0%  100.0%  
+	[192, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk____1KB-2	    2000	   3167146 ns/op	   6.31 MB/s
+--- Histogram (unit: ms)
+	Count: 2000  Min: 2  Max: 22  Avg: 2.53
+	------------------------------------------------------------
+	[  2,   3)  1734   86.7%   86.7%  #########
+	[  3,   4)   210   10.5%   97.2%  #
+	[  4,   5)     7    0.4%   97.6%  
+	[  5,   6)     0    0.0%   97.6%  
+	[  6,   8)     0    0.0%   97.6%  
+	[  8,  10)     0    0.0%   97.6%  
+	[ 10,  13)     0    0.0%   97.6%  
+	[ 13,  17)    13    0.7%   98.2%  
+	[ 17,  21)    17    0.9%   99.1%  
+	[ 21,  27)    19    1.0%  100.0%  
+	[ 27,  34)     0    0.0%  100.0%  
+	[ 34,  42)     0    0.0%  100.0%  
+	[ 42,  52)     0    0.0%  100.0%  
+	[ 52,  65)     0    0.0%  100.0%  
+	[ 65,  81)     0    0.0%  100.0%  
+	[ 81, 100)     0    0.0%  100.0%  
+	[100, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk___10KB	    1000	   6486765 ns/op	  30.83 MB/s
+--- Histogram (unit: ms)
+	Count: 1000  Min: 4  Max: 50  Avg: 5.74
+	------------------------------------------------------------
+	[  4,   5)   821   82.1%   82.1%  ########
+	[  5,   6)   128   12.8%   94.9%  #
+	[  6,   7)     3    0.3%   95.2%  
+	[  7,   9)     1    0.1%   95.3%  
+	[  9,  11)     0    0.0%   95.3%  
+	[ 11,  14)     0    0.0%   95.3%  
+	[ 14,  18)     8    0.8%   96.1%  
+	[ 18,  23)     0    0.0%   96.1%  
+	[ 23,  30)     3    0.3%   96.4%  
+	[ 30,  39)     5    0.5%   96.9%  
+	[ 39,  51)    31    3.1%  100.0%  
+	[ 51,  67)     0    0.0%  100.0%  
+	[ 67,  88)     0    0.0%  100.0%  
+	[ 88, 115)     0    0.0%  100.0%  
+	[115, 150)     0    0.0%  100.0%  
+	[150, 195)     0    0.0%  100.0%  
+	[195, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk___10KB-2	    2000	   4310677 ns/op	  46.40 MB/s
+--- Histogram (unit: ms)
+	Count: 2000  Min: 2  Max: 24  Avg: 3.84
+	------------------------------------------------------------
+	[  2,   3)     3    0.2%    0.2%  
+	[  3,   4)  1762   88.1%   88.2%  #########
+	[  4,   5)    33    1.7%   89.9%  
+	[  5,   6)   124    6.2%   96.1%  #
+	[  6,   8)     0    0.0%   96.1%  
+	[  8,  10)     0    0.0%   96.1%  
+	[ 10,  13)     0    0.0%   96.1%  
+	[ 13,  17)     0    0.0%   96.1%  
+	[ 17,  22)    33    1.7%   97.8%  
+	[ 22,  28)    45    2.2%  100.0%  
+	[ 28,  35)     0    0.0%  100.0%  
+	[ 35,  44)     0    0.0%  100.0%  
+	[ 44,  55)     0    0.0%  100.0%  
+	[ 55,  69)     0    0.0%  100.0%  
+	[ 69,  86)     0    0.0%  100.0%  
+	[ 86, 107)     0    0.0%  100.0%  
+	[107, inf)     0    0.0%  100.0%  
+Benchmark___10_chunk__100KB	     300	  29183306 ns/op	  68.53 MB/s
+--- Histogram (unit: ms)
+	Count: 300  Min: 21  Max: 71  Avg: 28.66
+	------------------------------------------------------------
+	[ 21,  22)  186   62.0%   62.0%  ######
+	[ 22,  23)   31   10.3%   72.3%  #
+	[ 23,  24)    5    1.7%   74.0%  
+	[ 24,  26)    1    0.3%   74.3%  
+	[ 26,  28)    0    0.0%   74.3%  
+	[ 28,  31)   23    7.7%   82.0%  #
+	[ 31,  35)    1    0.3%   82.3%  
+	[ 35,  41)    0    0.0%   82.3%  
+	[ 41,  49)    0    0.0%   82.3%  
+	[ 49,  59)   25    8.3%   90.7%  #
+	[ 59,  72)   28    9.3%  100.0%  #
+	[ 72,  89)    0    0.0%  100.0%  
+	[ 89, 111)    0    0.0%  100.0%  
+	[111, 140)    0    0.0%  100.0%  
+	[140, 178)    0    0.0%  100.0%  
+	[178, 228)    0    0.0%  100.0%  
+	[228, inf)    0    0.0%  100.0%  
+Benchmark___10_chunk__100KB-2	     500	  16030525 ns/op	 124.76 MB/s
+--- Histogram (unit: ms)
+	Count: 500  Min: 11  Max: 38  Avg: 15.56
+	------------------------------------------------------------
+	[ 11,  12)   88   17.6%   17.6%  ##
+	[ 12,  13)  295   59.0%   76.6%  ######
+	[ 13,  14)   14    2.8%   79.4%  
+	[ 14,  15)    1    0.2%   79.6%  
+	[ 15,  17)    6    1.2%   80.8%  
+	[ 17,  20)    9    1.8%   82.6%  
+	[ 20,  23)    0    0.0%   82.6%  
+	[ 23,  27)    0    0.0%   82.6%  
+	[ 27,  32)   37    7.4%   90.0%  #
+	[ 32,  39)   50   10.0%  100.0%  #
+	[ 39,  48)    0    0.0%  100.0%  
+	[ 48,  59)    0    0.0%  100.0%  
+	[ 59,  72)    0    0.0%  100.0%  
+	[ 72,  89)    0    0.0%  100.0%  
+	[ 89, 110)    0    0.0%  100.0%  
+	[110, 137)    0    0.0%  100.0%  
+	[137, inf)    0    0.0%  100.0%  
+
+Benchmark__100_chunk_____1B	     500	  14799281 ns/op	   0.01 MB/s
+--- Histogram (unit: ms)
+	Count: 500  Min: 14  Max: 16  Avg: 14.23
+	------------------------------------------------------------
+	[ 14,  15)  386   77.2%   77.2%  ########
+	[ 15,  16)  113   22.6%   99.8%  ##
+	[ 16, inf)    1    0.2%  100.0%  
+Benchmark__100_chunk_____1B-2	    1000	  10135511 ns/op	   0.02 MB/s
+--- Histogram (unit: ms)
+	Count: 1000  Min: 8  Max: 11  Avg: 9.63
+	------------------------------------------------------------
+	[  8,   9)    11    1.1%    1.1%  
+	[  9,  10)   432   43.2%   44.3%  ####
+	[ 10,  11)   477   47.7%   92.0%  #####
+	[ 11, inf)    80    8.0%  100.0%  #
+Benchmark__100_chunk____10B	     500	  15137229 ns/op	   0.13 MB/s
+--- Histogram (unit: ms)
+	Count: 500  Min: 14  Max: 18  Avg: 14.73
+	------------------------------------------------------------
+	[ 14,  15)  148   29.6%   29.6%  ###
+	[ 15,  16)  339   67.8%   97.4%  #######
+	[ 16,  17)   12    2.4%   99.8%  
+	[ 17,  18)    0    0.0%   99.8%  
+	[ 18, inf)    1    0.2%  100.0%  
+Benchmark__100_chunk____10B-2	    1000	  10731944 ns/op	   0.19 MB/s
+--- Histogram (unit: ms)
+	Count: 1000  Min: 8  Max: 12  Avg: 10.26
+	------------------------------------------------------------
+	[  8,   9)    12    1.2%    1.2%  
+	[  9,  10)   159   15.9%   17.1%  ##
+	[ 10,  11)   421   42.1%   59.2%  ####
+	[ 11,  12)   375   37.5%   96.7%  ####
+	[ 12, inf)    33    3.3%  100.0%  
+Benchmark__100_chunk___100B	     500	  15355974 ns/op	   1.30 MB/s
+--- Histogram (unit: ms)
+	Count: 500  Min: 14  Max: 17  Avg: 14.83
+	------------------------------------------------------------
+	[ 14,  15)  128   25.6%   25.6%  ###
+	[ 15,  16)  330   66.0%   91.6%  #######
+	[ 16,  17)   41    8.2%   99.8%  #
+	[ 17, inf)    1    0.2%  100.0%  
+Benchmark__100_chunk___100B-2	    1000	  10757797 ns/op	   1.86 MB/s
+--- Histogram (unit: ms)
+	Count: 1000  Min: 8  Max: 13  Avg: 10.25
+	------------------------------------------------------------
+	[  8,   9)    32    3.2%    3.2%  
+	[  9,  10)   217   21.7%   24.9%  ##
+	[ 10,  11)   363   36.3%   61.2%  ####
+	[ 11,  12)   253   25.3%   86.5%  ###
+	[ 12,  13)   127   12.7%   99.2%  #
+	[ 13, inf)     8    0.8%  100.0%  
+Benchmark__100_chunk____1KB	     500	  17505005 ns/op	  11.43 MB/s
+--- Histogram (unit: ms)
+	Count: 500  Min: 15  Max: 19  Avg: 17.03
+	------------------------------------------------------------
+	[ 15,  16)   51   10.2%   10.2%  #
+	[ 16,  17)  112   22.4%   32.6%  ##
+	[ 17,  18)  115   23.0%   55.6%  ##
+	[ 18,  19)  216   43.2%   98.8%  ####
+	[ 19, inf)    6    1.2%  100.0%  
+Benchmark__100_chunk____1KB-2	    1000	  11660590 ns/op	  17.15 MB/s
+--- Histogram (unit: ms)
+	Count: 1000  Min: 8  Max: 14  Avg: 11.15
+	------------------------------------------------------------
+	[  8,   9)    11    1.1%    1.1%  
+	[  9,  10)   158   15.8%   16.9%  ##
+	[ 10,  11)   183   18.3%   35.2%  ##
+	[ 11,  12)   270   27.0%   62.2%  ###
+	[ 12,  13)   123   12.3%   74.5%  #
+	[ 13,  14)   206   20.6%   95.1%  ##
+	[ 14, inf)    49    4.9%  100.0%  
+Benchmark__100_chunk___10KB	     200	  37914384 ns/op	  52.75 MB/s
+--- Histogram (unit: ms)
+	Count: 200  Min: 35  Max: 42  Avg: 37.35
+	------------------------------------------------------------
+	[ 35,  36)    9    4.5%    4.5%  
+	[ 36,  37)    4    2.0%    6.5%  
+	[ 37,  38)  120   60.0%   66.5%  ######
+	[ 38,  39)   52   26.0%   92.5%  ###
+	[ 39,  40)    8    4.0%   96.5%  
+	[ 40,  41)    5    2.5%   99.0%  
+	[ 41,  43)    2    1.0%  100.0%  
+	[ 43, inf)    0    0.0%  100.0%  
+Benchmark__100_chunk___10KB-2	     300	  20888999 ns/op	  95.74 MB/s
+--- Histogram (unit: ms)
+	Count: 300  Min: 18  Max: 23  Avg: 20.38
+	------------------------------------------------------------
+	[ 18,  19)   15    5.0%    5.0%  #
+	[ 19,  20)   11    3.7%    8.7%  
+	[ 20,  21)  135   45.0%   53.7%  #####
+	[ 21,  22)  125   41.7%   95.3%  ####
+	[ 22,  23)   13    4.3%   99.7%  
+	[ 23, inf)    1    0.3%  100.0%  
+Benchmark__100_chunk__100KB	      30	 215706680 ns/op	  92.72 MB/s
+--- Histogram (unit: ms)
+	Count: 30  Min: 210  Max: 220  Avg: 215.20
+	------------------------------------------------------------
+	[210, 211)   1    3.3%    3.3%  
+	[211, 212)   2    6.7%   10.0%  #
+	[212, 213)   0    0.0%   10.0%  
+	[213, 214)   9   30.0%   40.0%  ###
+	[214, 215)   4   13.3%   53.3%  #
+	[215, 217)   4   13.3%   66.7%  #
+	[217, 219)   1    3.3%   70.0%  
+	[219, 221)   9   30.0%  100.0%  ###
+	[221, 224)   0    0.0%  100.0%  
+	[224, 227)   0    0.0%  100.0%  
+	[227, inf)   0    0.0%  100.0%  
+Benchmark__100_chunk__100KB-2	     100	 113221561 ns/op	 176.64 MB/s
+--- Histogram (unit: ms)
+	Count: 100  Min: 108  Max: 120  Avg: 112.75
+	------------------------------------------------------------
+	[108, 109)    2    2.0%    2.0%  
+	[109, 110)    7    7.0%    9.0%  #
+	[110, 111)    3    3.0%   12.0%  
+	[111, 112)   16   16.0%   28.0%  ##
+	[112, 113)   20   20.0%   48.0%  ##
+	[113, 115)   29   29.0%   77.0%  ###
+	[115, 117)   20   20.0%   97.0%  ##
+	[117, 120)    2    2.0%   99.0%  
+	[120, 123)    1    1.0%  100.0%  
+	[123, 127)    0    0.0%  100.0%  
+	[127, 132)    0    0.0%  100.0%  
+	[132, 138)    0    0.0%  100.0%  
+	[138, inf)    0    0.0%  100.0%  
+Benchmark___1K_chunk_____1B	      50	 127031961 ns/op	   0.02 MB/s
+--- Histogram (unit: ms)
+	Count: 50  Min: 123  Max: 131  Avg: 126.56
 	------------------------------------------------------------
 	[123, 124)   1    2.0%    2.0%  
-	[124, 125)   0    0.0%    2.0%  
-	[125, 126)   0    0.0%    2.0%  
-	[126, 128)   0    0.0%    2.0%  
-	[128, 131)   0    0.0%    2.0%  
-	[131, 135)   1    2.0%    4.0%  
-	[135, 140)  20   40.0%   44.0%  ####
-	[140, 147)  19   38.0%   82.0%  ####
-	[147, 156)   1    2.0%   84.0%  
-	[156, 169)   0    0.0%   84.0%  
-	[169, 186)   2    4.0%   88.0%  
-	[186, 209)   6   12.0%  100.0%  #
-	[209, 239)   0    0.0%  100.0%  
-	[239, 279)   0    0.0%  100.0%  
-	[279, 333)   0    0.0%  100.0%  
-	[333, 404)   0    0.0%  100.0%  
-	[404, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk_____1B-2	     100	 112701633 ns/op	   0.02 MB/s
+	[124, 125)   1    2.0%    4.0%  
+	[125, 126)  11   22.0%   26.0%  ##
+	[126, 127)  19   38.0%   64.0%  ####
+	[127, 128)   6   12.0%   76.0%  #
+	[128, 130)   8   16.0%   92.0%  ##
+	[130, 132)   4    8.0%  100.0%  #
+	[132, 134)   0    0.0%  100.0%  
+	[134, inf)   0    0.0%  100.0%  
+Benchmark___1K_chunk_____1B-2	     100	  82251965 ns/op	   0.02 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 109  Max: 128  Avg: 112.17
+	Count: 100  Min: 75  Max: 93  Avg: 81.77
 	------------------------------------------------------------
-	[109, 110)    4    4.0%    4.0%  
-	[110, 111)   17   17.0%   21.0%  ##
-	[111, 112)   31   31.0%   52.0%  ###
-	[112, 113)   16   16.0%   68.0%  ##
-	[113, 115)   21   21.0%   89.0%  ##
-	[115, 117)    4    4.0%   93.0%  
-	[117, 120)    5    5.0%   98.0%  #
-	[120, 123)    1    1.0%   99.0%  
-	[123, 127)    0    0.0%   99.0%  
-	[127, 132)    1    1.0%  100.0%  
-	[132, 139)    0    0.0%  100.0%  
-	[139, 147)    0    0.0%  100.0%  
-	[147, 157)    0    0.0%  100.0%  
-	[157, 169)    0    0.0%  100.0%  
-	[169, 184)    0    0.0%  100.0%  
-	[184, 202)    0    0.0%  100.0%  
-	[202, inf)    0    0.0%  100.0%  
-Benchmark___1K_chunk____10B	      30	 210652536 ns/op	   0.09 MB/s
+	[ 75,  76)    3    3.0%    3.0%  
+	[ 76,  77)   10   10.0%   13.0%  #
+	[ 77,  78)    6    6.0%   19.0%  #
+	[ 78,  79)    5    5.0%   24.0%  #
+	[ 79,  81)   17   17.0%   41.0%  ##
+	[ 81,  83)   17   17.0%   58.0%  ##
+	[ 83,  86)   27   27.0%   85.0%  ###
+	[ 86,  89)    6    6.0%   91.0%  #
+	[ 89,  93)    8    8.0%   99.0%  #
+	[ 93,  98)    1    1.0%  100.0%  
+	[ 98, 104)    0    0.0%  100.0%  
+	[104, 112)    0    0.0%  100.0%  
+	[112, 122)    0    0.0%  100.0%  
+	[122, 134)    0    0.0%  100.0%  
+	[134, 148)    0    0.0%  100.0%  
+	[148, 165)    0    0.0%  100.0%  
+	[165, inf)    0    0.0%  100.0%  
+Benchmark___1K_chunk____10B	      50	 126841430 ns/op	   0.16 MB/s
 --- Histogram (unit: ms)
-	Count: 30  Min: 205  Max: 216  Avg: 210.23
+	Count: 50  Min: 121  Max: 130  Avg: 126.34
 	------------------------------------------------------------
-	[205, 206)   1    3.3%    3.3%  
-	[206, 207)   3   10.0%   13.3%  #
-	[207, 208)   4   13.3%   26.7%  #
-	[208, 209)   3   10.0%   36.7%  #
-	[209, 210)   0    0.0%   36.7%  
-	[210, 212)   6   20.0%   56.7%  ##
-	[212, 214)  10   33.3%   90.0%  ###
-	[214, 217)   3   10.0%  100.0%  #
-	[217, 220)   0    0.0%  100.0%  
-	[220, 224)   0    0.0%  100.0%  
-	[224, 228)   0    0.0%  100.0%  
-	[228, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk____10B-2	     100	 121674848 ns/op	   0.16 MB/s
+	[121, 122)   1    2.0%    2.0%  
+	[122, 123)   0    0.0%    2.0%  
+	[123, 124)   1    2.0%    4.0%  
+	[124, 125)   0    0.0%    4.0%  
+	[125, 126)   7   14.0%   18.0%  #
+	[126, 128)  31   62.0%   80.0%  ######
+	[128, 130)   9   18.0%   98.0%  ##
+	[130, 132)   1    2.0%  100.0%  
+	[132, 135)   0    0.0%  100.0%  
+	[135, inf)   0    0.0%  100.0%  
+Benchmark___1K_chunk____10B-2	     100	  80662645 ns/op	   0.25 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 113  Max: 132  Avg: 121.15
+	Count: 100  Min: 73  Max: 93  Avg: 80.11
 	------------------------------------------------------------
-	[113, 114)    4    4.0%    4.0%  
-	[114, 115)    9    9.0%   13.0%  #
-	[115, 116)    5    5.0%   18.0%  #
-	[116, 117)    3    3.0%   21.0%  
-	[117, 119)    7    7.0%   28.0%  #
-	[119, 121)   14   14.0%   42.0%  #
-	[121, 124)   24   24.0%   66.0%  ##
-	[124, 127)   25   25.0%   91.0%  ###
-	[127, 131)    8    8.0%   99.0%  #
-	[131, 136)    1    1.0%  100.0%  
-	[136, 143)    0    0.0%  100.0%  
-	[143, 151)    0    0.0%  100.0%  
-	[151, 161)    0    0.0%  100.0%  
-	[161, 173)    0    0.0%  100.0%  
-	[173, 188)    0    0.0%  100.0%  
-	[188, 206)    0    0.0%  100.0%  
-	[206, inf)    0    0.0%  100.0%  
-Benchmark___1K_chunk___100B	      30	 238543410 ns/op	   0.84 MB/s
+	[ 73,  74)    2    2.0%    2.0%  
+	[ 74,  75)    3    3.0%    5.0%  
+	[ 75,  76)   10   10.0%   15.0%  #
+	[ 76,  77)   12   12.0%   27.0%  #
+	[ 77,  79)   19   19.0%   46.0%  ##
+	[ 79,  81)   13   13.0%   59.0%  #
+	[ 81,  84)   20   20.0%   79.0%  ##
+	[ 84,  88)   12   12.0%   91.0%  #
+	[ 88,  92)    6    6.0%   97.0%  #
+	[ 92,  98)    3    3.0%  100.0%  
+	[ 98, 105)    0    0.0%  100.0%  
+	[105, 113)    0    0.0%  100.0%  
+	[113, 123)    0    0.0%  100.0%  
+	[123, 136)    0    0.0%  100.0%  
+	[136, 152)    0    0.0%  100.0%  
+	[152, 171)    0    0.0%  100.0%  
+	[171, inf)    0    0.0%  100.0%  
+Benchmark___1K_chunk___100B	      50	 130500666 ns/op	   1.53 MB/s
 --- Histogram (unit: ms)
-	Count: 30  Min: 230  Max: 250  Avg: 238.03
+	Count: 50  Min: 125  Max: 141  Avg: 129.98
 	------------------------------------------------------------
-	[230, 231)   3   10.0%   10.0%  #
-	[231, 232)   0    0.0%   10.0%  
-	[232, 233)   1    3.3%   13.3%  
-	[233, 234)   2    6.7%   20.0%  #
-	[234, 236)   5   16.7%   36.7%  ##
-	[236, 238)   4   13.3%   50.0%  #
-	[238, 241)   5   16.7%   66.7%  ##
-	[241, 245)   7   23.3%   90.0%  ##
-	[245, 249)   2    6.7%   96.7%  #
-	[249, 255)   1    3.3%  100.0%  
-	[255, 262)   0    0.0%  100.0%  
-	[262, 270)   0    0.0%  100.0%  
-	[270, 280)   0    0.0%  100.0%  
-	[280, 293)   0    0.0%  100.0%  
-	[293, 309)   0    0.0%  100.0%  
-	[309, 328)   0    0.0%  100.0%  
-	[328, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk___100B-2	      50	 138412318 ns/op	   1.44 MB/s
+	[125, 126)   1    2.0%    2.0%  
+	[126, 127)   1    2.0%    4.0%  
+	[127, 128)   1    2.0%    6.0%  
+	[128, 129)   6   12.0%   18.0%  #
+	[129, 131)  27   54.0%   72.0%  #####
+	[131, 133)   8   16.0%   88.0%  ##
+	[133, 136)   4    8.0%   96.0%  #
+	[136, 139)   1    2.0%   98.0%  
+	[139, 143)   1    2.0%  100.0%  
+	[143, 148)   0    0.0%  100.0%  
+	[148, 154)   0    0.0%  100.0%  
+	[154, 161)   0    0.0%  100.0%  
+	[161, 170)   0    0.0%  100.0%  
+	[170, 181)   0    0.0%  100.0%  
+	[181, 194)   0    0.0%  100.0%  
+	[194, 210)   0    0.0%  100.0%  
+	[210, inf)   0    0.0%  100.0%  
+Benchmark___1K_chunk___100B-2	     100	  82993437 ns/op	   2.41 MB/s
 --- Histogram (unit: ms)
-	Count: 50  Min: 126  Max: 149  Avg: 137.94
+	Count: 100  Min: 72  Max: 93  Avg: 82.49
 	------------------------------------------------------------
-	[126, 127)   1    2.0%    2.0%  
-	[127, 128)   0    0.0%    2.0%  
-	[128, 129)   0    0.0%    2.0%  
-	[129, 130)   0    0.0%    2.0%  
-	[130, 132)   3    6.0%    8.0%  #
-	[132, 134)   6   12.0%   20.0%  #
-	[134, 137)  11   22.0%   42.0%  ##
-	[137, 141)  12   24.0%   66.0%  ##
-	[141, 146)  14   28.0%   94.0%  ###
-	[146, 152)   3    6.0%  100.0%  #
-	[152, 160)   0    0.0%  100.0%  
-	[160, 169)   0    0.0%  100.0%  
-	[169, 181)   0    0.0%  100.0%  
-	[181, 196)   0    0.0%  100.0%  
-	[196, 214)   0    0.0%  100.0%  
-	[214, 236)   0    0.0%  100.0%  
-	[236, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk____1KB	      30	 276508870 ns/op	   7.23 MB/s
+	[ 72,  73)    1    1.0%    1.0%  
+	[ 73,  74)    0    0.0%    1.0%  
+	[ 74,  75)    0    0.0%    1.0%  
+	[ 75,  76)    1    1.0%    2.0%  
+	[ 76,  78)   10   10.0%   12.0%  #
+	[ 78,  80)   14   14.0%   26.0%  #
+	[ 80,  83)   15   15.0%   41.0%  ##
+	[ 83,  87)   48   48.0%   89.0%  #####
+	[ 87,  92)    7    7.0%   96.0%  #
+	[ 92,  98)    4    4.0%  100.0%  
+	[ 98, 105)    0    0.0%  100.0%  
+	[105, 114)    0    0.0%  100.0%  
+	[114, 125)    0    0.0%  100.0%  
+	[125, 138)    0    0.0%  100.0%  
+	[138, 155)    0    0.0%  100.0%  
+	[155, 175)    0    0.0%  100.0%  
+	[175, inf)    0    0.0%  100.0%  
+Benchmark___1K_chunk____1KB	      50	 152120390 ns/op	  13.15 MB/s
 --- Histogram (unit: ms)
-	Count: 30  Min: 264  Max: 299  Avg: 275.97
+	Count: 50  Min: 145  Max: 161  Avg: 151.72
 	------------------------------------------------------------
-	[264, 265)   1    3.3%    3.3%  
-	[265, 266)   0    0.0%    3.3%  
-	[266, 267)   1    3.3%    6.7%  
-	[267, 269)   3   10.0%   16.7%  #
-	[269, 271)   5   16.7%   33.3%  ##
-	[271, 274)   7   23.3%   56.7%  ##
-	[274, 278)   2    6.7%   63.3%  #
-	[278, 283)   7   23.3%   86.7%  ##
-	[283, 289)   1    3.3%   90.0%  
-	[289, 297)   1    3.3%   93.3%  
-	[297, 307)   2    6.7%  100.0%  #
-	[307, 320)   0    0.0%  100.0%  
-	[320, 337)   0    0.0%  100.0%  
-	[337, 358)   0    0.0%  100.0%  
-	[358, 385)   0    0.0%  100.0%  
-	[385, 419)   0    0.0%  100.0%  
-	[419, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk____1KB-2	      50	 156292302 ns/op	  12.80 MB/s
---- Histogram (unit: ms)
-	Count: 50  Min: 144  Max: 169  Avg: 155.82
-	------------------------------------------------------------
-	[144, 145)   1    2.0%    2.0%  
-	[145, 146)   0    0.0%    2.0%  
+	[145, 146)   1    2.0%    2.0%  
 	[146, 147)   1    2.0%    4.0%  
-	[147, 148)   0    0.0%    4.0%  
-	[148, 150)   3    6.0%   10.0%  #
-	[150, 152)   5   10.0%   20.0%  #
-	[152, 155)  14   28.0%   48.0%  ###
-	[155, 159)  12   24.0%   72.0%  ##
-	[159, 164)   8   16.0%   88.0%  ##
-	[164, 170)   6   12.0%  100.0%  #
-	[170, 178)   0    0.0%  100.0%  
-	[178, 188)   0    0.0%  100.0%  
-	[188, 201)   0    0.0%  100.0%  
-	[201, 217)   0    0.0%  100.0%  
-	[217, 237)   0    0.0%  100.0%  
-	[237, 261)   0    0.0%  100.0%  
-	[261, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk___10KB	      20	 468904636 ns/op	  42.65 MB/s
+	[147, 148)   1    2.0%    6.0%  
+	[148, 149)   2    4.0%   10.0%  
+	[149, 151)  17   34.0%   44.0%  ###
+	[151, 153)   8   16.0%   60.0%  ##
+	[153, 156)  16   32.0%   92.0%  ###
+	[156, 159)   2    4.0%   96.0%  
+	[159, 163)   2    4.0%  100.0%  
+	[163, 168)   0    0.0%  100.0%  
+	[168, 174)   0    0.0%  100.0%  
+	[174, 181)   0    0.0%  100.0%  
+	[181, 190)   0    0.0%  100.0%  
+	[190, 201)   0    0.0%  100.0%  
+	[201, 214)   0    0.0%  100.0%  
+	[214, 230)   0    0.0%  100.0%  
+	[230, inf)   0    0.0%  100.0%  
+Benchmark___1K_chunk____1KB-2	     100	  91860277 ns/op	  21.77 MB/s
 --- Histogram (unit: ms)
-	Count: 20  Min: 458  Max: 491  Avg: 468.40
+	Count: 100  Min: 80  Max: 106  Avg: 91.33
 	------------------------------------------------------------
-	[458, 459)   2   10.0%   10.0%  #
-	[459, 460)   2   10.0%   20.0%  #
-	[460, 461)   2   10.0%   30.0%  #
-	[461, 463)   1    5.0%   35.0%  #
-	[463, 465)   1    5.0%   40.0%  #
-	[465, 468)   2   10.0%   50.0%  #
-	[468, 472)   2   10.0%   60.0%  #
-	[472, 477)   6   30.0%   90.0%  ###
-	[477, 483)   0    0.0%   90.0%  
-	[483, 491)   1    5.0%   95.0%  #
-	[491, 501)   1    5.0%  100.0%  #
-	[501, 513)   0    0.0%  100.0%  
-	[513, 529)   0    0.0%  100.0%  
-	[529, 549)   0    0.0%  100.0%  
-	[549, 575)   0    0.0%  100.0%  
-	[575, 608)   0    0.0%  100.0%  
-	[608, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk___10KB-2	      30	 263653358 ns/op	  75.86 MB/s
+	[ 80,  81)    2    2.0%    2.0%  
+	[ 81,  82)    2    2.0%    4.0%  
+	[ 82,  83)    3    3.0%    7.0%  
+	[ 83,  84)    4    4.0%   11.0%  
+	[ 84,  86)   10   10.0%   21.0%  #
+	[ 86,  88)   11   11.0%   32.0%  #
+	[ 88,  91)   14   14.0%   46.0%  #
+	[ 91,  95)   19   19.0%   65.0%  ##
+	[ 95, 100)   26   26.0%   91.0%  ###
+	[100, 107)    9    9.0%  100.0%  #
+	[107, 115)    0    0.0%  100.0%  
+	[115, 125)    0    0.0%  100.0%  
+	[125, 138)    0    0.0%  100.0%  
+	[138, 154)    0    0.0%  100.0%  
+	[154, 174)    0    0.0%  100.0%  
+	[174, 199)    0    0.0%  100.0%  
+	[199, inf)    0    0.0%  100.0%  
+Benchmark___1K_chunk___10KB	      20	 337020835 ns/op	  59.34 MB/s
 --- Histogram (unit: ms)
-	Count: 30  Min: 242  Max: 275  Avg: 263.13
+	Count: 20  Min: 331  Max: 342  Avg: 336.50
 	------------------------------------------------------------
-	[242, 243)   2    6.7%    6.7%  #
-	[243, 244)   0    0.0%    6.7%  
-	[244, 245)   0    0.0%    6.7%  
-	[245, 247)   0    0.0%    6.7%  
-	[247, 249)   0    0.0%    6.7%  
-	[249, 252)   0    0.0%    6.7%  
-	[252, 256)   3   10.0%   16.7%  #
-	[256, 261)   5   16.7%   33.3%  ##
-	[261, 267)   8   26.7%   60.0%  ###
-	[267, 275)  11   36.7%   96.7%  ####
-	[275, 285)   1    3.3%  100.0%  
-	[285, 297)   0    0.0%  100.0%  
-	[297, 313)   0    0.0%  100.0%  
-	[313, 333)   0    0.0%  100.0%  
-	[333, 359)   0    0.0%  100.0%  
-	[359, 392)   0    0.0%  100.0%  
-	[392, inf)   0    0.0%  100.0%  
-Benchmark___1K_chunk__100KB	       3	2573103606 ns/op	  77.73 MB/s
+	[331, 332)   1    5.0%    5.0%  #
+	[332, 333)   2   10.0%   15.0%  #
+	[333, 334)   1    5.0%   20.0%  #
+	[334, 335)   3   15.0%   35.0%  ##
+	[335, 336)   2   10.0%   45.0%  #
+	[336, 338)   2   10.0%   55.0%  #
+	[338, 340)   5   25.0%   80.0%  ###
+	[340, 343)   4   20.0%  100.0%  ##
+	[343, 346)   0    0.0%  100.0%  
+	[346, 350)   0    0.0%  100.0%  
+	[350, 354)   0    0.0%  100.0%  
+	[354, inf)   0    0.0%  100.0%  
+Benchmark___1K_chunk___10KB-2	      50	 177497001 ns/op	 112.68 MB/s
+--- Histogram (unit: ms)
+	Count: 50  Min: 172  Max: 183  Avg: 176.96
+	------------------------------------------------------------
+	[172, 173)   4    8.0%    8.0%  #
+	[173, 174)   2    4.0%   12.0%  
+	[174, 175)   8   16.0%   28.0%  ##
+	[175, 176)   4    8.0%   36.0%  #
+	[176, 177)   2    4.0%   40.0%  
+	[177, 179)   9   18.0%   58.0%  ##
+	[179, 181)  18   36.0%   94.0%  ####
+	[181, 184)   3    6.0%  100.0%  #
+	[184, 187)   0    0.0%  100.0%  
+	[187, 191)   0    0.0%  100.0%  
+	[191, 195)   0    0.0%  100.0%  
+	[195, inf)   0    0.0%  100.0%  
+Benchmark___1K_chunk__100KB	       3	2185333858 ns/op	  91.52 MB/s
 --- Histogram (unit: s)
 	Count: 3  Min: 2  Max: 2  Avg: 2.00
 	------------------------------------------------------------
 	[  2, inf)  3  100.0%  100.0%  ##########
-Benchmark___1K_chunk__100KB-2	       5	1337696624 ns/op	 149.51 MB/s
+Benchmark___1K_chunk__100KB-2	       5	1140505127 ns/op	 175.36 MB/s
 --- Histogram (unit: s)
 	Count: 5  Min: 1  Max: 1  Avg: 1.00
 	------------------------------------------------------------
 	[  1, inf)  5  100.0%  100.0%  ##########
 
-Benchmark__per_chunk____1B	   50000	    192129 ns/op	   0.01 MB/s
-Benchmark__per_chunk____1B-2	   50000	    131601 ns/op	   0.02 MB/s
-Benchmark__per_chunk___10B	   20000	    372009 ns/op	   0.05 MB/s
-Benchmark__per_chunk___10B-2	   30000	    222774 ns/op	   0.09 MB/s
-Benchmark__per_chunk__100B	   20000	    434465 ns/op	   0.46 MB/s
-Benchmark__per_chunk__100B-2	   30000	    238245 ns/op	   0.84 MB/s
-Benchmark__per_chunk___1KB	   20000	    464091 ns/op	   4.31 MB/s
-Benchmark__per_chunk___1KB-2	   30000	    253694 ns/op	   7.88 MB/s
-Benchmark__per_chunk__10KB	   10000	    650380 ns/op	  30.75 MB/s
-Benchmark__per_chunk__10KB-2	   20000	    357218 ns/op	  55.99 MB/s
-Benchmark__per_chunk_100KB	    3000	   2728670 ns/op	  73.30 MB/s
-Benchmark__per_chunk_100KB-2	    5000	   1380520 ns/op	 144.87 MB/s
+Benchmark__per_chunk____1B	   50000	    127847 ns/op	   0.02 MB/s
+Benchmark__per_chunk____1B-2	  100000	     81496 ns/op	   0.02 MB/s
+Benchmark__per_chunk___10B	   50000	    125213 ns/op	   0.16 MB/s
+Benchmark__per_chunk___10B-2	  100000	     79532 ns/op	   0.25 MB/s
+Benchmark__per_chunk__100B	   50000	    126242 ns/op	   1.58 MB/s
+Benchmark__per_chunk__100B-2	  100000	     77971 ns/op	   2.57 MB/s
+Benchmark__per_chunk___1KB	   50000	    148314 ns/op	  13.48 MB/s
+Benchmark__per_chunk___1KB-2	  100000	     87787 ns/op	  22.78 MB/s
+Benchmark__per_chunk__10KB	   20000	    323521 ns/op	  61.82 MB/s
+Benchmark__per_chunk__10KB-2	   50000	    172500 ns/op	 115.94 MB/s
+Benchmark__per_chunk_100KB	    3000	   2065561 ns/op	  96.83 MB/s
+Benchmark__per_chunk_100KB-2	   10000	   1062338 ns/op	 188.26 MB/s
 
-Benchmark___10B_mux__100_chunks___10B	     300	  26348223 ns/op	   0.00 MB/s
+Benchmark___10B_mux__100_chunks___10B	     500	  16428840 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 9  Max: 30  Avg: 25.79
+	Count: 500  Min: 8  Max: 18  Avg: 16.03
 	------------------------------------------------------------
-	[  9,  10)   19    6.3%    6.3%  #
-	[ 10,  11)    5    1.7%    8.0%  
-	[ 11,  12)    0    0.0%    8.0%  
-	[ 12,  13)    0    0.0%    8.0%  
-	[ 13,  15)    0    0.0%    8.0%  
-	[ 15,  17)    0    0.0%    8.0%  
-	[ 17,  20)    1    0.3%    8.3%  
-	[ 20,  24)   10    3.3%   11.7%  
-	[ 24,  29)  233   77.7%   89.3%  ########
-	[ 29,  35)   32   10.7%  100.0%  #
-	[ 35,  42)    0    0.0%  100.0%  
-	[ 42,  51)    0    0.0%  100.0%  
-	[ 51,  62)    0    0.0%  100.0%  
-	[ 62,  75)    0    0.0%  100.0%  
-	[ 75,  92)    0    0.0%  100.0%  
-	[ 92, 112)    0    0.0%  100.0%  
-	[112, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks___10B-2	    1000	   9053248 ns/op	   0.00 MB/s
+	[  8,   9)    4    0.8%    0.8%  
+	[  9,  10)    0    0.0%    0.8%  
+	[ 10,  11)    0    0.0%    0.8%  
+	[ 11,  12)    1    0.2%    1.0%  
+	[ 12,  13)    3    0.6%    1.6%  
+	[ 13,  15)    5    1.0%    2.6%  
+	[ 15,  17)  403   80.6%   83.2%  ########
+	[ 17,  19)   84   16.8%  100.0%  ##
+	[ 19,  22)    0    0.0%  100.0%  
+	[ 22,  25)    0    0.0%  100.0%  
+	[ 25, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks___10B-2	    2000	   4039798 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 4  Max: 17  Avg: 8.54
+	Count: 2000  Min: 1  Max: 10  Avg: 3.55
 	------------------------------------------------------------
-	[  4,   5)     3    0.3%    0.3%  
-	[  5,   6)    48    4.8%    5.1%  
-	[  6,   7)   166   16.6%   21.7%  ##
-	[  7,   8)   206   20.6%   42.3%  ##
-	[  8,   9)   179   17.9%   60.2%  ##
-	[  9,  11)   186   18.6%   78.8%  ##
-	[ 11,  13)   111   11.1%   89.9%  #
-	[ 13,  16)    96    9.6%   99.5%  #
-	[ 16,  19)     5    0.5%  100.0%  
-	[ 19,  23)     0    0.0%  100.0%  
-	[ 23,  28)     0    0.0%  100.0%  
-	[ 28,  34)     0    0.0%  100.0%  
-	[ 34,  41)     0    0.0%  100.0%  
-	[ 41, inf)     0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks__100B	     300	  29202434 ns/op	   0.00 MB/s
+	[  1,   2)   104    5.2%    5.2%  #
+	[  2,   3)   588   29.4%   34.6%  ###
+	[  3,   4)   397   19.9%   54.5%  ##
+	[  4,   5)   375   18.8%   73.2%  ##
+	[  5,   6)   278   13.9%   87.1%  #
+	[  6,   8)   208   10.4%   97.5%  #
+	[  8,  10)    48    2.4%   99.9%  
+	[ 10,  12)     2    0.1%  100.0%  
+	[ 12,  15)     0    0.0%  100.0%  
+	[ 15, inf)     0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks__100B	     500	  16959639 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 9  Max: 34  Avg: 28.80
+	Count: 500  Min: 10  Max: 19  Avg: 16.44
 	------------------------------------------------------------
-	[  9,  10)    4    1.3%    1.3%  
-	[ 10,  11)   10    3.3%    4.7%  
-	[ 11,  12)    6    2.0%    6.7%  
-	[ 12,  13)    0    0.0%    6.7%  
-	[ 13,  15)    0    0.0%    6.7%  
-	[ 15,  17)    0    0.0%    6.7%  
-	[ 17,  20)    0    0.0%    6.7%  
-	[ 20,  24)    0    0.0%    6.7%  
-	[ 24,  29)   20    6.7%   13.3%  #
-	[ 29,  35)  260   86.7%  100.0%  #########
-	[ 35,  43)    0    0.0%  100.0%  
-	[ 43,  53)    0    0.0%  100.0%  
-	[ 53,  66)    0    0.0%  100.0%  
-	[ 66,  82)    0    0.0%  100.0%  
-	[ 82, 102)    0    0.0%  100.0%  
-	[102, 126)    0    0.0%  100.0%  
-	[126, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks__100B-2	    1000	  10238260 ns/op	   0.00 MB/s
+	[ 10,  11)    3    0.6%    0.6%  
+	[ 11,  12)    0    0.0%    0.6%  
+	[ 12,  13)    3    0.6%    1.2%  
+	[ 13,  14)    1    0.2%    1.4%  
+	[ 14,  15)   77   15.4%   16.8%  ##
+	[ 15,  17)  122   24.4%   41.2%  ##
+	[ 17,  19)  286   57.2%   98.4%  ######
+	[ 19,  21)    8    1.6%  100.0%  
+	[ 21,  24)    0    0.0%  100.0%  
+	[ 24, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks__100B-2	    2000	   4129118 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 5  Max: 21  Avg: 9.74
+	Count: 2000  Min: 1  Max: 12  Avg: 3.64
 	------------------------------------------------------------
-	[  5,   6)    39    3.9%    3.9%  
-	[  6,   7)   118   11.8%   15.7%  #
-	[  7,   8)   123   12.3%   28.0%  #
-	[  8,   9)   141   14.1%   42.1%  #
-	[  9,  11)   217   21.7%   63.8%  ##
-	[ 11,  13)   152   15.2%   79.0%  ##
-	[ 13,  16)   157   15.7%   94.7%  ##
-	[ 16,  19)    50    5.0%   99.7%  #
-	[ 19,  23)     3    0.3%  100.0%  
-	[ 23,  28)     0    0.0%  100.0%  
-	[ 28,  34)     0    0.0%  100.0%  
-	[ 34,  41)     0    0.0%  100.0%  
-	[ 41,  50)     0    0.0%  100.0%  
-	[ 50,  61)     0    0.0%  100.0%  
-	[ 61,  74)     0    0.0%  100.0%  
-	[ 74,  90)     0    0.0%  100.0%  
-	[ 90, inf)     0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks___1KB	     300	  30121503 ns/op	   0.00 MB/s
+	[  1,   2)    77    3.9%    3.9%  
+	[  2,   3)   693   34.6%   38.5%  ###
+	[  3,   4)   407   20.4%   58.9%  ##
+	[  4,   5)   308   15.4%   74.2%  ##
+	[  5,   6)   182    9.1%   83.4%  #
+	[  6,   8)   213   10.7%   94.0%  #
+	[  8,  10)    91    4.5%   98.6%  
+	[ 10,  13)    29    1.5%  100.0%  
+	[ 13,  16)     0    0.0%  100.0%  
+	[ 16,  20)     0    0.0%  100.0%  
+	[ 20,  24)     0    0.0%  100.0%  
+	[ 24, inf)     0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks___1KB	     500	  19240324 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 9  Max: 38  Avg: 29.57
+	Count: 500  Min: 13  Max: 24  Avg: 18.60
 	------------------------------------------------------------
-	[  9,  10)    7    2.3%    2.3%  
-	[ 10,  11)   13    4.3%    6.7%  
-	[ 11,  12)    5    1.7%    8.3%  
-	[ 12,  13)    3    1.0%    9.3%  
-	[ 13,  15)    3    1.0%   10.3%  
-	[ 15,  18)    0    0.0%   10.3%  
-	[ 18,  21)    0    0.0%   10.3%  
-	[ 21,  25)    0    0.0%   10.3%  
-	[ 25,  31)   33   11.0%   21.3%  #
-	[ 31,  38)  235   78.3%   99.7%  ########
-	[ 38,  47)    1    0.3%  100.0%  
-	[ 47,  58)    0    0.0%  100.0%  
-	[ 58,  72)    0    0.0%  100.0%  
-	[ 72,  90)    0    0.0%  100.0%  
-	[ 90, 113)    0    0.0%  100.0%  
-	[113, 141)    0    0.0%  100.0%  
-	[141, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks___1KB-2	    1000	  11123358 ns/op	   0.00 MB/s
+	[ 13,  14)    1    0.2%    0.2%  
+	[ 14,  15)    0    0.0%    0.2%  
+	[ 15,  16)    0    0.0%    0.2%  
+	[ 16,  17)  152   30.4%   30.6%  ###
+	[ 17,  18)   75   15.0%   45.6%  ##
+	[ 18,  20)   58   11.6%   57.2%  #
+	[ 20,  22)  179   35.8%   93.0%  ####
+	[ 22,  25)   35    7.0%  100.0%  #
+	[ 25,  28)    0    0.0%  100.0%  
+	[ 28,  32)    0    0.0%  100.0%  
+	[ 32,  36)    0    0.0%  100.0%  
+	[ 36, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks___1KB-2	    2000	   4765628 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 4  Max: 22  Avg: 10.61
+	Count: 2000  Min: 1  Max: 15  Avg: 4.29
 	------------------------------------------------------------
-	[  4,   5)    21    2.1%    2.1%  
-	[  5,   6)    66    6.6%    8.7%  #
-	[  6,   7)   110   11.0%   19.7%  #
-	[  7,   8)    88    8.8%   28.5%  #
-	[  8,  10)   175   17.5%   46.0%  ##
-	[ 10,  12)   152   15.2%   61.2%  ##
-	[ 12,  15)   168   16.8%   78.0%  ##
-	[ 15,  18)   150   15.0%   93.0%  ##
-	[ 18,  22)    69    6.9%   99.9%  #
-	[ 22,  27)     1    0.1%  100.0%  
+	[  1,   2)    49    2.5%    2.5%  
+	[  2,   3)   573   28.7%   31.1%  ###
+	[  3,   4)   411   20.6%   51.7%  ##
+	[  4,   5)   262   13.1%   64.8%  #
+	[  5,   7)   369   18.4%   83.2%  ##
+	[  7,   9)   150    7.5%   90.7%  #
+	[  9,  11)    87    4.4%   95.1%  
+	[ 11,  14)    90    4.5%   99.6%  
+	[ 14,  18)     9    0.5%  100.0%  
+	[ 18,  22)     0    0.0%  100.0%  
+	[ 22,  27)     0    0.0%  100.0%  
 	[ 27,  33)     0    0.0%  100.0%  
 	[ 33,  41)     0    0.0%  100.0%  
-	[ 41,  51)     0    0.0%  100.0%  
-	[ 51,  63)     0    0.0%  100.0%  
-	[ 63,  77)     0    0.0%  100.0%  
-	[ 77,  94)     0    0.0%  100.0%  
-	[ 94, inf)     0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks__10KB	     200	  44810613 ns/op	   0.00 MB/s
+	[ 41,  50)     0    0.0%  100.0%  
+	[ 50, inf)     0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks__10KB	     200	  38595003 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 9  Max: 57  Avg: 44.30
+	Count: 200  Min: 8  Max: 43  Avg: 38.09
 	------------------------------------------------------------
-	[  9,  10)    1    0.5%    0.5%  
-	[ 10,  11)    9    4.5%    5.0%  
-	[ 11,  12)    1    0.5%    5.5%  
-	[ 12,  14)   11    5.5%   11.0%  #
-	[ 14,  16)    7    3.5%   14.5%  
-	[ 16,  19)    2    1.0%   15.5%  
-	[ 19,  23)    0    0.0%   15.5%  
-	[ 23,  29)    0    0.0%   15.5%  
-	[ 29,  36)    0    0.0%   15.5%  
-	[ 36,  46)   21   10.5%   26.0%  #
-	[ 46,  59)  148   74.0%  100.0%  #######
-	[ 59,  76)    0    0.0%  100.0%  
-	[ 76,  98)    0    0.0%  100.0%  
-	[ 98, 126)    0    0.0%  100.0%  
-	[126, 163)    0    0.0%  100.0%  
-	[163, 210)    0    0.0%  100.0%  
-	[210, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux__100_chunks__10KB-2	     300	  23793028 ns/op	   0.00 MB/s
+	[  8,   9)    2    1.0%    1.0%  
+	[  9,  10)    0    0.0%    1.0%  
+	[ 10,  11)    0    0.0%    1.0%  
+	[ 11,  13)    0    0.0%    1.0%  
+	[ 13,  15)    0    0.0%    1.0%  
+	[ 15,  18)    0    0.0%    1.0%  
+	[ 18,  22)    0    0.0%    1.0%  
+	[ 22,  27)    0    0.0%    1.0%  
+	[ 27,  33)    2    1.0%    2.0%  
+	[ 33,  41)  125   62.5%   64.5%  ######
+	[ 41,  51)   71   35.5%  100.0%  ####
+	[ 51,  64)    0    0.0%  100.0%  
+	[ 64,  81)    0    0.0%  100.0%  
+	[ 81, 102)    0    0.0%  100.0%  
+	[102, 129)    0    0.0%  100.0%  
+	[129, 163)    0    0.0%  100.0%  
+	[163, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux__100_chunks__10KB-2	     500	  13282699 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 4  Max: 41  Avg: 23.28
+	Count: 500  Min: 1  Max: 27  Avg: 12.81
 	------------------------------------------------------------
-	[  4,   5)    1    0.3%    0.3%  
-	[  5,   6)    3    1.0%    1.3%  
-	[  6,   7)    2    0.7%    2.0%  
-	[  7,   9)    9    3.0%    5.0%  
-	[  9,  11)    9    3.0%    8.0%  
-	[ 11,  14)   21    7.0%   15.0%  #
-	[ 14,  18)   19    6.3%   21.3%  #
-	[ 18,  23)   51   17.0%   38.3%  ##
-	[ 23,  29)  108   36.0%   74.3%  ####
-	[ 29,  37)   70   23.3%   97.7%  ##
-	[ 37,  48)    7    2.3%  100.0%  
-	[ 48,  62)    0    0.0%  100.0%  
-	[ 62,  79)    0    0.0%  100.0%  
-	[ 79, 101)    0    0.0%  100.0%  
-	[101, 130)    0    0.0%  100.0%  
-	[130, 166)    0    0.0%  100.0%  
-	[166, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks___10B	     100	 131543346 ns/op	   0.00 MB/s
+	[  1,   2)   12    2.4%    2.4%  
+	[  2,   3)   87   17.4%   19.8%  ##
+	[  3,   4)   19    3.8%   23.6%  
+	[  4,   5)   19    3.8%   27.4%  
+	[  5,   7)   23    4.6%   32.0%  
+	[  7,   9)   25    5.0%   37.0%  #
+	[  9,  12)   31    6.2%   43.2%  #
+	[ 12,  16)   45    9.0%   52.2%  #
+	[ 16,  21)  130   26.0%   78.2%  ###
+	[ 21,  28)  109   21.8%  100.0%  ##
+	[ 28,  36)    0    0.0%  100.0%  
+	[ 36,  46)    0    0.0%  100.0%  
+	[ 46,  59)    0    0.0%  100.0%  
+	[ 59,  75)    0    0.0%  100.0%  
+	[ 75,  95)    0    0.0%  100.0%  
+	[ 95, 120)    0    0.0%  100.0%  
+	[120, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks___10B	     100	  89458344 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 12  Max: 215  Avg: 131.05
+	Count: 100  Min: 21  Max: 141  Avg: 88.95
 	------------------------------------------------------------
-	[ 12,  13)    1    1.0%    1.0%  
-	[ 13,  14)    0    0.0%    1.0%  
-	[ 14,  16)    0    0.0%    1.0%  
-	[ 16,  18)    0    0.0%    1.0%  
-	[ 18,  22)    2    2.0%    3.0%  
-	[ 22,  27)    0    0.0%    3.0%  
-	[ 27,  35)    2    2.0%    5.0%  
-	[ 35,  46)    0    0.0%    5.0%  
-	[ 46,  63)    3    3.0%    8.0%  
-	[ 63,  87)   18   18.0%   26.0%  ##
-	[ 87, 121)   21   21.0%   47.0%  ##
-	[121, 170)   16   16.0%   63.0%  ##
-	[170, 240)   37   37.0%  100.0%  ####
-	[240, 339)    0    0.0%  100.0%  
-	[339, 481)    0    0.0%  100.0%  
-	[481, 684)    0    0.0%  100.0%  
-	[684, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks___10B-2	     300	  26865810 ns/op	   0.00 MB/s
+	[ 21,  22)    1    1.0%    1.0%  
+	[ 22,  23)    0    0.0%    1.0%  
+	[ 23,  24)    0    0.0%    1.0%  
+	[ 24,  26)    0    0.0%    1.0%  
+	[ 26,  29)    2    2.0%    3.0%  
+	[ 29,  33)    1    1.0%    4.0%  
+	[ 33,  39)    1    1.0%    5.0%  
+	[ 39,  48)    5    5.0%   10.0%  #
+	[ 48,  60)   12   12.0%   22.0%  #
+	[ 60,  77)   18   18.0%   40.0%  ##
+	[ 77, 101)   21   21.0%   61.0%  ##
+	[101, 134)   33   33.0%   94.0%  ###
+	[134, 180)    6    6.0%  100.0%  #
+	[180, 243)    0    0.0%  100.0%  
+	[243, 330)    0    0.0%  100.0%  
+	[330, 449)    0    0.0%  100.0%  
+	[449, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks___10B-2	    2000	   5537208 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 5  Max: 108  Avg: 26.37
+	Count: 2000  Min: 1  Max: 46  Avg: 5.05
 	------------------------------------------------------------
-	[  5,   6)   18    6.0%    6.0%  #
-	[  6,   7)   10    3.3%    9.3%  
-	[  7,   8)   22    7.3%   16.7%  #
-	[  8,  10)   50   16.7%   33.3%  ##
-	[ 10,  13)   62   20.7%   54.0%  ##
-	[ 13,  17)   43   14.3%   68.3%  #
-	[ 17,  23)   21    7.0%   75.3%  #
-	[ 23,  31)    5    1.7%   77.0%  
-	[ 31,  42)    5    1.7%   78.7%  
-	[ 42,  58)    4    1.3%   80.0%  
-	[ 58,  79)   19    6.3%   86.3%  #
-	[ 79, 108)   40   13.3%   99.7%  #
-	[108, 148)    1    0.3%  100.0%  
-	[148, 203)    0    0.0%  100.0%  
-	[203, 278)    0    0.0%  100.0%  
-	[278, 380)    0    0.0%  100.0%  
-	[380, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks__100B	      50	 160157465 ns/op	   0.00 MB/s
+	[  1,   2)    36    1.8%    1.8%  
+	[  2,   3)   785   39.2%   41.1%  ####
+	[  3,   4)   580   29.0%   70.0%  ###
+	[  4,   6)   266   13.3%   83.4%  #
+	[  6,   8)    59    3.0%   86.3%  
+	[  8,  11)    48    2.4%   88.7%  
+	[ 11,  15)    76    3.8%   92.5%  
+	[ 15,  20)    37    1.9%   94.4%  
+	[ 20,  27)    54    2.7%   97.1%  
+	[ 27,  36)    36    1.8%   98.9%  
+	[ 36,  48)    23    1.2%  100.0%  
+	[ 48,  64)     0    0.0%  100.0%  
+	[ 64,  85)     0    0.0%  100.0%  
+	[ 85, 112)     0    0.0%  100.0%  
+	[112, 146)     0    0.0%  100.0%  
+	[146, 190)     0    0.0%  100.0%  
+	[190, inf)     0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks__100B	     100	  95560922 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 50  Min: 73  Max: 233  Avg: 159.76
+	Count: 100  Min: 4  Max: 154  Avg: 95.10
 	------------------------------------------------------------
-	[ 73,  74)   1    2.0%    2.0%  
-	[ 74,  75)   0    0.0%    2.0%  
-	[ 75,  76)   0    0.0%    2.0%  
-	[ 76,  78)   0    0.0%    2.0%  
-	[ 78,  81)   2    4.0%    6.0%  
-	[ 81,  86)   3    6.0%   12.0%  #
-	[ 86,  93)   2    4.0%   16.0%  
-	[ 93, 103)   4    8.0%   24.0%  #
-	[103, 117)   4    8.0%   32.0%  #
-	[117, 138)   5   10.0%   42.0%  #
-	[138, 167)   8   16.0%   58.0%  ##
-	[167, 208)   2    4.0%   62.0%  
-	[208, 265)  19   38.0%  100.0%  ####
-	[265, 346)   0    0.0%  100.0%  
-	[346, 460)   0    0.0%  100.0%  
-	[460, 619)   0    0.0%  100.0%  
-	[619, inf)   0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks__100B-2	     200	  38107608 ns/op	   0.00 MB/s
+	[  4,   5)    1    1.0%    1.0%  
+	[  5,   6)    0    0.0%    1.0%  
+	[  6,   7)    0    0.0%    1.0%  
+	[  7,   9)    1    1.0%    2.0%  
+	[  9,  12)    0    0.0%    2.0%  
+	[ 12,  17)    0    0.0%    2.0%  
+	[ 17,  24)    2    2.0%    4.0%  
+	[ 24,  34)    0    0.0%    4.0%  
+	[ 34,  48)    2    2.0%    6.0%  
+	[ 48,  68)   18   18.0%   24.0%  ##
+	[ 68,  96)   25   25.0%   49.0%  ###
+	[ 96, 135)   35   35.0%   84.0%  ####
+	[135, 190)   16   16.0%  100.0%  ##
+	[190, 266)    0    0.0%  100.0%  
+	[266, 373)    0    0.0%  100.0%  
+	[373, 522)    0    0.0%  100.0%  
+	[522, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks__100B-2	    2000	   5772039 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 4  Max: 124  Avg: 37.60
+	Count: 2000  Min: 1  Max: 48  Avg: 5.29
 	------------------------------------------------------------
-	[  4,   5)    1    0.5%    0.5%  
-	[  5,   6)    9    4.5%    5.0%  
-	[  6,   7)    2    1.0%    6.0%  
-	[  7,   9)    9    4.5%   10.5%  
-	[  9,  12)   28   14.0%   24.5%  #
-	[ 12,  16)   36   18.0%   42.5%  ##
-	[ 16,  22)   40   20.0%   62.5%  ##
-	[ 22,  31)   13    6.5%   69.0%  #
-	[ 31,  43)    6    3.0%   72.0%  
-	[ 43,  60)    3    1.5%   73.5%  
-	[ 60,  84)    5    2.5%   76.0%  
-	[ 84, 117)   44   22.0%   98.0%  ##
-	[117, 163)    4    2.0%  100.0%  
-	[163, 226)    0    0.0%  100.0%  
-	[226, 313)    0    0.0%  100.0%  
-	[313, 432)    0    0.0%  100.0%  
-	[432, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks___1KB	     100	 163950952 ns/op	   0.00 MB/s
+	[  1,   2)    19    1.0%    1.0%  
+	[  2,   3)   754   37.7%   38.7%  ####
+	[  3,   4)   569   28.5%   67.1%  ###
+	[  4,   6)   329   16.4%   83.6%  ##
+	[  6,   8)    56    2.8%   86.4%  
+	[  8,  11)    45    2.2%   88.6%  
+	[ 11,  15)    34    1.7%   90.3%  
+	[ 15,  21)    75    3.8%   94.1%  
+	[ 21,  28)    75    3.8%   97.8%  
+	[ 28,  38)    24    1.2%   99.0%  
+	[ 38,  51)    20    1.0%  100.0%  
+	[ 51,  67)     0    0.0%  100.0%  
+	[ 67,  88)     0    0.0%  100.0%  
+	[ 88, 116)     0    0.0%  100.0%  
+	[116, 152)     0    0.0%  100.0%  
+	[152, 198)     0    0.0%  100.0%  
+	[198, inf)     0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks___1KB	     100	 104839465 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 9  Max: 265  Avg: 163.45
+	Count: 100  Min: 9  Max: 179  Avg: 104.38
 	------------------------------------------------------------
-	[  9,  10)    2    2.0%    2.0%  
-	[ 10,  11)    0    0.0%    2.0%  
-	[ 11,  13)    0    0.0%    2.0%  
-	[ 13,  16)    1    1.0%    3.0%  
-	[ 16,  20)    1    1.0%    4.0%  
-	[ 20,  26)    0    0.0%    4.0%  
-	[ 26,  35)    1    1.0%    5.0%  
-	[ 35,  48)    3    3.0%    8.0%  
-	[ 48,  67)    0    0.0%    8.0%  
-	[ 67,  94)    9    9.0%   17.0%  #
-	[ 94, 134)   21   21.0%   38.0%  ##
-	[134, 192)   28   28.0%   66.0%  ###
-	[192, 276)   34   34.0%  100.0%  ###
-	[276, 398)    0    0.0%  100.0%  
-	[398, 574)    0    0.0%  100.0%  
-	[574, 829)    0    0.0%  100.0%  
-	[829, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks___1KB-2	     200	  43634458 ns/op	   0.00 MB/s
+	[  9,  10)    3    3.0%    3.0%  
+	[ 10,  11)    0    0.0%    3.0%  
+	[ 11,  12)    1    1.0%    4.0%  
+	[ 12,  14)    1    1.0%    5.0%  
+	[ 14,  17)    0    0.0%    5.0%  
+	[ 17,  22)    0    0.0%    5.0%  
+	[ 22,  29)    0    0.0%    5.0%  
+	[ 29,  39)    3    3.0%    8.0%  
+	[ 39,  54)    3    3.0%   11.0%  
+	[ 54,  75)    9    9.0%   20.0%  #
+	[ 75, 105)   35   35.0%   55.0%  ####
+	[105, 148)   20   20.0%   75.0%  ##
+	[148, 208)   25   25.0%  100.0%  ###
+	[208, 293)    0    0.0%  100.0%  
+	[293, 413)    0    0.0%  100.0%  
+	[413, 583)    0    0.0%  100.0%  
+	[583, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks___1KB-2	    1000	   7235554 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 4  Max: 137  Avg: 43.13
+	Count: 1000  Min: 1  Max: 55  Avg: 6.74
 	------------------------------------------------------------
-	[  4,   5)    7    3.5%    3.5%  
-	[  5,   6)   15    7.5%   11.0%  #
-	[  6,   7)    2    1.0%   12.0%  
-	[  7,   9)    9    4.5%   16.5%  
-	[  9,  12)   20   10.0%   26.5%  #
-	[ 12,  17)   22   11.0%   37.5%  #
-	[ 17,  24)   27   13.5%   51.0%  #
-	[ 24,  33)   17    8.5%   59.5%  #
-	[ 33,  46)   14    7.0%   66.5%  #
-	[ 46,  64)    9    4.5%   71.0%  
-	[ 64,  90)   13    6.5%   77.5%  #
-	[ 90, 126)   35   17.5%   95.0%  ##
-	[126, 176)   10    5.0%  100.0%  #
-	[176, 245)    0    0.0%  100.0%  
-	[245, 340)    0    0.0%  100.0%  
-	[340, 473)    0    0.0%  100.0%  
-	[473, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks__10KB	     100	  93479160 ns/op	   0.00 MB/s
+	[  1,   2)    10    1.0%    1.0%  
+	[  2,   3)   240   24.0%   25.0%  ##
+	[  3,   4)   272   27.2%   52.2%  ###
+	[  4,   6)   265   26.5%   78.7%  ###
+	[  6,   8)    44    4.4%   83.1%  
+	[  8,  11)    30    3.0%   86.1%  
+	[ 11,  15)    22    2.2%   88.3%  
+	[ 15,  21)    38    3.8%   92.1%  
+	[ 21,  29)    20    2.0%   94.1%  
+	[ 29,  39)    32    3.2%   97.3%  
+	[ 39,  53)    25    2.5%   99.8%  
+	[ 53,  71)     2    0.2%  100.0%  
+	[ 71,  95)     0    0.0%  100.0%  
+	[ 95, 126)     0    0.0%  100.0%  
+	[126, 167)     0    0.0%  100.0%  
+	[167, 221)     0    0.0%  100.0%  
+	[221, inf)     0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks__10KB	     100	  72299884 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 8  Max: 138  Avg: 92.97
+	Count: 100  Min: 8  Max: 122  Avg: 71.77
 	------------------------------------------------------------
 	[  8,   9)    1    1.0%    1.0%  
 	[  9,  10)    0    0.0%    1.0%  
 	[ 10,  11)    0    0.0%    1.0%  
 	[ 11,  13)    0    0.0%    1.0%  
 	[ 13,  16)    0    0.0%    1.0%  
-	[ 16,  21)    3    3.0%    4.0%  
-	[ 21,  28)    3    3.0%    7.0%  
-	[ 28,  37)    2    2.0%    9.0%  
-	[ 37,  50)    3    3.0%   12.0%  
-	[ 50,  68)   12   12.0%   24.0%  #
-	[ 68,  93)   12   12.0%   36.0%  #
-	[ 93, 128)   55   55.0%   91.0%  ######
-	[128, 177)    9    9.0%  100.0%  #
-	[177, 244)    0    0.0%  100.0%  
-	[244, 337)    0    0.0%  100.0%  
-	[337, 466)    0    0.0%  100.0%  
-	[466, inf)    0    0.0%  100.0%  
-Benchmark___10B_mux___1K_chunks__10KB-2	     100	  54432420 ns/op	   0.00 MB/s
+	[ 16,  20)    4    4.0%    5.0%  
+	[ 20,  26)    0    0.0%    5.0%  
+	[ 26,  35)    4    4.0%    9.0%  
+	[ 35,  47)   11   11.0%   20.0%  #
+	[ 47,  64)   12   12.0%   32.0%  #
+	[ 64,  87)   42   42.0%   74.0%  ####
+	[ 87, 119)   24   24.0%   98.0%  ##
+	[119, 163)    2    2.0%  100.0%  
+	[163, 223)    0    0.0%  100.0%  
+	[223, 306)    0    0.0%  100.0%  
+	[306, 420)    0    0.0%  100.0%  
+	[420, inf)    0    0.0%  100.0%  
+Benchmark___10B_mux___1K_chunks__10KB-2	     200	  36957063 ns/op	   0.00 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 5  Max: 89  Avg: 53.92
+	Count: 200  Min: 2  Max: 72  Avg: 36.49
 	------------------------------------------------------------
-	[  5,   6)    1    1.0%    1.0%  
-	[  6,   7)    2    2.0%    3.0%  
-	[  7,   8)    1    1.0%    4.0%  
-	[  8,  10)    2    2.0%    6.0%  
-	[ 10,  13)    3    3.0%    9.0%  
-	[ 13,  17)    1    1.0%   10.0%  
-	[ 17,  22)    6    6.0%   16.0%  #
-	[ 22,  29)    2    2.0%   18.0%  
-	[ 29,  39)    8    8.0%   26.0%  #
-	[ 39,  53)   12   12.0%   38.0%  #
-	[ 53,  72)   38   38.0%   76.0%  ####
-	[ 72,  97)   24   24.0%  100.0%  ##
-	[ 97, 131)    0    0.0%  100.0%  
-	[131, 177)    0    0.0%  100.0%  
-	[177, 239)    0    0.0%  100.0%  
-	[239, 322)    0    0.0%  100.0%  
-	[322, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks___10B	     300	  26012216 ns/op	   0.08 MB/s
+	[  2,   3)    8    4.0%    4.0%  
+	[  3,   4)    5    2.5%    6.5%  
+	[  4,   5)    6    3.0%    9.5%  
+	[  5,   7)    3    1.5%   11.0%  
+	[  7,  10)    6    3.0%   14.0%  
+	[ 10,  14)    6    3.0%   17.0%  
+	[ 14,  19)    8    4.0%   21.0%  
+	[ 19,  26)   12    6.0%   27.0%  #
+	[ 26,  35)   31   15.5%   42.5%  ##
+	[ 35,  47)   48   24.0%   66.5%  ##
+	[ 47,  63)   52   26.0%   92.5%  ###
+	[ 63,  85)   15    7.5%  100.0%  #
+	[ 85, 114)    0    0.0%  100.0%  
+	[114, 153)    0    0.0%  100.0%  
+	[153, 205)    0    0.0%  100.0%  
+	[205, 274)    0    0.0%  100.0%  
+	[274, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks___10B	     500	  17595461 ns/op	   0.11 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 8  Max: 32  Avg: 25.48
+	Count: 500  Min: 7  Max: 35  Avg: 17.11
 	------------------------------------------------------------
-	[  8,   9)    2    0.7%    0.7%  
-	[  9,  10)    0    0.0%    0.7%  
-	[ 10,  11)    0    0.0%    0.7%  
-	[ 11,  12)   10    3.3%    4.0%  
-	[ 12,  14)    0    0.0%    4.0%  
-	[ 14,  16)    1    0.3%    4.3%  
-	[ 16,  19)    0    0.0%    4.3%  
-	[ 19,  23)    9    3.0%    7.3%  
-	[ 23,  28)  202   67.3%   74.7%  #######
-	[ 28,  34)   76   25.3%  100.0%  ###
-	[ 34,  42)    0    0.0%  100.0%  
-	[ 42,  52)    0    0.0%  100.0%  
-	[ 52,  64)    0    0.0%  100.0%  
-	[ 64,  79)    0    0.0%  100.0%  
-	[ 79,  98)    0    0.0%  100.0%  
-	[ 98, 122)    0    0.0%  100.0%  
-	[122, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks___10B-2	    1000	   7943170 ns/op	   0.25 MB/s
---- Histogram (unit: ms)
-	Count: 1000  Min: 4  Max: 22  Avg: 7.46
-	------------------------------------------------------------
-	[  4,   5)    10    1.0%    1.0%  
-	[  5,   6)   233   23.3%   24.3%  ##
-	[  6,   7)   284   28.4%   52.7%  ###
-	[  7,   8)   126   12.6%   65.3%  #
-	[  8,  10)   155   15.5%   80.8%  ##
-	[ 10,  12)    87    8.7%   89.5%  #
-	[ 12,  15)    82    8.2%   97.7%  #
-	[ 15,  18)    19    1.9%   99.6%  
-	[ 18,  22)     3    0.3%   99.9%  
-	[ 22,  27)     1    0.1%  100.0%  
-	[ 27,  33)     0    0.0%  100.0%  
-	[ 33,  41)     0    0.0%  100.0%  
-	[ 41,  51)     0    0.0%  100.0%  
-	[ 51,  63)     0    0.0%  100.0%  
-	[ 63,  77)     0    0.0%  100.0%  
-	[ 77,  94)     0    0.0%  100.0%  
-	[ 94, inf)     0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks__100B	     300	  26131776 ns/op	   0.08 MB/s
---- Histogram (unit: ms)
-	Count: 300  Min: 8  Max: 35  Avg: 25.63
-	------------------------------------------------------------
-	[  8,   9)    1    0.3%    0.3%  
-	[  9,  10)    0    0.0%    0.3%  
-	[ 10,  11)    0    0.0%    0.3%  
-	[ 11,  12)    0    0.0%    0.3%  
-	[ 12,  14)    0    0.0%    0.3%  
-	[ 14,  17)    0    0.0%    0.3%  
-	[ 17,  20)    1    0.3%    0.7%  
-	[ 20,  24)  126   42.0%   42.7%  ####
-	[ 24,  29)   86   28.7%   71.3%  ###
-	[ 29,  36)   86   28.7%  100.0%  ###
-	[ 36,  45)    0    0.0%  100.0%  
-	[ 45,  56)    0    0.0%  100.0%  
-	[ 56,  69)    0    0.0%  100.0%  
+	[  7,   8)    1    0.2%    0.2%  
+	[  8,   9)    1    0.2%    0.4%  
+	[  9,  10)    0    0.0%    0.4%  
+	[ 10,  11)    0    0.0%    0.4%  
+	[ 11,  13)    4    0.8%    1.2%  
+	[ 13,  16)  380   76.0%   77.2%  ########
+	[ 16,  19)   43    8.6%   85.8%  #
+	[ 19,  23)    2    0.4%   86.2%  
+	[ 23,  28)   14    2.8%   89.0%  
+	[ 28,  35)   54   10.8%   99.8%  #
+	[ 35,  44)    1    0.2%  100.0%  
+	[ 44,  55)    0    0.0%  100.0%  
+	[ 55,  69)    0    0.0%  100.0%  
 	[ 69,  86)    0    0.0%  100.0%  
-	[ 86, 107)    0    0.0%  100.0%  
-	[107, 134)    0    0.0%  100.0%  
-	[134, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks__100B-2	    1000	   8434636 ns/op	   0.24 MB/s
+	[ 86, 108)    0    0.0%  100.0%  
+	[108, 135)    0    0.0%  100.0%  
+	[135, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks___10B-2	    2000	   4157817 ns/op	   0.48 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 4  Max: 23  Avg: 7.96
+	Count: 2000  Min: 1  Max: 22  Avg: 3.67
 	------------------------------------------------------------
-	[  4,   5)     6    0.6%    0.6%  
-	[  5,   6)   165   16.5%   17.1%  ##
-	[  6,   7)   286   28.6%   45.7%  ###
-	[  7,   8)   152   15.2%   60.9%  ##
-	[  8,  10)   151   15.1%   76.0%  ##
-	[ 10,  12)    97    9.7%   85.7%  #
-	[ 12,  15)    91    9.1%   94.8%  #
-	[ 15,  18)    43    4.3%   99.1%  
-	[ 18,  22)     7    0.7%   99.8%  
-	[ 22,  27)     2    0.2%  100.0%  
+	[  1,   2)    29    1.5%    1.5%  
+	[  2,   3)   804   40.2%   41.7%  ####
+	[  3,   4)   550   27.5%   69.2%  ###
+	[  4,   5)   289   14.5%   83.6%  #
+	[  5,   7)   160    8.0%   91.6%  #
+	[  7,   9)    31    1.6%   93.2%  
+	[  9,  12)    63    3.2%   96.3%  
+	[ 12,  16)    32    1.6%   97.9%  
+	[ 16,  21)    36    1.8%   99.7%  
+	[ 21,  27)     6    0.3%  100.0%  
 	[ 27,  34)     0    0.0%  100.0%  
-	[ 34,  42)     0    0.0%  100.0%  
-	[ 42,  52)     0    0.0%  100.0%  
-	[ 52,  64)     0    0.0%  100.0%  
-	[ 64,  79)     0    0.0%  100.0%  
-	[ 79,  97)     0    0.0%  100.0%  
-	[ 97, inf)     0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks___1KB	     200	  31946178 ns/op	   0.06 MB/s
+	[ 34,  43)     0    0.0%  100.0%  
+	[ 43,  54)     0    0.0%  100.0%  
+	[ 54,  67)     0    0.0%  100.0%  
+	[ 67,  84)     0    0.0%  100.0%  
+	[ 84, 104)     0    0.0%  100.0%  
+	[104, inf)     0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks__100B	     500	  18203976 ns/op	   0.11 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 9  Max: 44  Avg: 31.49
+	Count: 500  Min: 8  Max: 39  Avg: 17.78
 	------------------------------------------------------------
-	[  9,  10)   12    6.0%    6.0%  #
-	[ 10,  11)    1    0.5%    6.5%  
-	[ 11,  12)    0    0.0%    6.5%  
-	[ 12,  14)    4    2.0%    8.5%  
-	[ 14,  16)    0    0.0%    8.5%  
-	[ 16,  19)    2    1.0%    9.5%  
-	[ 19,  23)    0    0.0%    9.5%  
-	[ 23,  28)   13    6.5%   16.0%  #
-	[ 28,  34)   93   46.5%   62.5%  #####
-	[ 34,  42)   71   35.5%   98.0%  ####
-	[ 42,  52)    4    2.0%  100.0%  
-	[ 52,  65)    0    0.0%  100.0%  
-	[ 65,  82)    0    0.0%  100.0%  
-	[ 82, 103)    0    0.0%  100.0%  
-	[103, 130)    0    0.0%  100.0%  
-	[130, 164)    0    0.0%  100.0%  
-	[164, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks___1KB-2	    1000	  11688416 ns/op	   0.17 MB/s
+	[  8,   9)    1    0.2%    0.2%  
+	[  9,  10)    0    0.0%    0.2%  
+	[ 10,  11)    0    0.0%    0.2%  
+	[ 11,  12)    0    0.0%    0.2%  
+	[ 12,  14)    5    1.0%    1.2%  
+	[ 14,  17)  405   81.0%   82.2%  ########
+	[ 17,  20)   21    4.2%   86.4%  
+	[ 20,  24)    1    0.2%   86.6%  
+	[ 24,  30)    8    1.6%   88.2%  
+	[ 30,  37)   54   10.8%   99.0%  #
+	[ 37,  46)    5    1.0%  100.0%  
+	[ 46,  58)    0    0.0%  100.0%  
+	[ 58,  73)    0    0.0%  100.0%  
+	[ 73,  92)    0    0.0%  100.0%  
+	[ 92, 116)    0    0.0%  100.0%  
+	[116, 146)    0    0.0%  100.0%  
+	[146, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks__100B-2	    2000	   4271254 ns/op	   0.47 MB/s
 --- Histogram (unit: ms)
-	Count: 1000  Min: 4  Max: 28  Avg: 11.20
+	Count: 2000  Min: 1  Max: 26  Avg: 3.79
 	------------------------------------------------------------
-	[  4,   5)     5    0.5%    0.5%  
-	[  5,   6)    69    6.9%    7.4%  #
-	[  6,   7)    75    7.5%   14.9%  #
-	[  7,   8)   121   12.1%   27.0%  #
-	[  8,  10)   171   17.1%   44.1%  ##
-	[ 10,  12)   134   13.4%   57.5%  #
-	[ 12,  15)   172   17.2%   74.7%  ##
-	[ 15,  19)   170   17.0%   91.7%  ##
-	[ 19,  24)    79    7.9%   99.6%  #
-	[ 24,  30)     4    0.4%  100.0%  
-	[ 30,  38)     0    0.0%  100.0%  
-	[ 38,  48)     0    0.0%  100.0%  
-	[ 48,  60)     0    0.0%  100.0%  
-	[ 60,  75)     0    0.0%  100.0%  
-	[ 75,  94)     0    0.0%  100.0%  
+	[  1,   2)    31    1.6%    1.6%  
+	[  2,   3)   761   38.1%   39.6%  ####
+	[  3,   4)   550   27.5%   67.1%  ###
+	[  4,   5)   316   15.8%   82.9%  ##
+	[  5,   7)   166    8.3%   91.2%  #
+	[  7,   9)    25    1.2%   92.5%  
+	[  9,  12)    65    3.2%   95.7%  
+	[ 12,  16)    48    2.4%   98.1%  
+	[ 16,  21)    22    1.1%   99.2%  
+	[ 21,  27)    16    0.8%  100.0%  
+	[ 27,  35)     0    0.0%  100.0%  
+	[ 35,  45)     0    0.0%  100.0%  
+	[ 45,  58)     0    0.0%  100.0%  
+	[ 58,  74)     0    0.0%  100.0%  
+	[ 74,  94)     0    0.0%  100.0%  
 	[ 94, 118)     0    0.0%  100.0%  
 	[118, inf)     0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks__10KB	     200	  48210454 ns/op	   0.04 MB/s
+Benchmark___1KB_mux__100_chunks___1KB	     300	  20682669 ns/op	   0.10 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 9  Max: 61  Avg: 47.74
+	Count: 300  Min: 13  Max: 41  Avg: 20.18
 	------------------------------------------------------------
-	[  9,  10)    1    0.5%    0.5%  
-	[ 10,  11)    0    0.0%    0.5%  
-	[ 11,  12)    0    0.0%    0.5%  
-	[ 12,  14)   14    7.0%    7.5%  #
-	[ 14,  16)    9    4.5%   12.0%  
-	[ 16,  19)    5    2.5%   14.5%  
-	[ 19,  23)    2    1.0%   15.5%  
-	[ 23,  29)    0    0.0%   15.5%  
-	[ 29,  37)    0    0.0%   15.5%  
-	[ 37,  47)    7    3.5%   19.0%  
-	[ 47,  60)  159   79.5%   98.5%  ########
-	[ 60,  78)    3    1.5%  100.0%  
-	[ 78, 101)    0    0.0%  100.0%  
-	[101, 131)    0    0.0%  100.0%  
-	[131, 170)    0    0.0%  100.0%  
-	[170, 222)    0    0.0%  100.0%  
-	[222, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux__100_chunks__10KB-2	     300	  24547213 ns/op	   0.08 MB/s
+	[ 13,  14)    1    0.3%    0.3%  
+	[ 14,  15)    2    0.7%    1.0%  
+	[ 15,  16)    0    0.0%    1.0%  
+	[ 16,  17)    0    0.0%    1.0%  
+	[ 17,  19)  245   81.7%   82.7%  ########
+	[ 19,  22)    8    2.7%   85.3%  
+	[ 22,  25)    5    1.7%   87.0%  
+	[ 25,  29)    0    0.0%   87.0%  
+	[ 29,  34)    1    0.3%   87.3%  
+	[ 34,  41)   28    9.3%   96.7%  #
+	[ 41,  50)   10    3.3%  100.0%  
+	[ 50,  61)    0    0.0%  100.0%  
+	[ 61,  75)    0    0.0%  100.0%  
+	[ 75,  92)    0    0.0%  100.0%  
+	[ 92, 114)    0    0.0%  100.0%  
+	[114, 141)    0    0.0%  100.0%  
+	[141, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks___1KB-2	    2000	   4950276 ns/op	   0.40 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 4  Max: 42  Avg: 24.07
+	Count: 2000  Min: 1  Max: 26  Avg: 4.46
 	------------------------------------------------------------
-	[  4,   5)    1    0.3%    0.3%  
-	[  5,   6)    8    2.7%    3.0%  
-	[  6,   7)    1    0.3%    3.3%  
-	[  7,   9)    6    2.0%    5.3%  
-	[  9,  11)   14    4.7%   10.0%  
-	[ 11,  14)   24    8.0%   18.0%  #
-	[ 14,  18)   13    4.3%   22.3%  
-	[ 18,  23)   37   12.3%   34.7%  #
-	[ 23,  29)   67   22.3%   57.0%  ##
-	[ 29,  37)  120   40.0%   97.0%  ####
-	[ 37,  48)    9    3.0%  100.0%  
-	[ 48,  62)    0    0.0%  100.0%  
-	[ 62,  80)    0    0.0%  100.0%  
-	[ 80, 103)    0    0.0%  100.0%  
-	[103, 132)    0    0.0%  100.0%  
-	[132, 169)    0    0.0%  100.0%  
-	[169, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks___10B	     100	 131862174 ns/op	   0.02 MB/s
+	[  1,   2)    12    0.6%    0.6%  
+	[  2,   3)   546   27.3%   27.9%  ###
+	[  3,   4)   517   25.9%   53.8%  ###
+	[  4,   5)   354   17.7%   71.5%  ##
+	[  5,   7)   341   17.1%   88.5%  ##
+	[  7,   9)    60    3.0%   91.5%  
+	[  9,  12)    37    1.9%   93.4%  
+	[ 12,  16)    76    3.8%   97.2%  
+	[ 16,  21)    20    1.0%   98.2%  
+	[ 21,  27)    37    1.9%  100.0%  
+	[ 27,  35)     0    0.0%  100.0%  
+	[ 35,  45)     0    0.0%  100.0%  
+	[ 45,  58)     0    0.0%  100.0%  
+	[ 58,  74)     0    0.0%  100.0%  
+	[ 74,  94)     0    0.0%  100.0%  
+	[ 94, 118)     0    0.0%  100.0%  
+	[118, inf)     0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks__10KB	     200	  39416624 ns/op	   0.05 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 10  Max: 209  Avg: 131.34
+	Count: 200  Min: 14  Max: 57  Avg: 38.98
 	------------------------------------------------------------
-	[ 10,  11)    1    1.0%    1.0%  
-	[ 11,  12)    1    1.0%    2.0%  
-	[ 12,  14)    0    0.0%    2.0%  
-	[ 14,  16)    0    0.0%    2.0%  
-	[ 16,  20)    1    1.0%    3.0%  
-	[ 20,  25)    0    0.0%    3.0%  
-	[ 25,  33)    0    0.0%    3.0%  
-	[ 33,  44)    0    0.0%    3.0%  
-	[ 44,  60)    4    4.0%    7.0%  
-	[ 60,  83)   16   16.0%   23.0%  ##
-	[ 83, 117)   18   18.0%   41.0%  ##
-	[117, 165)   24   24.0%   65.0%  ##
-	[165, 234)   35   35.0%  100.0%  ####
-	[234, 332)    0    0.0%  100.0%  
-	[332, 471)    0    0.0%  100.0%  
-	[471, 669)    0    0.0%  100.0%  
-	[669, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks___10B-2	     300	  23370846 ns/op	   0.09 MB/s
+	[ 14,  15)    2    1.0%    1.0%  
+	[ 15,  16)    0    0.0%    1.0%  
+	[ 16,  17)    0    0.0%    1.0%  
+	[ 17,  19)    2    1.0%    2.0%  
+	[ 19,  21)    0    0.0%    2.0%  
+	[ 21,  24)    0    0.0%    2.0%  
+	[ 24,  28)    0    0.0%    2.0%  
+	[ 28,  33)    4    2.0%    4.0%  
+	[ 33,  40)  130   65.0%   69.0%  #######
+	[ 40,  49)   16    8.0%   77.0%  #
+	[ 49,  61)   46   23.0%  100.0%  ##
+	[ 61,  76)    0    0.0%  100.0%  
+	[ 76,  96)    0    0.0%  100.0%  
+	[ 96, 122)    0    0.0%  100.0%  
+	[122, 155)    0    0.0%  100.0%  
+	[155, 198)    0    0.0%  100.0%  
+	[198, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux__100_chunks__10KB-2	     500	  13370112 ns/op	   0.15 MB/s
 --- Histogram (unit: ms)
-	Count: 300  Min: 4  Max: 101  Avg: 22.88
+	Count: 500  Min: 1  Max: 35  Avg: 12.88
 	------------------------------------------------------------
-	[  4,   5)    1    0.3%    0.3%  
-	[  5,   6)   24    8.0%    8.3%  #
-	[  6,   7)   49   16.3%   24.7%  ##
-	[  7,   9)   48   16.0%   40.7%  ##
-	[  9,  12)   26    8.7%   49.3%  #
-	[ 12,  16)   53   17.7%   67.0%  ##
-	[ 16,  22)   36   12.0%   79.0%  #
-	[ 22,  30)    5    1.7%   80.7%  
-	[ 30,  41)    4    1.3%   82.0%  
-	[ 41,  56)    3    1.0%   83.0%  
-	[ 56,  77)   21    7.0%   90.0%  #
-	[ 77, 105)   30   10.0%  100.0%  #
-	[105, 143)    0    0.0%  100.0%  
-	[143, 195)    0    0.0%  100.0%  
-	[195, 266)    0    0.0%  100.0%  
-	[266, 362)    0    0.0%  100.0%  
-	[362, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks__100B	      50	 138026822 ns/op	   0.01 MB/s
+	[  1,   2)    6    1.2%    1.2%  
+	[  2,   3)   94   18.8%   20.0%  ##
+	[  3,   4)   29    5.8%   25.8%  #
+	[  4,   6)   22    4.4%   30.2%  
+	[  6,   8)   15    3.0%   33.2%  
+	[  8,  11)   55   11.0%   44.2%  #
+	[ 11,  15)   31    6.2%   50.4%  #
+	[ 15,  20)  174   34.8%   85.2%  ###
+	[ 20,  26)   14    2.8%   88.0%  
+	[ 26,  34)   54   10.8%   98.8%  #
+	[ 34,  44)    6    1.2%  100.0%  
+	[ 44,  57)    0    0.0%  100.0%  
+	[ 57,  73)    0    0.0%  100.0%  
+	[ 73,  94)    0    0.0%  100.0%  
+	[ 94, 120)    0    0.0%  100.0%  
+	[120, 153)    0    0.0%  100.0%  
+	[153, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks___10B	     100	  95315574 ns/op	   0.02 MB/s
 --- Histogram (unit: ms)
-	Count: 50  Min: 22  Max: 222  Avg: 137.50
+	Count: 100  Min: 23  Max: 150  Avg: 94.81
 	------------------------------------------------------------
-	[ 22,  23)   1    2.0%    2.0%  
-	[ 23,  24)   1    2.0%    4.0%  
-	[ 24,  26)   0    0.0%    4.0%  
-	[ 26,  28)   0    0.0%    4.0%  
-	[ 28,  32)   0    0.0%    4.0%  
-	[ 32,  37)   0    0.0%    4.0%  
-	[ 37,  45)   0    0.0%    4.0%  
-	[ 45,  56)   2    4.0%    8.0%  
-	[ 56,  72)   2    4.0%   12.0%  
-	[ 72,  96)   7   14.0%   26.0%  #
-	[ 96, 130)  11   22.0%   48.0%  ##
-	[130, 178)  10   20.0%   68.0%  ##
-	[178, 247)  16   32.0%  100.0%  ###
-	[247, 345)   0    0.0%  100.0%  
-	[345, 485)   0    0.0%  100.0%  
-	[485, 684)   0    0.0%  100.0%  
-	[684, inf)   0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks__100B-2	     200	  29916622 ns/op	   0.07 MB/s
+	[ 23,  24)    1    1.0%    1.0%  
+	[ 24,  25)    0    0.0%    1.0%  
+	[ 25,  26)    0    0.0%    1.0%  
+	[ 26,  28)    1    1.0%    2.0%  
+	[ 28,  31)    0    0.0%    2.0%  
+	[ 31,  36)    1    1.0%    3.0%  
+	[ 36,  42)    2    2.0%    5.0%  
+	[ 42,  51)    5    5.0%   10.0%  #
+	[ 51,  64)    7    7.0%   17.0%  #
+	[ 64,  82)   17   17.0%   34.0%  ##
+	[ 82, 107)   24   24.0%   58.0%  ##
+	[107, 141)   38   38.0%   96.0%  ####
+	[141, 189)    4    4.0%  100.0%  
+	[189, 255)    0    0.0%  100.0%  
+	[255, 346)    0    0.0%  100.0%  
+	[346, 472)    0    0.0%  100.0%  
+	[472, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks___10B-2	    2000	   5107260 ns/op	   0.39 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 5  Max: 117  Avg: 29.41
+	Count: 2000  Min: 1  Max: 46  Avg: 4.61
 	------------------------------------------------------------
-	[  5,   6)    8    4.0%    4.0%  
-	[  6,   7)   19    9.5%   13.5%  #
-	[  7,   8)   15    7.5%   21.0%  #
-	[  8,  10)   31   15.5%   36.5%  ##
-	[ 10,  13)   25   12.5%   49.0%  #
-	[ 13,  17)   37   18.5%   67.5%  ##
-	[ 17,  23)   15    7.5%   75.0%  #
-	[ 23,  32)    4    2.0%   77.0%  
-	[ 32,  44)    2    1.0%   78.0%  
-	[ 44,  60)    0    0.0%   78.0%  
-	[ 60,  83)    4    2.0%   80.0%  
-	[ 83, 114)   38   19.0%   99.0%  ##
-	[114, 157)    2    1.0%  100.0%  
-	[157, 216)    0    0.0%  100.0%  
-	[216, 297)    0    0.0%  100.0%  
-	[297, 408)    0    0.0%  100.0%  
-	[408, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks___1KB	      50	 165938483 ns/op	   0.01 MB/s
+	[  1,   2)    15    0.8%    0.8%  
+	[  2,   3)   792   39.6%   40.4%  ####
+	[  3,   4)   669   33.5%   73.8%  ###
+	[  4,   6)   289   14.5%   88.2%  #
+	[  6,   8)    28    1.4%   89.7%  
+	[  8,  11)    23    1.2%   90.8%  
+	[ 11,  15)    34    1.7%   92.5%  
+	[ 15,  20)    36    1.8%   94.3%  
+	[ 20,  27)    71    3.6%   97.9%  
+	[ 27,  36)    37    1.9%   99.7%  
+	[ 36,  48)     6    0.3%  100.0%  
+	[ 48,  64)     0    0.0%  100.0%  
+	[ 64,  85)     0    0.0%  100.0%  
+	[ 85, 112)     0    0.0%  100.0%  
+	[112, 146)     0    0.0%  100.0%  
+	[146, 190)     0    0.0%  100.0%  
+	[190, inf)     0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks__100B	     100	  94447578 ns/op	   0.02 MB/s
 --- Histogram (unit: ms)
-	Count: 50  Min: 19  Max: 292  Avg: 165.50
+	Count: 100  Min: 2  Max: 149  Avg: 93.96
 	------------------------------------------------------------
-	[ 19,  20)   1    2.0%    2.0%  
-	[ 20,  21)   0    0.0%    2.0%  
-	[ 21,  23)   0    0.0%    2.0%  
-	[ 23,  26)   0    0.0%    2.0%  
-	[ 26,  30)   0    0.0%    2.0%  
-	[ 30,  36)   0    0.0%    2.0%  
-	[ 36,  45)   0    0.0%    2.0%  
-	[ 45,  58)   1    2.0%    4.0%  
-	[ 58,  77)   0    0.0%    4.0%  
-	[ 77, 105)  10   20.0%   24.0%  ##
-	[105, 147)  11   22.0%   46.0%  ##
-	[147, 208)  14   28.0%   74.0%  ###
-	[208, 296)  13   26.0%  100.0%  ###
-	[296, 425)   0    0.0%  100.0%  
-	[425, 612)   0    0.0%  100.0%  
-	[612, 884)   0    0.0%  100.0%  
-	[884, inf)   0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks___1KB-2	     200	  44332653 ns/op	   0.05 MB/s
+	[  2,   3)    1    1.0%    1.0%  
+	[  3,   4)    0    0.0%    1.0%  
+	[  4,   5)    0    0.0%    1.0%  
+	[  5,   7)    0    0.0%    1.0%  
+	[  7,  10)    2    2.0%    3.0%  
+	[ 10,  15)    0    0.0%    3.0%  
+	[ 15,  22)    1    1.0%    4.0%  
+	[ 22,  32)    2    2.0%    6.0%  
+	[ 32,  46)    7    7.0%   13.0%  #
+	[ 46,  65)    9    9.0%   22.0%  #
+	[ 65,  92)   20   20.0%   42.0%  ##
+	[ 92, 130)   40   40.0%   82.0%  ####
+	[130, 184)   18   18.0%  100.0%  ##
+	[184, 259)    0    0.0%  100.0%  
+	[259, 364)    0    0.0%  100.0%  
+	[364, 511)    0    0.0%  100.0%  
+	[511, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks__100B-2	    2000	   5333802 ns/op	   0.37 MB/s
 --- Histogram (unit: ms)
-	Count: 200  Min: 5  Max: 136  Avg: 43.85
+	Count: 2000  Min: 1  Max: 55  Avg: 4.84
 	------------------------------------------------------------
-	[  5,   6)   10    5.0%    5.0%  #
-	[  6,   7)    1    0.5%    5.5%  
-	[  7,   8)    2    1.0%    6.5%  
-	[  8,  10)   14    7.0%   13.5%  #
-	[ 10,  13)   22   11.0%   24.5%  #
-	[ 13,  18)   23   11.5%   36.0%  #
-	[ 18,  25)   24   12.0%   48.0%  #
-	[ 25,  34)   21   10.5%   58.5%  #
-	[ 34,  47)   19    9.5%   68.0%  #
-	[ 47,  65)    9    4.5%   72.5%  
-	[ 65,  90)   10    5.0%   77.5%  #
-	[ 90, 125)   38   19.0%   96.5%  ##
-	[125, 174)    7    3.5%  100.0%  
-	[174, 242)    0    0.0%  100.0%  
-	[242, 336)    0    0.0%  100.0%  
-	[336, 466)    0    0.0%  100.0%  
-	[466, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks__10KB	     100	  97935953 ns/op	   0.02 MB/s
+	[  1,   2)    16    0.8%    0.8%  
+	[  2,   3)   766   38.3%   39.1%  ####
+	[  3,   4)   670   33.5%   72.6%  ###
+	[  4,   6)   318   15.9%   88.5%  ##
+	[  6,   8)    36    1.8%   90.3%  
+	[  8,  11)    12    0.6%   90.9%  
+	[ 11,  15)    26    1.3%   92.2%  
+	[ 15,  21)    46    2.3%   94.5%  
+	[ 21,  29)    65    3.2%   97.8%  
+	[ 29,  39)    34    1.7%   99.5%  
+	[ 39,  53)     7    0.4%   99.8%  
+	[ 53,  71)     4    0.2%  100.0%  
+	[ 71,  95)     0    0.0%  100.0%  
+	[ 95, 126)     0    0.0%  100.0%  
+	[126, 167)     0    0.0%  100.0%  
+	[167, 221)     0    0.0%  100.0%  
+	[221, inf)     0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks___1KB	     100	 106144273 ns/op	   0.02 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 10  Max: 161  Avg: 97.40
+	Count: 100  Min: 6  Max: 173  Avg: 105.63
 	------------------------------------------------------------
-	[ 10,  11)    1    1.0%    1.0%  
-	[ 11,  12)    0    0.0%    1.0%  
-	[ 12,  13)    0    0.0%    1.0%  
-	[ 13,  15)    1    1.0%    2.0%  
-	[ 15,  18)    0    0.0%    2.0%  
-	[ 18,  23)    0    0.0%    2.0%  
-	[ 23,  30)    1    1.0%    3.0%  
-	[ 30,  40)    4    4.0%    7.0%  
-	[ 40,  54)    4    4.0%   11.0%  
-	[ 54,  74)   17   17.0%   28.0%  ##
-	[ 74, 102)   20   20.0%   48.0%  ##
-	[102, 141)   45   45.0%   93.0%  #####
-	[141, 196)    7    7.0%  100.0%  #
-	[196, 273)    0    0.0%  100.0%  
-	[273, 381)    0    0.0%  100.0%  
-	[381, 531)    0    0.0%  100.0%  
-	[531, inf)    0    0.0%  100.0%  
-Benchmark___1KB_mux___1K_chunks__10KB-2	     100	  59656535 ns/op	   0.03 MB/s
+	[  6,   7)    1    1.0%    1.0%  
+	[  7,   8)    0    0.0%    1.0%  
+	[  8,   9)    0    0.0%    1.0%  
+	[  9,  11)    0    0.0%    1.0%  
+	[ 11,  14)    1    1.0%    2.0%  
+	[ 14,  19)    3    3.0%    5.0%  
+	[ 19,  26)    1    1.0%    6.0%  
+	[ 26,  36)    4    4.0%   10.0%  
+	[ 36,  51)    4    4.0%   14.0%  
+	[ 51,  72)    8    8.0%   22.0%  #
+	[ 72, 102)   24   24.0%   46.0%  ##
+	[102, 144)   26   26.0%   72.0%  ###
+	[144, 204)   28   28.0%  100.0%  ###
+	[204, 288)    0    0.0%  100.0%  
+	[288, 406)    0    0.0%  100.0%  
+	[406, 573)    0    0.0%  100.0%  
+	[573, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks___1KB-2	    1000	   7132495 ns/op	   0.28 MB/s
 --- Histogram (unit: ms)
-	Count: 100  Min: 5  Max: 111  Avg: 59.16
+	Count: 1000  Min: 1  Max: 43  Avg: 6.64
 	------------------------------------------------------------
-	[  5,   6)    2    2.0%    2.0%  
-	[  6,   7)    0    0.0%    2.0%  
-	[  7,   8)    0    0.0%    2.0%  
-	[  8,  10)    0    0.0%    2.0%  
-	[ 10,  13)    2    2.0%    4.0%  
-	[ 13,  17)    3    3.0%    7.0%  
-	[ 17,  23)    2    2.0%    9.0%  
-	[ 23,  31)    9    9.0%   18.0%  #
-	[ 31,  43)    5    5.0%   23.0%  #
-	[ 43,  59)   17   17.0%   40.0%  ##
-	[ 59,  81)   47   47.0%   87.0%  #####
-	[ 81, 111)   12   12.0%   99.0%  #
-	[111, 152)    1    1.0%  100.0%  
-	[152, 208)    0    0.0%  100.0%  
-	[208, 285)    0    0.0%  100.0%  
-	[285, 390)    0    0.0%  100.0%  
-	[390, inf)    0    0.0%  100.0%  
+	[  1,   2)    24    2.4%    2.4%  
+	[  2,   3)   286   28.6%   31.0%  ###
+	[  3,   4)   272   27.2%   58.2%  ###
+	[  4,   6)   217   21.7%   79.9%  ##
+	[  6,   8)    44    4.4%   84.3%  
+	[  8,  11)    15    1.5%   85.8%  
+	[ 11,  15)    11    1.1%   86.9%  
+	[ 15,  20)    19    1.9%   88.8%  
+	[ 20,  27)    14    1.4%   90.2%  
+	[ 27,  36)    87    8.7%   98.9%  #
+	[ 36,  48)    11    1.1%  100.0%  
+	[ 48,  63)     0    0.0%  100.0%  
+	[ 63,  82)     0    0.0%  100.0%  
+	[ 82, 107)     0    0.0%  100.0%  
+	[107, 139)     0    0.0%  100.0%  
+	[139, 181)     0    0.0%  100.0%  
+	[181, inf)     0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks__10KB	     100	  75825411 ns/op	   0.03 MB/s
+--- Histogram (unit: ms)
+	Count: 100  Min: 3  Max: 130  Avg: 75.35
+	------------------------------------------------------------
+	[  3,   4)    1    1.0%    1.0%  
+	[  4,   5)    0    0.0%    1.0%  
+	[  5,   6)    0    0.0%    1.0%  
+	[  6,   8)    0    0.0%    1.0%  
+	[  8,  11)    0    0.0%    1.0%  
+	[ 11,  16)    0    0.0%    1.0%  
+	[ 16,  22)    4    4.0%    5.0%  
+	[ 22,  31)    0    0.0%    5.0%  
+	[ 31,  44)    7    7.0%   12.0%  #
+	[ 44,  62)   14   14.0%   26.0%  #
+	[ 62,  87)   38   38.0%   64.0%  ####
+	[ 87, 121)   29   29.0%   93.0%  ###
+	[121, 169)    7    7.0%  100.0%  #
+	[169, 235)    0    0.0%  100.0%  
+	[235, 326)    0    0.0%  100.0%  
+	[326, 452)    0    0.0%  100.0%  
+	[452, inf)    0    0.0%  100.0%  
+Benchmark___1KB_mux___1K_chunks__10KB-2	     200	  38383294 ns/op	   0.05 MB/s
+--- Histogram (unit: ms)
+	Count: 200  Min: 1  Max: 81  Avg: 37.88
+	------------------------------------------------------------
+	[  1,   2)    1    0.5%    0.5%  
+	[  2,   3)   10    5.0%    5.5%  #
+	[  3,   4)    4    2.0%    7.5%  
+	[  4,   6)    3    1.5%    9.0%  
+	[  6,   9)    9    4.5%   13.5%  
+	[  9,  13)    3    1.5%   15.0%  
+	[ 13,  18)   12    6.0%   21.0%  #
+	[ 18,  25)    7    3.5%   24.5%  
+	[ 25,  35)   37   18.5%   43.0%  ##
+	[ 35,  48)   46   23.0%   66.0%  ##
+	[ 48,  66)   48   24.0%   90.0%  ##
+	[ 66,  90)   20   10.0%  100.0%  #
+	[ 90, 123)    0    0.0%  100.0%  
+	[123, 167)    0    0.0%  100.0%  
+	[167, 226)    0    0.0%  100.0%  
+	[226, 305)    0    0.0%  100.0%  
+	[305, inf)    0    0.0%  100.0%  
diff --git a/runtimes/google/ipc/client_test.go b/runtimes/google/ipc/client_test.go
index b91f8c0..548db9a 100644
--- a/runtimes/google/ipc/client_test.go
+++ b/runtimes/google/ipc/client_test.go
@@ -36,17 +36,12 @@
 	return ctx, shutdown
 }
 
-func testArgs(args ...string) []string {
-	var targs = []string{"--", "--veyron.tcp.address=127.0.0.1:0"}
-	return append(targs, args...)
-}
-
 func runMountTable(t *testing.T, ctx *context.T) (*modules.Shell, func()) {
 	sh, err := modules.NewShell(ctx, nil)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
+	root, err := sh.Start(core.RootMTCommand, nil)
 	if err != nil {
 		t.Fatalf("unexpected error for root mt: %s", err)
 	}
@@ -109,7 +104,7 @@
 
 	sh, fn := runMountTable(t, ctx)
 	defer fn()
-	srv, err := sh.Start(core.EchoServerCommand, nil, testArgs("echoServer", "echoServer")...)
+	srv, err := sh.Start(core.EchoServerCommand, nil, "echoServer", "echoServer")
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -172,7 +167,7 @@
 	defer shutdown()
 	veyron2.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
 
-	name := args[1]
+	name := args[0]
 	call, err := veyron2.GetClient(ctx).StartCall(ctx, name, "Ping", nil)
 	if err != nil {
 		fmt.Errorf("unexpected error: %s", err)
@@ -334,7 +329,7 @@
 	// backoff of some minutes.
 	startServer := func() {
 		time.Sleep(10 * time.Millisecond)
-		srv, _ := sh.Start(core.EchoServerCommand, nil, testArgs("message", name)...)
+		srv, _ := sh.Start(core.EchoServerCommand, nil, "message", name)
 		s := expect.NewSession(t, srv.Stdout(), time.Minute)
 		s.ExpectVar("PID")
 		s.ExpectVar("NAME")
@@ -495,7 +490,7 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	server, err := sh.Start(core.EchoServerCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0", "mymessage", "")
+	server, err := sh.Start(core.EchoServerCommand, nil, "--veyron.tcp.address=127.0.0.1:0", "mymessage", "")
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -536,7 +531,7 @@
 	// Resurrect the server with the same address, verify client
 	// re-establishes the connection. This is racy if another
 	// process grabs the port.
-	server, err = sh.Start(core.EchoServerCommand, nil, "--", "--veyron.tcp.address="+ep.Address, "mymessage again", "")
+	server, err = sh.Start(core.EchoServerCommand, nil, "--veyron.tcp.address="+ep.Address, "mymessage again", "")
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 2db17e4..3e85647 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -6,6 +6,7 @@
 	"fmt"
 	"io"
 	"net"
+	"os"
 	"path/filepath"
 	"reflect"
 	"runtime"
@@ -758,7 +759,7 @@
 type dischargeTestServer struct {
 	p       security.Principal
 	impetus []security.DischargeImpetus
-	traceid []uniqueid.ID
+	traceid []uniqueid.Id
 }
 
 func (s *dischargeTestServer) Discharge(ctx ipc.ServerContext, cav vdl.AnyRep, impetus security.DischargeImpetus) (vdl.AnyRep, error) {
@@ -767,7 +768,7 @@
 	return nil, fmt.Errorf("discharges not issued")
 }
 
-func (s *dischargeTestServer) Release() ([]security.DischargeImpetus, []uniqueid.ID) {
+func (s *dischargeTestServer) Release() ([]security.DischargeImpetus, []uniqueid.Id) {
 	impetus, traceid := s.impetus, s.traceid
 	s.impetus, s.traceid = nil, nil
 	return impetus, traceid
@@ -1745,6 +1746,10 @@
 }
 
 func init() {
-	testutil.Init()
 	vdl.Register(fakeTimeCaveat(0))
 }
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	os.Exit(m.Run())
+}
diff --git a/runtimes/google/ipc/proxy_test.go b/runtimes/google/ipc/proxy_test.go
new file mode 100644
index 0000000..08123c6
--- /dev/null
+++ b/runtimes/google/ipc/proxy_test.go
@@ -0,0 +1,330 @@
+package ipc_test
+
+import (
+	"fmt"
+	"os"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/ipc"
+	"v.io/core/veyron2/naming"
+	"v.io/core/veyron2/security"
+	verror "v.io/core/veyron2/verror2"
+	"v.io/core/veyron2/vtrace"
+
+	"v.io/core/veyron/lib/expect"
+	"v.io/core/veyron/lib/flags"
+	"v.io/core/veyron/lib/modules"
+	"v.io/core/veyron/lib/modules/core"
+	tsecurity "v.io/core/veyron/lib/testutil/security"
+	_ "v.io/core/veyron/profiles"
+	iipc "v.io/core/veyron/runtimes/google/ipc"
+	imanager "v.io/core/veyron/runtimes/google/ipc/stream/manager"
+	"v.io/core/veyron/runtimes/google/ipc/stream/vc"
+	inaming "v.io/core/veyron/runtimes/google/naming"
+	tnaming "v.io/core/veyron/runtimes/google/testing/mocks/naming"
+	ivtrace "v.io/core/veyron/runtimes/google/vtrace"
+)
+
+func testContext() *context.T {
+	ctx, _ := context.WithTimeout(testContextWithoutDeadline(), 20*time.Second)
+	return ctx
+}
+
+func testContextWithoutDeadline() *context.T {
+	ctx, _ := context.RootContext()
+	ctx, err := ivtrace.Init(ctx, flags.VtraceFlags{})
+	if err != nil {
+		panic(err)
+	}
+	ctx, _ = vtrace.SetNewTrace(ctx)
+	return ctx
+}
+
+type testServer struct{}
+
+func (*testServer) Echo(ctx ipc.ServerContext, arg string) string {
+	return fmt.Sprintf("method:%q,suffix:%q,arg:%q", ctx.Method(), ctx.Suffix(), arg)
+}
+
+type testServerAuthorizer struct{}
+
+func (testServerAuthorizer) Authorize(c security.Context) error {
+	return nil
+}
+
+type testServerDisp struct{ server interface{} }
+
+func (t testServerDisp) Lookup(suffix string) (interface{}, security.Authorizer, error) {
+	return t.server, testServerAuthorizer{}, nil
+}
+
+type proxyHandle struct {
+	ns    naming.Namespace
+	sh    *modules.Shell
+	proxy modules.Handle
+	name  string
+}
+
+func (h *proxyHandle) Start(t *testing.T, ctx *context.T, args ...string) error {
+	sh, err := modules.NewShell(nil, nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	h.sh = sh
+	p, err := sh.Start(core.ProxyServerCommand, nil, args...)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	h.proxy = p
+	s := expect.NewSession(t, p.Stdout(), time.Minute)
+	s.ReadLine()
+	h.name = s.ExpectVar("PROXY_NAME")
+	if len(h.name) == 0 {
+		t.Fatalf("failed to get PROXY_NAME from proxyd")
+	}
+	return h.ns.Mount(ctx, "proxy", h.name, time.Hour)
+}
+
+func (h *proxyHandle) Stop(ctx *context.T) error {
+	defer h.sh.Cleanup(os.Stderr, os.Stderr)
+	if err := h.proxy.Shutdown(os.Stderr, os.Stderr); err != nil {
+		return err
+	}
+	if len(h.name) == 0 {
+		return nil
+	}
+	return h.ns.Unmount(ctx, "proxy", h.name)
+}
+
+func TestProxyOnly(t *testing.T) {
+	listenSpec := ipc.ListenSpec{Proxy: "proxy"}
+	testProxy(t, listenSpec)
+}
+
+func TestProxy(t *testing.T) {
+	proxyListenSpec := ipc.ListenSpec{Addrs: ipc.ListenAddrs{{"tcp", "127.0.0.1:0"}}}
+	proxyListenSpec.Proxy = "proxy"
+	testProxy(t, proxyListenSpec)
+}
+
+func TestWSProxy(t *testing.T) {
+	proxyListenSpec := ipc.ListenSpec{Addrs: ipc.ListenAddrs{{"tcp", "127.0.0.1:0"}}}
+	proxyListenSpec.Proxy = "proxy"
+	// The proxy uses websockets only, but the server is using tcp.
+	testProxy(t, proxyListenSpec, "--veyron.tcp.protocol=ws")
+}
+
+func testProxy(t *testing.T, spec ipc.ListenSpec, args ...string) {
+	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
+	defer sm.Shutdown()
+	ns := tnaming.NewSimpleNamespace()
+	client, err := iipc.InternalNewClient(sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal("client")})
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer client.Close()
+	ctx := testContext()
+	server, err := iipc.InternalNewServer(ctx, sm, ns, nil, vc.LocalPrincipal{tsecurity.NewPrincipal("server")})
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer server.Stop()
+
+	// If no address is specified then we'll only 'listen' via
+	// the proxy.
+	hasLocalListener := len(spec.Addrs) > 0 && len(spec.Addrs[0].Address) != 0
+
+	name := "mountpoint/server/suffix"
+	makeCall := func() (string, error) {
+		ctx, _ := context.WithDeadline(testContext(), time.Now().Add(5*time.Second))
+		// Let's fail fast so that the tests don't take as long to run.
+		call, err := client.StartCall(ctx, name, "Echo", []interface{}{"batman"})
+		if err != nil {
+			// proxy is down, we should return here/.... prepend
+			// the error with a well known string so that we can test for that.
+			return "", fmt.Errorf("RESOLVE: %s", err)
+		}
+		var result string
+		if err = call.Finish(&result); err != nil {
+			return "", err
+		}
+		return result, nil
+	}
+	proxy := &proxyHandle{ns: ns}
+	if err := proxy.Start(t, ctx, args...); err != nil {
+		t.Fatal(err)
+	}
+	defer proxy.Stop(ctx)
+	addrs := verifyMount(t, ctx, ns, spec.Proxy)
+	if len(addrs) != 1 {
+		t.Fatalf("failed to lookup proxy")
+	}
+
+	eps, err := server.Listen(spec)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := server.ServeDispatcher("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
+		t.Fatal(err)
+	}
+
+	// Proxy connections are started asynchronously, so we need to wait..
+	waitForMountTable := func(ch chan int, expect int) {
+		then := time.Now().Add(time.Minute)
+		for {
+			me, err := ns.Resolve(ctx, name)
+			if err == nil && len(me.Servers) == expect {
+				ch <- 1
+				return
+			}
+			if time.Now().After(then) {
+				t.Fatalf("timed out")
+			}
+			time.Sleep(100 * time.Millisecond)
+		}
+	}
+	waitForServerStatus := func(ch chan int, proxy string) {
+		then := time.Now().Add(time.Minute)
+		for {
+			status := server.Status()
+			if len(status.Proxies) == 1 && status.Proxies[0].Proxy == proxy {
+				ch <- 2
+				return
+			}
+			if time.Now().After(then) {
+				t.Fatalf("timed out")
+			}
+			time.Sleep(100 * time.Millisecond)
+		}
+	}
+	proxyEP, _ := naming.SplitAddressName(addrs[0])
+	proxiedEP, err := inaming.NewEndpoint(proxyEP)
+	if err != nil {
+		t.Fatalf("unexpected error for %q: %s", proxyEP, err)
+	}
+	proxiedEP.RID = naming.FixedRoutingID(0x555555555)
+	expectedNames := []string{naming.JoinAddressName(proxiedEP.String(), "suffix")}
+	if hasLocalListener {
+		expectedNames = append(expectedNames, naming.JoinAddressName(eps[0].String(), "suffix"))
+	}
+
+	// Proxy connetions are created asynchronously, so we wait for the
+	// expected number of endpoints to appear for the specified service name.
+	ch := make(chan int, 2)
+	go waitForMountTable(ch, len(expectedNames))
+	go waitForServerStatus(ch, spec.Proxy)
+	select {
+	case <-time.After(time.Minute):
+		t.Fatalf("timedout waiting for two entries in the mount table and server status")
+	case i := <-ch:
+		select {
+		case <-time.After(time.Minute):
+			t.Fatalf("timedout waiting for two entries in the mount table or server status")
+		case j := <-ch:
+			if !((i == 1 && j == 2) || (i == 2 && j == 1)) {
+				t.Fatalf("unexpected return values from waiters")
+			}
+		}
+	}
+
+	status := server.Status()
+	if got, want := status.Proxies[0].Endpoint, proxiedEP; !reflect.DeepEqual(got, want) {
+		t.Fatalf("got %q, want %q", got, want)
+	}
+
+	got := []string{}
+	for _, s := range verifyMount(t, ctx, ns, name) {
+		got = append(got, s)
+	}
+	sort.Strings(got)
+	sort.Strings(expectedNames)
+	if !reflect.DeepEqual(got, expectedNames) {
+		t.Errorf("got %v, want %v", got, expectedNames)
+	}
+
+	if hasLocalListener {
+		// Listen will publish both the local and proxied endpoint with the
+		// mount table, given that we're trying to test the proxy, we remove
+		// the local endpoint from the mount table entry!  We have to remove both
+		// the tcp and the websocket address.
+		sep := eps[0].String()
+		ns.Unmount(ctx, "mountpoint/server", sep)
+	}
+
+	addrs = verifyMount(t, ctx, ns, name)
+	if len(addrs) != 1 {
+		t.Fatalf("failed to lookup proxy: addrs %v", addrs)
+	}
+
+	// Proxied endpoint should be published and RPC should succeed (through proxy)
+	const expected = `method:"Echo",suffix:"suffix",arg:"batman"`
+	if result, err := makeCall(); result != expected || err != nil {
+		t.Fatalf("Got (%v, %v) want (%v, nil)", result, err, expected)
+	}
+	// Proxy dies, calls should fail and the name should be unmounted.
+	if err := proxy.Stop(ctx); err != nil {
+		t.Fatal(err)
+	}
+
+	if result, err := makeCall(); err == nil || (!strings.HasPrefix(err.Error(), "RESOLVE") && !strings.Contains(err.Error(), "EOF")) {
+		t.Fatalf(`Got (%v, %v) want ("", "RESOLVE: <err>" or "EOF") as proxy is down`, result, err)
+	}
+
+	for {
+		if _, err := ns.Resolve(ctx, name); err != nil {
+			break
+		}
+		time.Sleep(10 * time.Millisecond)
+	}
+	verifyMountMissing(t, ctx, ns, name)
+
+	status = server.Status()
+	if len(status.Proxies) != 1 || status.Proxies[0].Proxy != spec.Proxy || !verror.Is(status.Proxies[0].Error, verror.NoServers.ID) {
+		t.Fatalf("proxy status is incorrect: %v", status.Proxies)
+	}
+
+	// Proxy restarts, calls should eventually start succeeding.
+	if err := proxy.Start(t, ctx, args...); err != nil {
+		t.Fatal(err)
+	}
+
+	retries := 0
+	for {
+		if result, err := makeCall(); err == nil {
+			if result != expected {
+				t.Errorf("Got (%v, %v) want (%v, nil)", result, err, expected)
+			}
+			break
+		} else {
+			retries++
+			if retries > 10 {
+				t.Fatalf("Failed after 10 attempts: err: %s", err)
+			}
+		}
+	}
+}
+
+func verifyMount(t *testing.T, ctx *context.T, ns naming.Namespace, name string) []string {
+	me, err := ns.Resolve(ctx, name)
+	if err != nil {
+		t.Errorf("%s not found in mounttable", name)
+		return nil
+	}
+	return me.Names()
+}
+
+func verifyMountMissing(t *testing.T, ctx *context.T, ns naming.Namespace, name string) {
+	if me, err := ns.Resolve(ctx, name); err == nil {
+		names := me.Names()
+		t.Errorf("%s not supposed to be found in mounttable; got %d servers instead: %v", name, len(names), names)
+	}
+}
+
+func TestHelperProcess(t *testing.T) {
+	modules.DispatchInTest()
+}
diff --git a/runtimes/google/ipc/resolve_test.go b/runtimes/google/ipc/resolve_test.go
index ece505c..d7b5261 100644
--- a/runtimes/google/ipc/resolve_test.go
+++ b/runtimes/google/ipc/resolve_test.go
@@ -17,7 +17,7 @@
 )
 
 func startMT(t *testing.T, sh *modules.Shell) string {
-	h, err := sh.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0")
+	h, err := sh.Start(core.RootMTCommand, nil, "--veyron.tcp.address=127.0.0.1:0")
 	if err != nil {
 		t.Fatalf("unexpected error for root mt: %s", err)
 	}
diff --git a/runtimes/google/ipc/results_store_test.go b/runtimes/google/ipc/results_store_test.go
index 5c31331..c41bdec 100644
--- a/runtimes/google/ipc/results_store_test.go
+++ b/runtimes/google/ipc/results_store_test.go
@@ -8,8 +8,6 @@
 	"v.io/core/veyron/lib/testutil"
 )
 
-func init() { testutil.Init() }
-
 func randomKeys() []uint64 {
 	n := (testutil.Rand.Intn(256*10) / 10) + 256
 	k := make([]uint64, n)
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index d83367a..728a4bf 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -1,12 +1,9 @@
 package ipc
 
 import (
-	"fmt"
 	"net"
-	"os"
 	"reflect"
 	"sort"
-	"strings"
 	"testing"
 	"time"
 
@@ -18,9 +15,6 @@
 	verror "v.io/core/veyron2/verror2"
 	"v.io/core/veyron2/vlog"
 
-	"v.io/core/veyron/lib/expect"
-	"v.io/core/veyron/lib/modules"
-	"v.io/core/veyron/lib/modules/core"
 	"v.io/core/veyron/lib/netstate"
 	tsecurity "v.io/core/veyron/lib/testutil/security"
 	imanager "v.io/core/veyron/runtimes/google/ipc/stream/manager"
@@ -90,252 +84,6 @@
 	}
 }
 
-type proxyHandle struct {
-	ns    naming.Namespace
-	sh    *modules.Shell
-	proxy modules.Handle
-	name  string
-}
-
-func (h *proxyHandle) Start(t *testing.T, args ...string) error {
-	sh, err := modules.NewShell(nil, nil)
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-	h.sh = sh
-	p, err := sh.Start(core.ProxyServerCommand, nil, args...)
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-	h.proxy = p
-	s := expect.NewSession(t, p.Stdout(), time.Minute)
-	s.ReadLine()
-	h.name = s.ExpectVar("PROXY_NAME")
-	if len(h.name) == 0 {
-		t.Fatalf("failed to get PROXY_NAME from proxyd")
-	}
-	return h.ns.Mount(testContext(), "proxy", h.name, time.Hour)
-}
-
-func (h *proxyHandle) Stop() error {
-	defer h.sh.Cleanup(os.Stderr, os.Stderr)
-	if err := h.proxy.Shutdown(os.Stderr, os.Stderr); err != nil {
-		return err
-	}
-	if len(h.name) == 0 {
-		return nil
-	}
-	return h.ns.Unmount(testContext(), "proxy", h.name)
-}
-
-func TestProxyOnly(t *testing.T) {
-	listenSpec := ipc.ListenSpec{Proxy: "proxy"}
-	testProxy(t, listenSpec, "--", "--veyron.tcp.address=127.0.0.1:0")
-}
-
-func TestProxy(t *testing.T) {
-	proxyListenSpec := listenSpec
-	proxyListenSpec.Proxy = "proxy"
-	testProxy(t, proxyListenSpec, "--", "--veyron.tcp.address=127.0.0.1:0")
-}
-
-func TestWSProxy(t *testing.T) {
-	proxyListenSpec := listenSpec
-	proxyListenSpec.Proxy = "proxy"
-	// The proxy uses websockets only, but the server is using tcp.
-	testProxy(t, proxyListenSpec, "--", "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0")
-}
-
-func testProxy(t *testing.T, spec ipc.ListenSpec, args ...string) {
-	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
-	defer sm.Shutdown()
-	ns := tnaming.NewSimpleNamespace()
-	client, err := InternalNewClient(sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal("client")})
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer client.Close()
-	ctx := testContext()
-	server, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal("server")})
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer server.Stop()
-
-	// If no address is specified then we'll only 'listen' via
-	// the proxy.
-	hasLocalListener := len(spec.Addrs) > 0 && len(spec.Addrs[0].Address) != 0
-
-	name := "mountpoint/server/suffix"
-	makeCall := func() (string, error) {
-		ctx, _ := context.WithDeadline(testContext(), time.Now().Add(5*time.Second))
-		// Let's fail fast so that the tests don't take as long to run.
-		call, err := client.StartCall(ctx, name, "Echo", []interface{}{"batman"})
-		if err != nil {
-			// proxy is down, we should return here/.... prepend
-			// the error with a well known string so that we can test for that.
-			return "", fmt.Errorf("RESOLVE: %s", err)
-		}
-		var result string
-		if err = call.Finish(&result); err != nil {
-			return "", err
-		}
-		return result, nil
-	}
-	proxy := &proxyHandle{ns: ns}
-	if err := proxy.Start(t, args...); err != nil {
-		t.Fatal(err)
-	}
-	defer proxy.Stop()
-	addrs := verifyMount(t, ns, spec.Proxy)
-	if len(addrs) != 1 {
-		t.Fatalf("failed to lookup proxy")
-	}
-
-	eps, err := server.Listen(spec)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err := server.ServeDispatcher("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
-		t.Fatal(err)
-	}
-
-	// Proxy connections are started asynchronously, so we need to wait..
-	waitForMountTable := func(ch chan int, expect int) {
-		then := time.Now().Add(time.Minute)
-		for {
-			me, err := ns.Resolve(testContext(), name)
-			if err == nil && len(me.Servers) == expect {
-				ch <- 1
-				return
-			}
-			if time.Now().After(then) {
-				t.Fatalf("timed out")
-			}
-			time.Sleep(100 * time.Millisecond)
-		}
-	}
-	waitForServerStatus := func(ch chan int, proxy string) {
-		then := time.Now().Add(time.Minute)
-		for {
-			status := server.Status()
-			if len(status.Proxies) == 1 && status.Proxies[0].Proxy == proxy {
-				ch <- 2
-				return
-			}
-			if time.Now().After(then) {
-				t.Fatalf("timed out")
-			}
-			time.Sleep(100 * time.Millisecond)
-		}
-	}
-	proxyEP, _ := naming.SplitAddressName(addrs[0])
-	proxiedEP, err := inaming.NewEndpoint(proxyEP)
-	if err != nil {
-		t.Fatalf("unexpected error for %q: %s", proxyEP, err)
-	}
-	proxiedEP.RID = naming.FixedRoutingID(0x555555555)
-	expectedNames := []string{naming.JoinAddressName(proxiedEP.String(), "suffix")}
-	if hasLocalListener {
-		expectedNames = append(expectedNames, naming.JoinAddressName(eps[0].String(), "suffix"))
-	}
-
-	// Proxy connetions are created asynchronously, so we wait for the
-	// expected number of endpoints to appear for the specified service name.
-	ch := make(chan int, 2)
-	go waitForMountTable(ch, len(expectedNames))
-	go waitForServerStatus(ch, spec.Proxy)
-	select {
-	case <-time.After(time.Minute):
-		t.Fatalf("timedout waiting for two entries in the mount table and server status")
-	case i := <-ch:
-		select {
-		case <-time.After(time.Minute):
-			t.Fatalf("timedout waiting for two entries in the mount table or server status")
-		case j := <-ch:
-			if !((i == 1 && j == 2) || (i == 2 && j == 1)) {
-				t.Fatalf("unexpected return values from waiters")
-			}
-		}
-	}
-
-	status := server.Status()
-	if got, want := status.Proxies[0].Endpoint, proxiedEP; !reflect.DeepEqual(got, want) {
-		t.Fatalf("got %q, want %q", got, want)
-	}
-
-	got := []string{}
-	for _, s := range verifyMount(t, ns, name) {
-		got = append(got, s)
-	}
-	sort.Strings(got)
-	sort.Strings(expectedNames)
-	if !reflect.DeepEqual(got, expectedNames) {
-		t.Errorf("got %v, want %v", got, expectedNames)
-	}
-
-	if hasLocalListener {
-		// Listen will publish both the local and proxied endpoint with the
-		// mount table, given that we're trying to test the proxy, we remove
-		// the local endpoint from the mount table entry!  We have to remove both
-		// the tcp and the websocket address.
-		sep := eps[0].String()
-		ns.Unmount(testContext(), "mountpoint/server", sep)
-	}
-
-	addrs = verifyMount(t, ns, name)
-	if len(addrs) != 1 {
-		t.Fatalf("failed to lookup proxy: addrs %v", addrs)
-	}
-
-	// Proxied endpoint should be published and RPC should succeed (through proxy)
-	const expected = `method:"Echo",suffix:"suffix",arg:"batman"`
-	if result, err := makeCall(); result != expected || err != nil {
-		t.Fatalf("Got (%v, %v) want (%v, nil)", result, err, expected)
-	}
-	// Proxy dies, calls should fail and the name should be unmounted.
-	if err := proxy.Stop(); err != nil {
-		t.Fatal(err)
-	}
-
-	if result, err := makeCall(); err == nil || (!strings.HasPrefix(err.Error(), "RESOLVE") && !strings.Contains(err.Error(), "EOF")) {
-		t.Fatalf(`Got (%v, %v) want ("", "RESOLVE: <err>" or "EOF") as proxy is down`, result, err)
-	}
-
-	for {
-		if _, err := ns.Resolve(testContext(), name); err != nil {
-			break
-		}
-		time.Sleep(10 * time.Millisecond)
-	}
-	verifyMountMissing(t, ns, name)
-
-	status = server.Status()
-	if len(status.Proxies) != 1 || status.Proxies[0].Proxy != spec.Proxy || !verror.Is(status.Proxies[0].Error, verror.NoServers.ID) {
-		t.Fatalf("proxy status is incorrect: %v", status.Proxies)
-	}
-
-	// Proxy restarts, calls should eventually start succeeding.
-	if err := proxy.Start(t, args...); err != nil {
-		t.Fatal(err)
-	}
-
-	retries := 0
-	for {
-		if result, err := makeCall(); err == nil {
-			if result != expected {
-				t.Errorf("Got (%v, %v) want (%v, nil)", result, err, expected)
-			}
-			break
-		} else {
-			retries++
-			if retries > 10 {
-				t.Fatalf("Failed after 10 attempts: err: %s", err)
-			}
-		}
-	}
-}
-
 func TestServerArgs(t *testing.T) {
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	defer sm.Shutdown()
@@ -382,11 +130,12 @@
 }
 
 func TestServerStatus(t *testing.T) {
+	ctx := testContext()
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	defer sm.Shutdown()
 	ns := tnaming.NewSimpleNamespace()
 	principal := vc.LocalPrincipal{tsecurity.NewPrincipal("testServerStatus")}
-	server, err := testInternalNewServer(testContext(), sm, ns, principal)
+	server, err := testInternalNewServer(ctx, sm, ns, principal)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -414,12 +163,12 @@
 	progress := make(chan error)
 
 	client, err := InternalNewClient(sm, ns, principal)
-	makeCall := func() {
-		call, err := client.StartCall(testContext(), "test", "Hang", nil)
+	makeCall := func(ctx *context.T) {
+		call, err := client.StartCall(ctx, "test", "Hang", nil)
 		progress <- err
 		progress <- call.Finish()
 	}
-	go makeCall()
+	go makeCall(ctx)
 
 	// Wait for RPC to start
 	if err := <-progress; err != nil {
@@ -473,6 +222,7 @@
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	defer sm.Shutdown()
 	ns := tnaming.NewSimpleNamespace()
+	ctx := testContext()
 
 	expectBadState := func(err error) {
 		if !verror.Is(err, verror.BadState.ID) {
@@ -486,7 +236,7 @@
 		}
 	}
 
-	server, err := testInternalNewServer(testContext(), sm, ns)
+	server, err := testInternalNewServer(ctx, sm, ns)
 	expectNoError(err)
 	defer server.Stop()
 
@@ -873,8 +623,3 @@
 	}
 
 }
-
-// Required by modules framework.
-func TestHelperProcess(t *testing.T) {
-	modules.DispatchInTest()
-}
diff --git a/runtimes/google/ipc/signature_test.go b/runtimes/google/ipc/signature_test.go
index bd54d06..7dcc056 100644
--- a/runtimes/google/ipc/signature_test.go
+++ b/runtimes/google/ipc/signature_test.go
@@ -17,8 +17,6 @@
 	_ "v.io/core/veyron/profiles"
 )
 
-func init() { testutil.Init() }
-
 func startSigServer(ctx *context.T, sig sigImpl) (string, func(), error) {
 	server, err := veyron2.NewServer(ctx)
 	if err != nil {
diff --git a/runtimes/google/ipc/stream/benchmark/RESULTS.txt b/runtimes/google/ipc/stream/benchmark/RESULTS.txt
index b60e4ed..85c78ee 100644
--- a/runtimes/google/ipc/stream/benchmark/RESULTS.txt
+++ b/runtimes/google/ipc/stream/benchmark/RESULTS.txt
@@ -1,72 +1,82 @@
-Date: 01/06/2015
+Date: 01/30/2015
 Platform: Intel(R) Xeon(R) CPU E5-2689 0 @ 2.60GHz,  66114888KB Memory
 
 $ v23 go test -bench=. -cpu=1 -benchtime=5s \
   v.io/core/veyron/runtimes/google/ipc/stream/benchmark
 
-Benchmark_dial_VIF	  500000	     15356 ns/op
+Benchmark_dial_VIF	  500000	     14292 ns/op
 --- Histogram (unit: s)
-	Count: 500000  Min: 4  Max: 15644  Avg: 14.66
+	Count: 500000  Min: 4  Max: 16455  Avg: 13.58
 	------------------------------------------------------------
-	[    4,     5)   47181    9.4%    9.4%  #
-	[    5,     6)  314973   63.0%   72.4%  ######
-	[    6,     9)  123582   24.7%   97.1%  ##
-	[    9,    15)   10991    2.2%   99.3%  
-	[   15,    28)    2038    0.4%   99.8%  
-	[   28,    53)     129    0.0%   99.8%  
-	[   53,   100)      53    0.0%   99.8%  
-	[  100,   190)      12    0.0%   99.8%  
-	[  190,   362)       0    0.0%   99.8%  
-	[  362,   690)       1    0.0%   99.8%  
-	[  690,  1315)      38    0.0%   99.8%  
-	[ 1315,  2505)     165    0.0%   99.8%  
-	[ 2505,  4771)     487    0.1%   99.9%  
-	[ 4771,  9086)     326    0.1%  100.0%  
-	[ 9086, 17301)      24    0.0%  100.0%  
-	[17301, 32941)       0    0.0%  100.0%  
-	[32941,   inf)       0    0.0%  100.0%  
-Benchmark_dial_VIF_TLS	     500	  12681088 ns/op
+	[    4,     5)  139232   27.8%   27.8%  ###
+	[    5,     6)  257818   51.6%   79.4%  #####
+	[    6,     9)   92644   18.5%   97.9%  ##
+	[    9,    15)    5963    1.2%   99.1%  
+	[   15,    28)    3162    0.6%   99.8%  
+	[   28,    53)     171    0.0%   99.8%  
+	[   53,   101)      67    0.0%   99.8%  
+	[  101,   193)       1    0.0%   99.8%  
+	[  193,   370)       0    0.0%   99.8%  
+	[  370,   708)       0    0.0%   99.8%  
+	[  708,  1354)      57    0.0%   99.8%  
+	[ 1354,  2589)     152    0.0%   99.9%  
+	[ 2589,  4949)     393    0.1%   99.9%  
+	[ 4949,  9457)     322    0.1%  100.0%  
+	[ 9457, 18069)      18    0.0%  100.0%  
+	[18069, 34520)       0    0.0%  100.0%  
+	[34520,   inf)       0    0.0%  100.0%  
+Benchmark_dial_VIF_TLS	     500	  12594281 ns/op
 --- Histogram (unit: ms)
-	Count: 500  Min: 12  Max: 16  Avg: 12.31
+	Count: 500  Min: 12  Max: 14  Avg: 12.31
 	------------------------------------------------------------
-	[ 12,  13)  357   71.4%   71.4%  #######
-	[ 13,  14)  133   26.6%   98.0%  ###
-	[ 14,  15)    7    1.4%   99.4%  
-	[ 15,  16)    2    0.4%   99.8%  
-	[ 16, inf)    1    0.2%  100.0%  
-Benchmark_dial_VC_TLS	     500	  16224331 ns/op
+	[ 12,  13)  352   70.4%   70.4%  #######
+	[ 13,  14)  141   28.2%   98.6%  ###
+	[ 14, inf)    7    1.4%  100.0%  
+Benchmark_dial_VC_TLS	     500	  16116072 ns/op
 --- Histogram (unit: ms)
-	Count: 500  Min: 15  Max: 22  Avg: 15.60
+	Count: 500  Min: 15  Max: 22  Avg: 15.53
 	------------------------------------------------------------
-	[ 15,  16)  279   55.8%   55.8%  ######
-	[ 16,  17)  152   30.4%   86.2%  ###
-	[ 17,  18)   62   12.4%   98.6%  #
-	[ 18,  19)    6    1.2%   99.8%  
-	[ 19,  20)    0    0.0%   99.8%  
+	[ 15,  16)  313   62.6%   62.6%  ######
+	[ 16,  17)  121   24.2%   86.8%  ##
+	[ 17,  18)   60   12.0%   98.8%  #
+	[ 18,  19)    3    0.6%   99.4%  
+	[ 19,  20)    2    0.4%   99.8%  
 	[ 20,  21)    0    0.0%   99.8%  
 	[ 21,  23)    1    0.2%  100.0%  
 	[ 23, inf)    0    0.0%  100.0%  
-Benchmark_throughput_TCP_1Conn	 1000000	     10963 ns/op	4669.96 MB/s
-Benchmark_throughput_TCP_2Conns	 1000000	      9739 ns/op	5257.14 MB/s
-Benchmark_throughput_TCP_4Conns	  500000	     11896 ns/op	4303.82 MB/s
-Benchmark_throughput_TCP_8Conns	  500000	     12867 ns/op	3979.12 MB/s
-Benchmark_throughput_Pipe_1Conn	  300000	     28233 ns/op	1813.43 MB/s
-Benchmark_throughput_Pipe_2Conns	  500000	     25339 ns/op	2020.60 MB/s
-Benchmark_throughput_Pipe_4Conns	  300000	     26626 ns/op	1922.90 MB/s
-Benchmark_throughput_Pipe_8Conns	  500000	     27340 ns/op	1872.67 MB/s
-Benchmark_throughput_Flow_1VIF_1VC_1Flow	  200000	     32590 ns/op	1571.02 MB/s
-Benchmark_throughput_Flow_1VIF_1VC_2Flow	  200000	     32731 ns/op	1564.24 MB/s
-Benchmark_throughput_Flow_1VIF_1VC_8Flow	  200000	     41289 ns/op	1240.03 MB/s
-Benchmark_throughput_Flow_1VIF_2VC_2Flow	  200000	     33878 ns/op	1511.30 MB/s
-Benchmark_throughput_Flow_1VIF_2VC_8Flow	  200000	     40923 ns/op	1251.10 MB/s
-Benchmark_throughput_Flow_2VIF_4VC_8Flow	  200000	     42293 ns/op	1210.60 MB/s
-Benchmark_throughput_TLS_1Conn	   20000	    426157 ns/op	 120.14 MB/s
-Benchmark_throughput_TLS_2Conns	   20000	    421319 ns/op	 121.52 MB/s
-Benchmark_throughput_TLS_4Conns	   20000	    425284 ns/op	 120.39 MB/s
-Benchmark_throughput_TLS_8Conns	   20000	    426533 ns/op	 120.04 MB/s
-Benchmark_throughput_Flow_1VIF_1VC_1FlowTLS	   20000	    474126 ns/op	 107.99 MB/s
-Benchmark_throughput_Flow_1VIF_1VC_2FlowTLS	   20000	    472005 ns/op	 108.47 MB/s
-Benchmark_throughput_Flow_1VIF_1VC_8FlowTLS	   20000	    484625 ns/op	 105.65 MB/s
-Benchmark_throughput_Flow_1VIF_2VC_2FlowTLS	   20000	    483762 ns/op	 105.84 MB/s
-Benchmark_throughput_Flow_1VIF_2VC_8FlowTLS	   20000	    485164 ns/op	 105.53 MB/s
-Benchmark_throughput_Flow_2VIF_4VC_8FlowTLS	   20000	    493864 ns/op	 103.67 MB/s
+Benchmark_throughput_TCP_1Conn	 1000000	      9197 ns/op	5566.89 MB/s
+Benchmark_throughput_TCP_2Conns	 1000000	      9083 ns/op	5636.56 MB/s
+Benchmark_throughput_TCP_4Conns	 1000000	      9855 ns/op	5194.81 MB/s
+Benchmark_throughput_TCP_8Conns	  500000	     12541 ns/op	4082.43 MB/s
+Benchmark_throughput_WS_1Conn	   30000	    206804 ns/op	 247.58 MB/s
+Benchmark_throughput_WS_2Conns	   30000	    211842 ns/op	 241.69 MB/s
+Benchmark_throughput_WS_4Conns	   30000	    209994 ns/op	 243.82 MB/s
+Benchmark_throughput_WS_8Conns	   30000	    217110 ns/op	 235.83 MB/s
+Benchmark_throughput_WSH_TCP_1Conn	 1000000	      9322 ns/op	5491.85 MB/s
+Benchmark_throughput_WSH_TCP_2Conns	 1000000	      9370 ns/op	5463.77 MB/s
+Benchmark_throughput_WSH_TCP_4Conns	 1000000	      9466 ns/op	5408.50 MB/s
+Benchmark_throughput_WSH_TCP_8Conns	  500000	     12526 ns/op	4087.22 MB/s
+Benchmark_throughput_WSH_WS_1Conn	   30000	    207833 ns/op	 246.35 MB/s
+Benchmark_throughput_WSH_WS_2Conns	   30000	    208567 ns/op	 245.48 MB/s
+Benchmark_throughput_WSH_WS_4Conns	   30000	    211562 ns/op	 242.01 MB/s
+Benchmark_throughput_WSH_WS_8Conns	   30000	    216454 ns/op	 236.54 MB/s
+Benchmark_throughput_Pipe_1Conn	  500000	     20169 ns/op	2538.54 MB/s
+Benchmark_throughput_Pipe_2Conns	  500000	     19935 ns/op	2568.29 MB/s
+Benchmark_throughput_Pipe_4Conns	  300000	     19893 ns/op	2573.76 MB/s
+Benchmark_throughput_Pipe_8Conns	 1000000	     20235 ns/op	2530.22 MB/s
+Benchmark_throughput_Flow_1VIF_1VC_1Flow	  300000	     28014 ns/op	1827.66 MB/s
+Benchmark_throughput_Flow_1VIF_1VC_2Flow	  300000	     27495 ns/op	1862.09 MB/s
+Benchmark_throughput_Flow_1VIF_1VC_8Flow	  200000	     35584 ns/op	1438.84 MB/s
+Benchmark_throughput_Flow_1VIF_2VC_2Flow	  300000	     27665 ns/op	1850.66 MB/s
+Benchmark_throughput_Flow_1VIF_2VC_8Flow	  200000	     34974 ns/op	1463.94 MB/s
+Benchmark_throughput_Flow_2VIF_4VC_8Flow	  200000	     37642 ns/op	1360.15 MB/s
+Benchmark_throughput_TLS_1Conn	   20000	    415149 ns/op	 123.33 MB/s
+Benchmark_throughput_TLS_2Conns	   20000	    416008 ns/op	 123.07 MB/s
+Benchmark_throughput_TLS_4Conns	   20000	    421083 ns/op	 121.59 MB/s
+Benchmark_throughput_TLS_8Conns	   20000	    423079 ns/op	 121.02 MB/s
+Benchmark_throughput_Flow_1VIF_1VC_1FlowTLS	   20000	    466212 ns/op	 109.82 MB/s
+Benchmark_throughput_Flow_1VIF_1VC_2FlowTLS	   20000	    466104 ns/op	 109.85 MB/s
+Benchmark_throughput_Flow_1VIF_1VC_8FlowTLS	   20000	    476604 ns/op	 107.43 MB/s
+Benchmark_throughput_Flow_1VIF_2VC_2FlowTLS	   20000	    466818 ns/op	 109.68 MB/s
+Benchmark_throughput_Flow_1VIF_2VC_8FlowTLS	   20000	    477094 ns/op	 107.32 MB/s
+Benchmark_throughput_Flow_2VIF_4VC_8FlowTLS	   20000	    476370 ns/op	 107.48 MB/s
diff --git a/runtimes/google/ipc/stream/benchmark/throughput_test.go b/runtimes/google/ipc/stream/benchmark/throughput_test.go
index 76ad57d..f97b6e9 100644
--- a/runtimes/google/ipc/stream/benchmark/throughput_test.go
+++ b/runtimes/google/ipc/stream/benchmark/throughput_test.go
@@ -7,6 +7,21 @@
 func Benchmark_throughput_TCP_4Conns(b *testing.B) { benchmarkTCP(b, 4) }
 func Benchmark_throughput_TCP_8Conns(b *testing.B) { benchmarkTCP(b, 8) }
 
+func Benchmark_throughput_WS_1Conn(b *testing.B)  { benchmarkWS(b, 1) }
+func Benchmark_throughput_WS_2Conns(b *testing.B) { benchmarkWS(b, 2) }
+func Benchmark_throughput_WS_4Conns(b *testing.B) { benchmarkWS(b, 4) }
+func Benchmark_throughput_WS_8Conns(b *testing.B) { benchmarkWS(b, 8) }
+
+func Benchmark_throughput_WSH_TCP_1Conn(b *testing.B)  { benchmarkWSH(b, "tcp", 1) }
+func Benchmark_throughput_WSH_TCP_2Conns(b *testing.B) { benchmarkWSH(b, "tcp", 2) }
+func Benchmark_throughput_WSH_TCP_4Conns(b *testing.B) { benchmarkWSH(b, "tcp", 4) }
+func Benchmark_throughput_WSH_TCP_8Conns(b *testing.B) { benchmarkWSH(b, "tcp", 8) }
+
+func Benchmark_throughput_WSH_WS_1Conn(b *testing.B)  { benchmarkWSH(b, "ws", 1) }
+func Benchmark_throughput_WSH_WS_2Conns(b *testing.B) { benchmarkWSH(b, "ws", 2) }
+func Benchmark_throughput_WSH_WS_4Conns(b *testing.B) { benchmarkWSH(b, "ws", 4) }
+func Benchmark_throughput_WSH_WS_8Conns(b *testing.B) { benchmarkWSH(b, "ws", 8) }
+
 func Benchmark_throughput_Pipe_1Conn(b *testing.B)  { benchmarkPipe(b, 1) }
 func Benchmark_throughput_Pipe_2Conns(b *testing.B) { benchmarkPipe(b, 2) }
 func Benchmark_throughput_Pipe_4Conns(b *testing.B) { benchmarkPipe(b, 4) }
diff --git a/runtimes/google/ipc/stream/benchmark/throughput_ws.go b/runtimes/google/ipc/stream/benchmark/throughput_ws.go
new file mode 100644
index 0000000..aa07582
--- /dev/null
+++ b/runtimes/google/ipc/stream/benchmark/throughput_ws.go
@@ -0,0 +1,60 @@
+package benchmark
+
+import (
+	"io"
+	"net"
+	"testing"
+
+	"v.io/core/veyron/lib/websocket"
+)
+
+// benchmarkWS sets up nConns WS connections and measures throughput.
+func benchmarkWS(b *testing.B, nConns int) {
+	rchan := make(chan net.Conn, nConns)
+	wchan := make(chan net.Conn, nConns)
+	ln, err := websocket.Listener("ws", "127.0.0.1:0")
+	if err != nil {
+		b.Fatalf("websocket.Listener failed: %v", err)
+		return
+	}
+	defer ln.Close()
+	// One goroutine to dial nConns connections.
+	go func() {
+		for i := 0; i < nConns; i++ {
+			conn, err := websocket.Dial("ws", ln.Addr().String(), 0)
+			if err != nil {
+				b.Fatalf("websocket.Dial(%q, %q) failed: %v", "ws", ln.Addr(), err)
+				wchan <- nil
+				return
+			}
+			wchan <- conn
+		}
+		close(wchan)
+	}()
+	// One goroutine to accept nConns connections.
+	go func() {
+		for i := 0; i < nConns; i++ {
+			conn, err := ln.Accept()
+			if err != nil {
+				b.Fatalf("Accept failed: %v", err)
+				rchan <- nil
+				return
+			}
+			rchan <- conn
+		}
+		close(rchan)
+	}()
+
+	var readers []io.ReadCloser
+	var writers []io.WriteCloser
+	for r := range rchan {
+		readers = append(readers, r)
+	}
+	for w := range wchan {
+		writers = append(writers, w)
+	}
+	if b.Failed() {
+		return
+	}
+	(&throughputTester{b: b, readers: readers, writers: writers}).Run()
+}
diff --git a/runtimes/google/ipc/stream/benchmark/throughput_wsh.go b/runtimes/google/ipc/stream/benchmark/throughput_wsh.go
new file mode 100644
index 0000000..58066a9
--- /dev/null
+++ b/runtimes/google/ipc/stream/benchmark/throughput_wsh.go
@@ -0,0 +1,75 @@
+package benchmark
+
+import (
+	"io"
+	"net"
+	"testing"
+
+	"v.io/core/veyron/lib/websocket"
+)
+
+// benchmarkWS sets up nConns WS connections and measures throughput.
+func benchmarkWSH(b *testing.B, protocol string, nConns int) {
+	rchan := make(chan net.Conn, nConns)
+	wchan := make(chan net.Conn, nConns)
+	ln, err := websocket.HybridListener("wsh", "127.0.0.1:0")
+	if err != nil {
+		b.Fatalf("websocket.HybridListener failed: %v", err)
+		return
+	}
+	defer ln.Close()
+	// One goroutine to dial nConns connections.
+	go func() {
+		for i := 0; i < nConns; i++ {
+			var conn net.Conn
+			var err error
+			switch protocol {
+			case "tcp":
+				conn, err = net.Dial("tcp", ln.Addr().String())
+			case "ws":
+				conn, err = websocket.Dial("ws", ln.Addr().String(), 0)
+			}
+			if err != nil {
+				b.Fatalf("Dial(%q, %q) failed: %v", protocol, ln.Addr(), err)
+				wchan <- nil
+				return
+			}
+			if protocol == "tcp" {
+				// Write a dummy byte since wsh waits for magic byte forever.
+				conn.Write([]byte("."))
+			}
+			wchan <- conn
+		}
+		close(wchan)
+	}()
+	// One goroutine to accept nConns connections.
+	go func() {
+		for i := 0; i < nConns; i++ {
+			conn, err := ln.Accept()
+			if err != nil {
+				b.Fatalf("Accept failed: %v", err)
+				rchan <- nil
+				return
+			}
+			if protocol == "tcp" {
+				// Read a dummy byte.
+				conn.Read(make([]byte, 1))
+			}
+			rchan <- conn
+		}
+		close(rchan)
+	}()
+
+	var readers []io.ReadCloser
+	var writers []io.WriteCloser
+	for r := range rchan {
+		readers = append(readers, r)
+	}
+	for w := range wchan {
+		writers = append(writers, w)
+	}
+	if b.Failed() {
+		return
+	}
+	(&throughputTester{b: b, readers: readers, writers: writers}).Run()
+}
diff --git a/runtimes/google/ipc/stream/crypto/tls.go b/runtimes/google/ipc/stream/crypto/tls.go
index da35acc..fafa18c 100644
--- a/runtimes/google/ipc/stream/crypto/tls.go
+++ b/runtimes/google/ipc/stream/crypto/tls.go
@@ -166,6 +166,7 @@
 }
 
 func (c *tlsCrypter) Decrypt(ciphertext *iobuf.Slice) (*iobuf.Slice, error) {
+	defer ciphertext.Release()
 	if ciphertext.Size() == 0 {
 		return ciphertext, nil
 	}
diff --git a/runtimes/google/ipc/stream/manager/manager.go b/runtimes/google/ipc/stream/manager/manager.go
index f76a522..7b2b05c 100644
--- a/runtimes/google/ipc/stream/manager/manager.go
+++ b/runtimes/google/ipc/stream/manager/manager.go
@@ -138,6 +138,7 @@
 		if !retry || verror.ErrorID(err) != verror.Aborted {
 			return vc, err
 		}
+		vf.Close()
 		m.vifs.Delete(vf)
 		vlog.VI(2).Infof("VIF %v is closed, removing from cache", vf)
 	}
diff --git a/runtimes/google/ipc/stream/manager/manager_test.go b/runtimes/google/ipc/stream/manager/manager_test.go
index e1fb7b4..861b3f4 100644
--- a/runtimes/google/ipc/stream/manager/manager_test.go
+++ b/runtimes/google/ipc/stream/manager/manager_test.go
@@ -555,7 +555,7 @@
 
 func runServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	server := InternalNew(naming.FixedRoutingID(0x55555555))
-	_, ep, err := server.Listen(args[1], args[2])
+	_, ep, err := server.Listen(args[0], args[1])
 	if err != nil {
 		fmt.Fprintln(stderr, err)
 		return err
diff --git a/runtimes/google/ipc/stream/proxy/proxy.go b/runtimes/google/ipc/stream/proxy/proxy.go
index a498b4b..2b79f97 100644
--- a/runtimes/google/ipc/stream/proxy/proxy.go
+++ b/runtimes/google/ipc/stream/proxy/proxy.go
@@ -46,15 +46,18 @@
 // process encapsulates the physical network connection and the routing table
 // associated with the process at the other end of the network connection.
 type process struct {
-	Conn         net.Conn
+	proxy        *Proxy
+	conn         net.Conn
+	pool         *iobuf.Pool
+	reader       *iobuf.Reader
 	isSetup      bool
 	ctrlCipher   crypto.ControlCipher
-	Queue        *upcqueue.T
+	queue        *upcqueue.T
 	mu           sync.RWMutex
 	routingTable map[id.VC]*destination
 	nextVCI      id.VC
 	servers      map[id.VC]*vc.VC // servers wishing to be proxied create a VC that terminates at the proxy
-	BQ           bqueue.T         // Flow control for messages sent on behalf of servers.
+	bq           bqueue.T         // Flow control for messages sent on behalf of servers.
 }
 
 // destination is an entry in the routingtable of a process.
@@ -70,6 +73,7 @@
 }
 
 func (s *server) RoutingID() naming.RoutingID { return s.VC.RemoteAddr().RoutingID() }
+
 func (s *server) Close(err error) {
 	if vc := s.Process.RemoveServerVC(s.VC.VCI()); vc != nil {
 		if err != nil {
@@ -80,6 +84,7 @@
 		s.Process.SendCloseVC(s.VC.VCI(), err)
 	}
 }
+
 func (s *server) String() string {
 	return fmt.Sprintf("RoutingID %v on process %v (VCI:%v Blessings:%v)", s.RoutingID(), s.Process, s.VC.VCI(), s.VC.RemoteBlessings())
 }
@@ -102,6 +107,7 @@
 	proxyLog().Infof("Started proxying server: %v", server)
 	return nil
 }
+
 func (m *servermap) Remove(server *server) {
 	key := server.RoutingID()
 	m.mu.Lock()
@@ -111,6 +117,7 @@
 	}
 	m.mu.Unlock()
 }
+
 func (m *servermap) Process(rid naming.RoutingID) *process {
 	m.mu.Lock()
 	defer m.mu.Unlock()
@@ -119,6 +126,7 @@
 	}
 	return nil
 }
+
 func (m *servermap) List() []string {
 	m.mu.Lock()
 	defer m.mu.Unlock()
@@ -168,220 +176,36 @@
 }
 
 func (p *Proxy) acceptProcess(conn net.Conn) {
+	pool := iobuf.NewPool(0)
 	process := &process{
-		Conn:         conn,
+		proxy:        p,
+		conn:         conn,
+		pool:         pool,
+		reader:       iobuf.NewReader(pool, conn),
 		ctrlCipher:   &crypto.NullControlCipher{},
-		Queue:        upcqueue.New(),
+		queue:        upcqueue.New(),
 		routingTable: make(map[id.VC]*destination),
 		servers:      make(map[id.VC]*vc.VC),
-		BQ:           drrqueue.New(vc.MaxPayloadSizeBytes),
+		bq:           drrqueue.New(vc.MaxPayloadSizeBytes),
 	}
-	go writeLoop(process)
-	go serverVCsLoop(process)
-	go p.readLoop(process)
-}
 
-func writeLoop(process *process) {
-	defer processLog().Infof("Exited writeLoop for %v", process)
-	defer process.Close()
-	for {
-		item, err := process.Queue.Get(nil)
-		if err != nil {
-			if err != upcqueue.ErrQueueIsClosed {
-				processLog().Infof("upcqueue.Get failed on %v: %v", process, err)
-			}
-			return
-		}
-		if err = message.WriteTo(process.Conn, item.(message.T), process.ctrlCipher); err != nil {
-			processLog().Infof("message.WriteTo on %v failed: %v", process, err)
-			return
-		}
-	}
-}
-func serverVCsLoop(process *process) {
-	for {
-		w, bufs, err := process.BQ.Get(nil)
-		if err != nil {
-			return
-		}
-		vci, fid := unpackIDs(w.ID())
-		if vc := process.ServerVC(vci); vc != nil {
-			queueDataMessages(bufs, vc, fid, process.Queue)
-			if len(bufs) == 0 {
-				m := &message.Data{VCI: vci, Flow: fid}
-				m.SetClose()
-				process.Queue.Put(m)
-				w.Shutdown(true)
-			}
-			continue
-		}
-		releaseBufs(0, bufs)
-	}
-}
-func releaseBufs(start int, bufs []*iobuf.Slice) {
-	for i := start; i < len(bufs); i++ {
-		bufs[i].Release()
-	}
-}
-func queueDataMessages(bufs []*iobuf.Slice, vc *vc.VC, fid id.Flow, q *upcqueue.T) {
-	for ix, b := range bufs {
-		m := &message.Data{VCI: vc.VCI(), Flow: fid}
-		var err error
-		if m.Payload, err = vc.Encrypt(fid, b); err != nil {
-			msgLog().Infof("vc.Encrypt failed. VC:%v Flow:%v Error:%v", vc, fid, err)
-			releaseBufs(ix+1, bufs)
-			return
-		}
-		if err = q.Put(m); err != nil {
-			msgLog().Infof("Failed to enqueue data message %v: %v", m, err)
-			m.Release()
-			releaseBufs(ix+1, bufs)
-			return
-		}
-	}
-}
-func (p *Proxy) startProcess(process *process) {
 	p.mu.Lock()
 	p.processes[process] = struct{}{}
 	p.mu.Unlock()
+
+	go process.serverVCsLoop()
+	go process.writeLoop()
+	go process.readLoop()
+
 	processLog().Infof("Started process %v", process)
 }
-func (p *Proxy) stopProcess(process *process) {
-	process.Close()
+
+func (p *Proxy) removeProcess(process *process) {
 	p.mu.Lock()
 	delete(p.processes, process)
 	p.mu.Unlock()
-	processLog().Infof("Stopped process %v", process)
 }
-func (p *Proxy) readLoop(process *process) {
-	p.startProcess(process)
-	defer p.stopProcess(process)
-	reader := iobuf.NewReader(iobuf.NewPool(0), process.Conn)
-	defer reader.Close()
-	for {
-		msg, err := message.ReadFrom(reader, process.ctrlCipher)
-		if err != nil {
-			processLog().Infof("Read on %v failed: %v", process, err)
-			return
-		}
-		msgLog().Infof("Received msg: %T = %v", msg, msg)
-		switch m := msg.(type) {
-		case *message.Data:
-			if vc := process.ServerVC(m.VCI); vc != nil {
-				if err := vc.DispatchPayload(m.Flow, m.Payload); err != nil {
-					processLog().Infof("Ignoring data message %v from process %v: %v", m, process, err)
-				}
-				if m.Close() {
-					vc.ShutdownFlow(m.Flow)
-				}
-				break
-			}
-			srcVCI := m.VCI
-			if d := process.Route(srcVCI); d != nil {
-				m.VCI = d.VCI
-				if err := d.Process.Queue.Put(m); err != nil {
-					process.RemoveRoute(srcVCI)
-					process.SendCloseVC(srcVCI, fmt.Errorf("proxy failed to forward data message: %v", err))
-				}
-				break
-			}
-			process.SendCloseVC(srcVCI, errNoRoutingTableEntry)
-		case *message.OpenFlow:
-			if vc := process.ServerVC(m.VCI); vc != nil {
-				if err := vc.AcceptFlow(m.Flow); err != nil {
-					processLog().Infof("OpenFlow %+v on process %v failed: %v", m, process, err)
-					cm := &message.Data{VCI: m.VCI, Flow: m.Flow}
-					cm.SetClose()
-					process.Queue.Put(cm)
-				}
-				vc.ReleaseCounters(m.Flow, m.InitialCounters)
-				break
-			}
-			srcVCI := m.VCI
-			if d := process.Route(srcVCI); d != nil {
-				m.VCI = d.VCI
-				if err := d.Process.Queue.Put(m); err != nil {
-					process.RemoveRoute(srcVCI)
-					process.SendCloseVC(srcVCI, fmt.Errorf("proxy failed to forward open flow message: %v", err))
-				}
-				break
-			}
-			process.SendCloseVC(srcVCI, errNoRoutingTableEntry)
-		case *message.CloseVC:
-			if vc := process.RemoveServerVC(m.VCI); vc != nil {
-				vc.Close(m.Error)
-				break
-			}
-			srcVCI := m.VCI
-			if d := process.Route(srcVCI); d != nil {
-				m.VCI = d.VCI
-				d.Process.Queue.Put(m)
-				d.Process.RemoveRoute(d.VCI)
-			}
-			process.RemoveRoute(srcVCI)
-		case *message.AddReceiveBuffers:
-			p.routeCounters(process, m.Counters)
-		case *message.OpenVC:
-			dstrid := m.DstEndpoint.RoutingID()
-			if naming.Compare(dstrid, p.rid) || naming.Compare(dstrid, naming.NullRoutingID) {
-				// VC that terminates at the proxy.
-				// See protocol.vdl for details on the protocol between the server and the proxy.
-				vcObj := process.NewServerVC(m)
-				// route counters after creating the VC so counters to vc are not lost.
-				p.routeCounters(process, m.Counters)
-				if vcObj != nil {
-					server := &server{Process: process, VC: vcObj}
-					go p.runServer(server, vcObj.HandshakeAcceptedVC(vc.LocalPrincipal{p.principal}))
-				}
-				break
-			}
-			dstprocess := p.servers.Process(dstrid)
-			if dstprocess == nil {
-				process.SendCloseVC(m.VCI, fmt.Errorf("no server with routing id %v is being proxied", dstrid))
-				p.routeCounters(process, m.Counters)
-				break
-			}
-			srcVCI := m.VCI
-			dstVCI := dstprocess.AllocVCI()
-			startRoutingVC(srcVCI, dstVCI, process, dstprocess)
-			// Forward the OpenVC message.
-			// Typically, an OpenVC message is accompanied with Counters for the new VC.
-			// Keep that in the forwarded message and route the remaining counters separately.
-			counters := m.Counters
-			m.Counters = message.NewCounters()
-			for cid, bytes := range counters {
-				if cid.VCI() == srcVCI {
-					m.Counters.Add(dstVCI, cid.Flow(), bytes)
-					delete(counters, cid)
-				}
-			}
-			m.VCI = dstVCI
-			dstprocess.Queue.Put(m)
-			p.routeCounters(process, counters)
-		case *message.HopSetup:
-			// Set up the hop.  This takes over the process during negotiation.
-			if process.isSetup {
-				// Already performed authentication.  We don't do it again.
-				processLog().Infof("Process %v is already setup", process)
-				return
-			}
-			var blessings security.Blessings
-			if p.principal != nil {
-				blessings = p.principal.BlessingStore().Default()
-			}
-			c, err := vif.AuthenticateAsServer(process.Conn, nil, p.principal, blessings, nil, m)
-			if err != nil {
-				processLog().Infof("Process %v failed to authenticate: %s", process, err)
-				return
-			}
-			process.ctrlCipher = c
-			process.isSetup = true
-		default:
-			processLog().Infof("Closing %v because of unrecognized message %T", process, m)
-			return
-		}
-	}
-}
+
 func (p *Proxy) runServer(server *server, c <-chan vc.HandshakeResult) {
 	hr := <-c
 	if hr.Error != nil {
@@ -439,6 +263,7 @@
 	// Wait for this flow to be closed.
 	<-conn.Closed()
 }
+
 func (p *Proxy) routeCounters(process *process, counters message.Counters) {
 	// Since each VC can be routed to a different process, split up the
 	// Counters into one message per VC.
@@ -453,13 +278,14 @@
 		if d := process.Route(srcVCI); d != nil {
 			c := message.NewCounters()
 			c.Add(d.VCI, cid.Flow(), bytes)
-			if err := d.Process.Queue.Put(&message.AddReceiveBuffers{Counters: c}); err != nil {
+			if err := d.Process.queue.Put(&message.AddReceiveBuffers{Counters: c}); err != nil {
 				process.RemoveRoute(srcVCI)
 				process.SendCloseVC(srcVCI, fmt.Errorf("proxy failed to forward receive buffers: %v", err))
 			}
 		}
 	}
 }
+
 func startRoutingVC(srcVCI, dstVCI id.VC, srcProcess, dstProcess *process) {
 	dstProcess.AddRoute(dstVCI, &destination{VCI: srcVCI, Process: srcProcess})
 	srcProcess.AddRoute(srcVCI, &destination{VCI: dstVCI, Process: dstProcess})
@@ -477,13 +303,210 @@
 func (p *Proxy) Shutdown() {
 	p.ln.Close()
 	p.mu.Lock()
-	defer p.mu.Unlock()
-	for process, _ := range p.processes {
+	processes := p.processes
+	p.processes = nil
+	p.mu.Unlock()
+	for process, _ := range processes {
 		process.Close()
 	}
 }
+
+func (p *process) serverVCsLoop() {
+	for {
+		w, bufs, err := p.bq.Get(nil)
+		if err != nil {
+			return
+		}
+		vci, fid := unpackIDs(w.ID())
+		if vc := p.ServerVC(vci); vc != nil {
+			queueDataMessages(bufs, vc, fid, p.queue)
+			if len(bufs) == 0 {
+				m := &message.Data{VCI: vci, Flow: fid}
+				m.SetClose()
+				p.queue.Put(m)
+				w.Shutdown(true)
+			}
+			continue
+		}
+		releaseBufs(0, bufs)
+	}
+}
+
+func releaseBufs(start int, bufs []*iobuf.Slice) {
+	for _, buf := range bufs[start:] {
+		buf.Release()
+	}
+}
+
+func queueDataMessages(bufs []*iobuf.Slice, vc *vc.VC, fid id.Flow, q *upcqueue.T) {
+	for ix, b := range bufs {
+		m := &message.Data{VCI: vc.VCI(), Flow: fid}
+		var err error
+		if m.Payload, err = vc.Encrypt(fid, b); err != nil {
+			msgLog().Infof("vc.Encrypt failed. VC:%v Flow:%v Error:%v", vc, fid, err)
+			releaseBufs(ix+1, bufs)
+			return
+		}
+		if err = q.Put(m); err != nil {
+			msgLog().Infof("Failed to enqueue data message %v: %v", m, err)
+			m.Release()
+			releaseBufs(ix+1, bufs)
+			return
+		}
+	}
+}
+
+func (p *process) writeLoop() {
+	defer processLog().Infof("Exited writeLoop for %v", p)
+	defer p.Close()
+
+	for {
+		item, err := p.queue.Get(nil)
+		if err != nil {
+			if err != upcqueue.ErrQueueIsClosed {
+				processLog().Infof("upcqueue.Get failed on %v: %v", p, err)
+			}
+			return
+		}
+		if err = message.WriteTo(p.conn, item.(message.T), p.ctrlCipher); err != nil {
+			processLog().Infof("message.WriteTo on %v failed: %v", p, err)
+			return
+		}
+	}
+}
+
+func (p *process) readLoop() {
+	defer processLog().Infof("Exited readLoop for %v", p)
+	defer p.Close()
+
+	for {
+		msg, err := message.ReadFrom(p.reader, p.ctrlCipher)
+		if err != nil {
+			processLog().Infof("Read on %v failed: %v", p, err)
+			return
+		}
+		msgLog().Infof("Received msg: %T = %v", msg, msg)
+		switch m := msg.(type) {
+		case *message.Data:
+			if vc := p.ServerVC(m.VCI); vc != nil {
+				if err := vc.DispatchPayload(m.Flow, m.Payload); err != nil {
+					processLog().Infof("Ignoring data message %v from process %v: %v", m, p, err)
+				}
+				if m.Close() {
+					vc.ShutdownFlow(m.Flow)
+				}
+				break
+			}
+			srcVCI := m.VCI
+			if d := p.Route(srcVCI); d != nil {
+				m.VCI = d.VCI
+				if err := d.Process.queue.Put(m); err != nil {
+					m.Release()
+					p.RemoveRoute(srcVCI)
+					p.SendCloseVC(srcVCI, fmt.Errorf("proxy failed to forward data message: %v", err))
+				}
+				break
+			}
+			p.SendCloseVC(srcVCI, errNoRoutingTableEntry)
+		case *message.OpenFlow:
+			if vc := p.ServerVC(m.VCI); vc != nil {
+				if err := vc.AcceptFlow(m.Flow); err != nil {
+					processLog().Infof("OpenFlow %+v on process %v failed: %v", m, p, err)
+					cm := &message.Data{VCI: m.VCI, Flow: m.Flow}
+					cm.SetClose()
+					p.queue.Put(cm)
+				}
+				vc.ReleaseCounters(m.Flow, m.InitialCounters)
+				break
+			}
+			srcVCI := m.VCI
+			if d := p.Route(srcVCI); d != nil {
+				m.VCI = d.VCI
+				if err := d.Process.queue.Put(m); err != nil {
+					p.RemoveRoute(srcVCI)
+					p.SendCloseVC(srcVCI, fmt.Errorf("proxy failed to forward open flow message: %v", err))
+				}
+				break
+			}
+			p.SendCloseVC(srcVCI, errNoRoutingTableEntry)
+		case *message.CloseVC:
+			if vc := p.RemoveServerVC(m.VCI); vc != nil {
+				vc.Close(m.Error)
+				break
+			}
+			srcVCI := m.VCI
+			if d := p.Route(srcVCI); d != nil {
+				m.VCI = d.VCI
+				d.Process.queue.Put(m)
+				d.Process.RemoveRoute(d.VCI)
+			}
+			p.RemoveRoute(srcVCI)
+		case *message.AddReceiveBuffers:
+			p.proxy.routeCounters(p, m.Counters)
+		case *message.OpenVC:
+			dstrid := m.DstEndpoint.RoutingID()
+			if naming.Compare(dstrid, p.proxy.rid) || naming.Compare(dstrid, naming.NullRoutingID) {
+				// VC that terminates at the proxy.
+				// See protocol.vdl for details on the protocol between the server and the proxy.
+				vcObj := p.NewServerVC(m)
+				// route counters after creating the VC so counters to vc are not lost.
+				p.proxy.routeCounters(p, m.Counters)
+				if vcObj != nil {
+					server := &server{Process: p, VC: vcObj}
+					go p.proxy.runServer(server, vcObj.HandshakeAcceptedVC(vc.LocalPrincipal{p.proxy.principal}))
+				}
+				break
+			}
+			dstprocess := p.proxy.servers.Process(dstrid)
+			if dstprocess == nil {
+				p.SendCloseVC(m.VCI, fmt.Errorf("no server with routing id %v is being proxied", dstrid))
+				p.proxy.routeCounters(p, m.Counters)
+				break
+			}
+			srcVCI := m.VCI
+			dstVCI := dstprocess.AllocVCI()
+			startRoutingVC(srcVCI, dstVCI, p, dstprocess)
+			// Forward the OpenVC message.
+			// Typically, an OpenVC message is accompanied with Counters for the new VC.
+			// Keep that in the forwarded message and route the remaining counters separately.
+			counters := m.Counters
+			m.Counters = message.NewCounters()
+			for cid, bytes := range counters {
+				if cid.VCI() == srcVCI {
+					m.Counters.Add(dstVCI, cid.Flow(), bytes)
+					delete(counters, cid)
+				}
+			}
+			m.VCI = dstVCI
+			dstprocess.queue.Put(m)
+			p.proxy.routeCounters(p, counters)
+		case *message.HopSetup:
+			// Set up the hop.  This takes over the process during negotiation.
+			if p.isSetup {
+				// Already performed authentication.  We don't do it again.
+				processLog().Infof("Process %v is already setup", p)
+				return
+			}
+			var blessings security.Blessings
+			if p.proxy.principal != nil {
+				blessings = p.proxy.principal.BlessingStore().Default()
+			}
+			c, err := vif.AuthenticateAsServer(p.conn, p.reader, nil, p.proxy.principal, blessings, nil, m)
+			if err != nil {
+				processLog().Infof("Process %v failed to authenticate: %s", p, err)
+				return
+			}
+			p.ctrlCipher = c
+			p.isSetup = true
+		default:
+			processLog().Infof("Closing %v because of unrecognized message %T", p, m)
+			return
+		}
+	}
+}
+
 func (p *process) String() string {
-	r := p.Conn.RemoteAddr()
+	r := p.conn.RemoteAddr()
 	return fmt.Sprintf("(%s, %s)", r.Network(), r)
 }
 func (p *process) Route(vci id.VC) *destination {
@@ -520,10 +543,15 @@
 	if err != nil {
 		estr = err.Error()
 	}
-	p.Queue.Put(&message.CloseVC{VCI: vci, Error: estr})
+	p.queue.Put(&message.CloseVC{VCI: vci, Error: estr})
 }
+
 func (p *process) Close() {
 	p.mu.Lock()
+	if p.routingTable == nil {
+		p.mu.Unlock()
+		return
+	}
 	rt := p.routingTable
 	p.routingTable = nil
 	for _, vc := range p.servers {
@@ -533,15 +561,19 @@
 	for _, d := range rt {
 		d.Process.SendCloseVC(d.VCI, errProcessVanished)
 	}
-	p.BQ.Close()
-	p.Queue.Close()
-	p.Conn.Close()
+	p.bq.Close()
+	p.queue.Close()
+	p.conn.Close()
+
+	p.proxy.removeProcess(p)
 }
+
 func (p *process) ServerVC(vci id.VC) *vc.VC {
 	p.mu.Lock()
 	defer p.mu.Unlock()
 	return p.servers[vci]
 }
+
 func (p *process) NewServerVC(m *message.OpenVC) *vc.VC {
 	p.mu.Lock()
 	defer p.mu.Unlock()
@@ -558,7 +590,7 @@
 		VCI:          m.VCI,
 		LocalEP:      m.DstEndpoint,
 		RemoteEP:     m.SrcEndpoint,
-		Pool:         iobuf.NewPool(0),
+		Pool:         p.pool,
 		ReserveBytes: message.HeaderSizeBytes,
 		Helper:       p,
 		Version:      version,
@@ -567,6 +599,7 @@
 	proxyLog().Infof("Registered VC %v from server on process %v", vc, p)
 	return vc
 }
+
 func (p *process) RemoveServerVC(vci id.VC) *vc.VC {
 	p.mu.Lock()
 	defer p.mu.Unlock()
@@ -581,22 +614,24 @@
 // Make process implement vc.Helper
 func (p *process) NotifyOfNewFlow(vci id.VC, fid id.Flow, bytes uint) {
 	msg := &message.OpenFlow{VCI: vci, Flow: fid, InitialCounters: uint32(bytes)}
-	if err := p.Queue.Put(msg); err != nil {
+	if err := p.queue.Put(msg); err != nil {
 		processLog().Infof("Failed to send OpenFlow(%+v) on process %v: %v", msg, p, err)
 	}
 }
+
 func (p *process) AddReceiveBuffers(vci id.VC, fid id.Flow, bytes uint) {
 	if bytes == 0 {
 		return
 	}
 	msg := &message.AddReceiveBuffers{Counters: message.NewCounters()}
 	msg.Counters.Add(vci, fid, uint32(bytes))
-	if err := p.Queue.Put(msg); err != nil {
+	if err := p.queue.Put(msg); err != nil {
 		processLog().Infof("Failed to send AddReceiveBuffers(%+v) on process %v: %v", msg, p, err)
 	}
 }
+
 func (p *process) NewWriter(vci id.VC, fid id.Flow) (bqueue.Writer, error) {
-	return p.BQ.NewWriter(packIDs(vci, fid), 0, vc.DefaultBytesBufferedPerFlow)
+	return p.bq.NewWriter(packIDs(vci, fid), 0, vc.DefaultBytesBufferedPerFlow)
 }
 
 // Convenience functions to assist with the logging convention.
diff --git a/runtimes/google/ipc/stream/proxy/proxy_test.go b/runtimes/google/ipc/stream/proxy/proxy_test.go
index 8fd3b8c..9d23ab4 100644
--- a/runtimes/google/ipc/stream/proxy/proxy_test.go
+++ b/runtimes/google/ipc/stream/proxy/proxy_test.go
@@ -4,6 +4,7 @@
 	"bytes"
 	"fmt"
 	"io"
+	"os"
 	"reflect"
 	"strings"
 	"testing"
@@ -19,7 +20,10 @@
 	"v.io/core/veyron/runtimes/google/ipc/stream/vc"
 )
 
-func init() { testutil.Init() }
+func TestMain(m *testing.M) {
+	testutil.Init()
+	os.Exit(m.Run())
+}
 
 func TestProxy(t *testing.T) {
 	proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
diff --git a/runtimes/google/ipc/stream/vc/vc.go b/runtimes/google/ipc/stream/vc/vc.go
index d273830..d690fef 100644
--- a/runtimes/google/ipc/stream/vc/vc.go
+++ b/runtimes/google/ipc/stream/vc/vc.go
@@ -101,7 +101,7 @@
 	LocalEP      naming.Endpoint // Endpoint of the local end of the VC.
 	RemoteEP     naming.Endpoint // Endpoint of the remote end of the VC.
 	Pool         *iobuf.Pool     // Byte pool used for read and write buffer allocations.
-	ReserveBytes uint            // Number of bytes to reserve in iobuf.Slices.
+	ReserveBytes uint            // Number of padding bytes to reserve for headers.
 	Helper       Helper
 	Version      version.IPCVersion
 }
@@ -345,8 +345,8 @@
 	vc.flowMap = nil
 	if vc.listener != nil {
 		vc.listener.Close()
+		vc.listener = nil
 	}
-	vc.listener = nil
 	vc.closeReason = reason
 	vc.mu.Unlock()
 
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index aa6e129..05f4edd 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -7,6 +7,7 @@
 	"fmt"
 	"io"
 	"net"
+	"os"
 	"reflect"
 	"runtime"
 	"strings"
@@ -29,7 +30,10 @@
 	"v.io/core/veyron2/security"
 )
 
-func init() { testutil.Init() }
+func TestMain(m *testing.M) {
+	testutil.Init()
+	os.Exit(m.Run())
+}
 
 const (
 	// Convenience alias to avoid conflicts between the package name "vc" and variables called "vc".
diff --git a/runtimes/google/ipc/stream/vif/auth.go b/runtimes/google/ipc/stream/vif/auth.go
index db659c2..312c3a6 100644
--- a/runtimes/google/ipc/stream/vif/auth.go
+++ b/runtimes/google/ipc/stream/vif/auth.go
@@ -5,7 +5,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"net"
 
 	"golang.org/x/crypto/nacl/box"
 
@@ -61,7 +60,7 @@
 // including a hash of the HopSetup message in the encrypted stream.  It is
 // likely that this will be addressed in subsequent protocol versions (or it may
 // not be addressed at all if IPCVersion6 becomes the only supported version).
-func AuthenticateAsClient(ctx *context.T, conn net.Conn, versions *version.Range, principal security.Principal, dc vc.DischargeClient) (crypto.ControlCipher, error) {
+func AuthenticateAsClient(ctx *context.T, writer io.Writer, reader *iobuf.Reader, versions *version.Range, principal security.Principal, dc vc.DischargeClient) (crypto.ControlCipher, error) {
 	if versions == nil {
 		versions = version.SupportedRange
 	}
@@ -82,13 +81,11 @@
 	if err != nil {
 		return nil, err
 	}
-	if err := message.WriteTo(conn, &pub, nullCipher); err != nil {
+	if err := message.WriteTo(writer, &pub, nullCipher); err != nil {
 		return nil, err
 	}
 
 	// Read the server's public data.
-	pool := iobuf.NewPool(0)
-	reader := iobuf.NewReader(pool, conn)
 	pmsg, err := message.ReadFrom(reader, nullCipher)
 	if err != nil {
 		return nil, err
@@ -111,7 +108,7 @@
 	// Perform the authentication.
 	switch v {
 	case ipcversion.IPCVersion6:
-		return authenticateAsClientIPC6(ctx, conn, reader, principal, dc, &pvt, &pub, ppub)
+		return authenticateAsClientIPC6(ctx, writer, reader, principal, dc, &pvt, &pub, ppub)
 	default:
 		return nil, errUnsupportedEncryptVersion
 	}
@@ -137,7 +134,7 @@
 // based on the max common version.
 //
 // See AuthenticateAsClient for a description of the negotiation.
-func AuthenticateAsServer(conn net.Conn, versions *version.Range, principal security.Principal, lBlessings security.Blessings,
+func AuthenticateAsServer(writer io.Writer, reader *iobuf.Reader, versions *version.Range, principal security.Principal, lBlessings security.Blessings,
 	dc vc.DischargeClient, ppub *message.HopSetup) (crypto.ControlCipher, error) {
 	var err error
 	if versions == nil {
@@ -156,7 +153,7 @@
 	if err != nil {
 		return nil, err
 	}
-	if err := message.WriteTo(conn, &pub, nullCipher); err != nil {
+	if err := message.WriteTo(writer, &pub, nullCipher); err != nil {
 		return nil, err
 	}
 
@@ -173,22 +170,20 @@
 	// Perform authentication.
 	switch v {
 	case ipcversion.IPCVersion6:
-		return authenticateAsServerIPC6(conn, principal, lBlessings, dc, &pvt, &pub, ppub)
+		return authenticateAsServerIPC6(writer, reader, principal, lBlessings, dc, &pvt, &pub, ppub)
 	default:
 		return nil, errUnsupportedEncryptVersion
 	}
 }
 
-func authenticateAsServerIPC6(conn net.Conn, principal security.Principal, lBlessings security.Blessings, dc vc.DischargeClient,
+func authenticateAsServerIPC6(writer io.Writer, reader *iobuf.Reader, principal security.Principal, lBlessings security.Blessings, dc vc.DischargeClient,
 	pvt *privateData, pub, ppub *message.HopSetup) (crypto.ControlCipher, error) {
 	box := ppub.NaclBox()
 	if box == nil {
 		return nil, errVersionNegotiationFailed
 	}
 	c := crypto.NewControlCipherIPC6(&box.PublicKey, &pvt.naclBoxPrivateKey, true)
-	pool := iobuf.NewPool(0)
-	reader := iobuf.NewReader(pool, conn)
-	sconn := newSetupConn(conn, reader, c)
+	sconn := newSetupConn(writer, reader, c)
 	// TODO(jyh): act upon authentication results.
 	_, _, err := vc.AuthenticateAsServer(sconn, principal, lBlessings, dc, crypto.NewNullCrypter(), ipcversion.IPCVersion6)
 	if err != nil {
diff --git a/runtimes/google/ipc/stream/vif/vif.go b/runtimes/google/ipc/stream/vif/vif.go
index 3b51d61..1e5294e 100644
--- a/runtimes/google/ipc/stream/vif/vif.go
+++ b/runtimes/google/ipc/stream/vif/vif.go
@@ -37,8 +37,10 @@
 // single physical interface, multiple Virtual Circuits (VCs) can be
 // established over a single VIF.
 type VIF struct {
+	// All reads must be performed through reader, and not directly through conn.
 	conn    net.Conn
 	pool    *iobuf.Pool
+	reader  *iobuf.Reader
 	localEP naming.Endpoint
 
 	// control channel encryption.
@@ -72,6 +74,9 @@
 	// actually supported by this IPC implementation (which is always
 	// what you want outside of tests).
 	versions *version.Range
+
+	isClosedMu sync.Mutex
+	isClosed   bool // GUARDED_BY(isClosedMu)
 }
 
 // ConnectorAndFlow represents a Flow and the Connector that can be used to
@@ -118,11 +123,13 @@
 		span.Annotatef("(%v, %v)", conn.RemoteAddr().Network(), conn.RemoteAddr())
 		defer span.Finish()
 	}
-	c, err := AuthenticateAsClient(ctx, conn, versions, principal, dc)
+	pool := iobuf.NewPool(0)
+	reader := iobuf.NewReader(pool, conn)
+	c, err := AuthenticateAsClient(ctx, conn, reader, versions, principal, dc)
 	if err != nil {
 		return nil, err
 	}
-	return internalNew(conn, rid, id.VC(vc.NumReservedVCs), versions, nil, nil, c)
+	return internalNew(conn, pool, reader, rid, id.VC(vc.NumReservedVCs), versions, nil, nil, c)
 }
 
 // InternalNewAcceptedVIF creates a new virtual interface over the provided
@@ -136,11 +143,12 @@
 // placed inside veyron/runtimes/google. Code outside the
 // veyron/runtimes/google/* packages should never call this method.
 func InternalNewAcceptedVIF(conn net.Conn, rid naming.RoutingID, versions *version.Range, lopts ...stream.ListenerOpt) (*VIF, error) {
-	var nc crypto.NullControlCipher
-	return internalNew(conn, rid, id.VC(vc.NumReservedVCs)+1, versions, upcqueue.New(), lopts, &nc)
+	pool := iobuf.NewPool(0)
+	reader := iobuf.NewReader(pool, conn)
+	return internalNew(conn, pool, reader, rid, id.VC(vc.NumReservedVCs)+1, versions, upcqueue.New(), lopts, &crypto.NullControlCipher{})
 }
 
-func internalNew(conn net.Conn, rid naming.RoutingID, initialVCI id.VC, versions *version.Range, acceptor *upcqueue.T, listenerOpts []stream.ListenerOpt, c crypto.ControlCipher) (*VIF, error) {
+func internalNew(conn net.Conn, pool *iobuf.Pool, reader *iobuf.Reader, rid naming.RoutingID, initialVCI id.VC, versions *version.Range, acceptor *upcqueue.T, listenerOpts []stream.ListenerOpt, c crypto.ControlCipher) (*VIF, error) {
 	// Some cloud providers (like Google Compute Engine) seem to blackhole
 	// inactive TCP connections, set a TCP keep alive to prevent that.
 	// See: https://developers.google.com/compute/docs/troubleshooting#communicatewithinternet
@@ -187,7 +195,8 @@
 	}
 	vif := &VIF{
 		conn:         conn,
-		pool:         iobuf.NewPool(0),
+		pool:         pool,
+		reader:       reader,
 		ctrlCipher:   c,
 		vcMap:        newVCMap(),
 		acceptor:     acceptor,
@@ -238,6 +247,14 @@
 // underlying network connection after draining all pending writes on those
 // VCs.
 func (vif *VIF) Close() {
+	vif.isClosedMu.Lock()
+	if vif.isClosed {
+		vif.isClosedMu.Unlock()
+		return
+	}
+	vif.isClosed = true
+	vif.isClosedMu.Unlock()
+
 	vlog.VI(1).Infof("Closing VIF %s", vif)
 	// Stop accepting new VCs.
 	vif.StopAccepting()
@@ -323,14 +340,12 @@
 
 func (vif *VIF) readLoop() {
 	defer vif.Close()
-	reader := iobuf.NewReader(vif.pool, vif.conn)
-	defer reader.Close()
 	defer vif.stopVCDispatchLoops()
 	for {
 		// vif.ctrlCipher is guarded by vif.writeMu.  However, the only mutation
 		// to it is in handleMessage, which runs in the same goroutine, so a
 		// lock is not required here.
-		msg, err := message.ReadFrom(reader, vif.ctrlCipher)
+		msg, err := message.ReadFrom(vif.reader, vif.ctrlCipher)
 		if err != nil {
 			vlog.VI(1).Infof("Exiting readLoop of VIF %s because of read error: %v", vif, err)
 			return
@@ -420,7 +435,7 @@
 			return errVersionNegotiationFailed
 		}
 		vif.writeMu.Lock()
-		c, err := AuthenticateAsServer(vif.conn, vif.versions, principal, lBlessings, dischargeClient, m)
+		c, err := AuthenticateAsServer(vif.conn, vif.reader, vif.versions, principal, lBlessings, dischargeClient, m)
 		if err != nil {
 			vif.writeMu.Unlock()
 			return err
@@ -520,7 +535,7 @@
 		case vif.expressQ:
 			for _, b := range bufs {
 				if err := vif.writeSerializedMessage(b.Contents); err != nil {
-					vlog.Errorf("Exiting writeLoop of VIF %s because Control message write failed: %s", vif, err)
+					vlog.VI(1).Infof("Exiting writeLoop of VIF %s because Control message write failed: %s", vif, err)
 					releaseBufs(bufs)
 					return
 				}
@@ -792,6 +807,9 @@
 }
 
 // Methods and type that implement vc.Helper
+//
+// We create a separate type for vc.Helper to hide the vc.Helper methods
+// from the exported method set of VIF.
 type vcHelper struct{ vif *VIF }
 
 func (h vcHelper) NotifyOfNewFlow(vci id.VC, fid id.Flow, bytes uint) {
diff --git a/runtimes/google/ipc/stream/vif/vif_test.go b/runtimes/google/ipc/stream/vif/vif_test.go
index edffeba..232f985 100644
--- a/runtimes/google/ipc/stream/vif/vif_test.go
+++ b/runtimes/google/ipc/stream/vif/vif_test.go
@@ -9,6 +9,7 @@
 	"fmt"
 	"io"
 	"net"
+	"os"
 	"reflect"
 	"runtime"
 	"sort"
@@ -27,7 +28,10 @@
 	"v.io/core/veyron2/naming"
 )
 
-func init() { testutil.Init() }
+func TestMain(m *testing.M) {
+	testutil.Init()
+	os.Exit(m.Run())
+}
 
 func newPrincipal(defaultBlessing string) vc.LocalPrincipal {
 	return vc.LocalPrincipal{tsecurity.NewPrincipal("defaultBlessing")}
@@ -261,10 +265,12 @@
 	if n, err := serverFlow.Read(buf); n != 0 || err == nil {
 		t.Fatal("Got (%d, %v) = %q, want (0, nil)", n, err, buf[:n])
 	}
+	server.Close()
 }
 
 func TestShutdownVCs(t *testing.T) {
 	client, server := NewClientServer()
+	defer server.Close()
 	defer client.Close()
 
 	testN := func(N int) error {
diff --git a/runtimes/google/ipc/testutil_test.go b/runtimes/google/ipc/testutil_test.go
index 1011dd6..01f9444 100644
--- a/runtimes/google/ipc/testutil_test.go
+++ b/runtimes/google/ipc/testutil_test.go
@@ -6,12 +6,8 @@
 
 	"v.io/core/veyron2/security"
 	"v.io/core/veyron2/verror2"
-
-	"v.io/core/veyron/lib/testutil"
 )
 
-func init() { testutil.Init() }
-
 func makeResultPtrs(ins []interface{}) []interface{} {
 	outs := make([]interface{}, len(ins))
 	for ix, in := range ins {
diff --git a/runtimes/google/lib/iobuf/allocator.go b/runtimes/google/lib/iobuf/allocator.go
index 7c68de1..4483159 100644
--- a/runtimes/google/lib/iobuf/allocator.go
+++ b/runtimes/google/lib/iobuf/allocator.go
@@ -25,8 +25,7 @@
 // contiguous iobuf.  This can be used to reverse space for a header, for
 // example.
 func NewAllocator(pool *Pool, reserve uint) *Allocator {
-	iobuf := pool.alloc(reserve)
-	return &Allocator{pool: pool, reserve: reserve, index: reserve, iobuf: iobuf}
+	return &Allocator{pool: pool, reserve: reserve, index: reserve}
 }
 
 // Release releases the allocator.
@@ -34,15 +33,18 @@
 	if a.iobuf != nil {
 		a.iobuf.release()
 		a.iobuf = nil
-		a.pool = nil
 	}
+	a.pool = nil
 }
 
 // Alloc allocates a new Slice.
 func (a *Allocator) Alloc(bytes uint) *Slice {
 	if a.iobuf == nil {
-		vlog.Info("iobuf.Allocator has already been closed")
-		return nil
+		if a.pool == nil {
+			vlog.Info("iobuf.Allocator has already been closed")
+			return nil
+		}
+		a.iobuf = a.pool.alloc(a.reserve + bytes)
 	}
 	if uint(len(a.iobuf.Contents))-a.index < bytes {
 		a.allocIOBUF(bytes)
diff --git a/runtimes/google/lib/iobuf/iobuf.go b/runtimes/google/lib/iobuf/iobuf.go
index 2d55835..918ddba 100644
--- a/runtimes/google/lib/iobuf/iobuf.go
+++ b/runtimes/google/lib/iobuf/iobuf.go
@@ -59,7 +59,14 @@
 	allocated uint64 // Total number of iobufs allocated.
 }
 
+const defaultMinSize = 1 << 12
+
+// NewPool creates a new pool. The pool will allocate iobufs in multiples of minSize.
+// If minSize is zero, the default value (4K) will be used.
 func NewPool(minSize uint) *Pool {
+	if minSize == 0 {
+		minSize = defaultMinSize
+	}
 	return &Pool{minSize: minSize, freelist: []*buf{}}
 }
 
@@ -72,9 +79,12 @@
 
 // alloc allocates a new iobuf.  The returned iobuf has at least <size> bytes of free space.
 func (pool *Pool) alloc(size uint) *buf {
-	if size < pool.minSize {
+	if size == 0 {
 		size = pool.minSize
+	} else if r := size % pool.minSize; r > 0 {
+		size += pool.minSize - r
 	}
+
 	pool.mutex.Lock()
 	defer pool.mutex.Unlock()
 	if pool.freelist == nil {
diff --git a/runtimes/google/rt/rt_test.go b/runtimes/google/rt/rt_test.go
index aaebf45..0935d28 100644
--- a/runtimes/google/rt/rt_test.go
+++ b/runtimes/google/rt/rt_test.go
@@ -151,7 +151,7 @@
 	if err != nil {
 		return err
 	}
-	if _, err := sh.Start("principal", nil, args[1:]...); err != nil {
+	if _, err := sh.Start("principal", nil, args...); err != nil {
 		return err
 	}
 	// Cleanup copies the output of sh to these Writers.
diff --git a/runtimes/google/vtrace/store.go b/runtimes/google/vtrace/store.go
index b6ed2de..b3995b5 100644
--- a/runtimes/google/vtrace/store.go
+++ b/runtimes/google/vtrace/store.go
@@ -31,7 +31,7 @@
 	// of recently used items (the tail is the LRU traceStore).
 	// TODO(mattr): Use rwmutex.
 	mu     sync.Mutex
-	traces map[uniqueid.ID]*traceStore // GUARDED_BY(mu)
+	traces map[uniqueid.Id]*traceStore // GUARDED_BY(mu)
 	head   *traceStore                 // GUARDED_BY(mu)
 }
 
@@ -51,18 +51,18 @@
 	return &Store{
 		opts:          opts,
 		collectRegexp: collectRegexp,
-		traces:        make(map[uniqueid.ID]*traceStore),
+		traces:        make(map[uniqueid.Id]*traceStore),
 		head:          head,
 	}, nil
 }
 
-func (s *Store) ForceCollect(id uniqueid.ID) {
+func (s *Store) ForceCollect(id uniqueid.Id) {
 	s.mu.Lock()
 	s.forceCollectLocked(id)
 	s.mu.Unlock()
 }
 
-func (s *Store) forceCollectLocked(id uniqueid.ID) *traceStore {
+func (s *Store) forceCollectLocked(id uniqueid.Id) *traceStore {
 	ts := s.traces[id]
 	if ts == nil {
 		ts = newTraceStore(id)
@@ -144,7 +144,7 @@
 }
 
 // method returns the collection method for the given trace.
-func (s *Store) method(id uniqueid.ID) vtrace.TraceMethod {
+func (s *Store) method(id uniqueid.Id) vtrace.TraceMethod {
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	if ts := s.traces[id]; ts != nil {
@@ -169,7 +169,7 @@
 
 // TraceRecord returns a TraceRecord for a given ID.  Returns
 // nil if the given id is not present.
-func (s *Store) TraceRecord(id uniqueid.ID) *vtrace.TraceRecord {
+func (s *Store) TraceRecord(id uniqueid.Id) *vtrace.TraceRecord {
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	out := &vtrace.TraceRecord{}
@@ -181,15 +181,15 @@
 }
 
 type traceStore struct {
-	id         uniqueid.ID
-	spans      map[uniqueid.ID]*vtrace.SpanRecord
+	id         uniqueid.Id
+	spans      map[uniqueid.Id]*vtrace.SpanRecord
 	prev, next *traceStore
 }
 
-func newTraceStore(id uniqueid.ID) *traceStore {
+func newTraceStore(id uniqueid.Id) *traceStore {
 	return &traceStore{
 		id:    id,
-		spans: make(map[uniqueid.ID]*vtrace.SpanRecord),
+		spans: make(map[uniqueid.Id]*vtrace.SpanRecord),
 	}
 }
 
diff --git a/runtimes/google/vtrace/store_test.go b/runtimes/google/vtrace/store_test.go
index c24d120..ac0cf61 100644
--- a/runtimes/google/vtrace/store_test.go
+++ b/runtimes/google/vtrace/store_test.go
@@ -14,15 +14,15 @@
 
 var nextid = uint64(1)
 
-func id() uniqueid.ID {
-	var out uniqueid.ID
+func id() uniqueid.Id {
+	var out uniqueid.Id
 	binary.BigEndian.PutUint64(out[8:], nextid)
 	nextid++
 	return out
 }
 
-func makeTraces(n int, st *Store) []uniqueid.ID {
-	traces := make([]uniqueid.ID, n)
+func makeTraces(n int, st *Store) []uniqueid.Id {
+	traces := make([]uniqueid.Id, n)
 	for i := range traces {
 		curid := id()
 		traces[i] = curid
@@ -31,23 +31,23 @@
 	return traces
 }
 
-func recordids(records ...vtrace.TraceRecord) map[uniqueid.ID]bool {
-	out := make(map[uniqueid.ID]bool)
+func recordids(records ...vtrace.TraceRecord) map[uniqueid.Id]bool {
+	out := make(map[uniqueid.Id]bool)
 	for _, trace := range records {
 		out[trace.ID] = true
 	}
 	return out
 }
 
-func traceids(traces ...uniqueid.ID) map[uniqueid.ID]bool {
-	out := make(map[uniqueid.ID]bool)
+func traceids(traces ...uniqueid.Id) map[uniqueid.Id]bool {
+	out := make(map[uniqueid.Id]bool)
 	for _, trace := range traces {
 		out[trace] = true
 	}
 	return out
 }
 
-func pretty(in map[uniqueid.ID]bool) []int {
+func pretty(in map[uniqueid.Id]bool) []int {
 	out := make([]int, 0, len(in))
 	for k, _ := range in {
 		out = append(out, int(k[15]))
@@ -56,7 +56,7 @@
 	return out
 }
 
-func compare(t *testing.T, want map[uniqueid.ID]bool, records []vtrace.TraceRecord) {
+func compare(t *testing.T, want map[uniqueid.Id]bool, records []vtrace.TraceRecord) {
 	got := recordids(records...)
 	if !reflect.DeepEqual(want, got) {
 		t.Errorf("Got wrong traces.  Got %v, want %v.", pretty(got), pretty(want))
@@ -92,11 +92,11 @@
 }
 
 func TestRegexp(t *testing.T) {
-	traces := []uniqueid.ID{id(), id(), id()}
+	traces := []uniqueid.Id{id(), id(), id()}
 
 	type testcase struct {
 		pattern string
-		results []uniqueid.ID
+		results []uniqueid.Id
 	}
 	tests := []testcase{
 		{".*", traces},
diff --git a/runtimes/google/vtrace/vtrace.go b/runtimes/google/vtrace/vtrace.go
index a9adefd..528d717 100644
--- a/runtimes/google/vtrace/vtrace.go
+++ b/runtimes/google/vtrace/vtrace.go
@@ -17,15 +17,15 @@
 
 // A span represents an annotated period of time.
 type span struct {
-	id     uniqueid.ID
-	parent uniqueid.ID
+	id     uniqueid.Id
+	parent uniqueid.Id
 	name   string
-	trace  uniqueid.ID
+	trace  uniqueid.Id
 	start  time.Time
 	store  *Store
 }
 
-func newSpan(parent uniqueid.ID, name string, trace uniqueid.ID, store *Store) *span {
+func newSpan(parent uniqueid.Id, name string, trace uniqueid.Id, store *Store) *span {
 	id, err := uniqueid.Random()
 	if err != nil {
 		vlog.Errorf("vtrace: Couldn't generate Span ID, debug data may be lost: %v", err)
@@ -42,10 +42,10 @@
 	return s
 }
 
-func (s *span) ID() uniqueid.ID     { return s.id }
-func (s *span) Parent() uniqueid.ID { return s.parent }
+func (s *span) ID() uniqueid.Id     { return s.id }
+func (s *span) Parent() uniqueid.Id { return s.parent }
 func (s *span) Name() string        { return s.name }
-func (s *span) Trace() uniqueid.ID  { return s.trace }
+func (s *span) Trace() uniqueid.Id  { return s.trace }
 func (s *span) Annotate(msg string) {
 	s.store.annotate(s, msg)
 }
diff --git a/security/agent/agentd/main.go b/security/agent/agentd/main.go
index ec7babd..fe26023 100644
--- a/security/agent/agentd/main.go
+++ b/security/agent/agentd/main.go
@@ -35,6 +35,10 @@
 )
 
 func main() {
+	os.Exit(Main())
+}
+
+func Main() int {
 	flag.Usage = func() {
 		fmt.Fprintf(os.Stderr, `Usage: %s [agent options] command command_args...
 
@@ -45,26 +49,26 @@
 `, os.Args[0], consts.VeyronCredentials)
 		flag.PrintDefaults()
 	}
-	exitCode := 0
-	defer func() {
-		os.Exit(exitCode)
-	}()
 	flag.Parse()
 	if len(flag.Args()) < 1 {
 		fmt.Fprintln(os.Stderr, "Need at least one argument.")
 		flag.Usage()
-		exitCode = 1
-		return
+		return 1
 	}
 	var restartOpts restartOptions
 	if err := restartOpts.parse(); err != nil {
 		fmt.Fprintln(os.Stderr, err)
 		flag.Usage()
-		exitCode = 1
-		return
+		return 1
 	}
 
-	dir := flag.Lookup("veyron.credentials").Value.String()
+	var dir string
+	if f := flag.Lookup("veyron.credentials").Value; true {
+		dir = f.String()
+		// Clear out the flag value to prevent veyron2.Init from
+		// trying to load this password protected principal.
+		f.Set("")
+	}
 	if len(dir) == 0 {
 		vlog.Fatalf("The %v environment variable must be set to a directory", consts.VeyronCredentials)
 	}
@@ -74,6 +78,10 @@
 		vlog.Fatalf("failed to create new principal from dir(%s): %v", dir, err)
 	}
 
+	// Clear out the environment variable before veyron2.Init.
+	if err = os.Setenv(consts.VeyronCredentials, ""); err != nil {
+		vlog.Fatalf("setenv: %v", err)
+	}
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
@@ -84,9 +92,6 @@
 	if err = os.Setenv(agent.FdVarName, "3"); err != nil {
 		vlog.Fatalf("setenv: %v", err)
 	}
-	if err = os.Setenv(consts.VeyronCredentials, ""); err != nil {
-		vlog.Fatalf("setenv: %v", err)
-	}
 
 	if *keypath == "" && passphrase != nil {
 		// If we're done with the passphrase, zero it out so it doesn't stay in memory
@@ -107,6 +112,7 @@
 		}
 	}
 
+	exitCode := 0
 	for {
 		// Run the client and wait for it to finish.
 		cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
@@ -148,6 +154,7 @@
 	// right after cmd.Start().
 	sock.Close()
 	mgrSock.Close()
+	return exitCode
 }
 
 func newPrincipalFromDir(dir string) (security.Principal, []byte, error) {
diff --git a/security/agent/test.sh b/security/agent/test.sh
index f4aaeba..2d05ccd 100755
--- a/security/agent/test.sh
+++ b/security/agent/test.sh
@@ -21,9 +21,28 @@
 
 
   shell_test::setup_server_test || shell_test::fail "line ${LINENO} failed to setup server test"
+
+  # Test passphrase use
   export VEYRON_CREDENTIALS="$(shell::tmp_dir)"
+  local -r LOG_DIR="$(shell::tmp_dir)"
+  echo -n "agentd: passphrase..."
+  # Create the passphrase
+  echo "PASSWORD" | "${AGENTD_BIN}" echo "Hello" &>"${LOG_DIR}/1" || shell_test::fail "line ${LINENO}: agent failed to create passphrase protected principal: $(cat "${LOG_DIR}/1")"
+  # Use it successfully
+  echo "PASSWORD" | "${AGENTD_BIN}" echo "Hello" &>"${LOG_DIR}/2"  || shell_test::fail "line ${LINENO}: agent failed to use passphrase protected principal: $(cat "${LOG_DIR}/2")"
+  # Wrong passphrase should fail
+  echo "BADPASSWORD" | "${AGENTD_BIN}" echo "Hello" &>"${LOG_DIR}/3" && shell_test::fail "line ${LINENO}: agent should have failed with wrong passphrase"
+  local -r NHELLOS="$(grep "Hello" "${LOG_DIR}"/* | wc -l)"
+  if [[ "${NHELLOS}" -ne 2 ]]; then
+	  shell_test::fail "line ${LINENO}: expected 2 'Hello's, got "${NHELLOS}" in $(cat "${LOG_DIR}"/*)"
+  fi
+  echo "OK"
+
+
+
   # Test all methods of the principal interface.
   # (Errors are printed to STDERR)
+  export VEYRON_CREDENTIALS="$(shell::tmp_dir)"
   echo -n "agentd: test_principal..."
   "${AGENTD_BIN}" "${TESTPRINCIPAL_BIN}" >/dev/null || shell_test::fail "line ${LINENO}"
   echo "OK"
diff --git a/services/identity/blesser/oauth.go b/services/identity/blesser/oauth.go
index c11c0e5..504173a 100644
--- a/services/identity/blesser/oauth.go
+++ b/services/identity/blesser/oauth.go
@@ -8,6 +8,7 @@
 	"v.io/core/veyron/services/identity"
 	"v.io/core/veyron/services/identity/oauth"
 	"v.io/core/veyron/services/identity/revocation"
+	"v.io/core/veyron/services/identity/util"
 
 	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/security"
@@ -18,7 +19,7 @@
 	authcodeClient     struct{ ID, Secret string }
 	accessTokenClients []oauth.AccessTokenClient
 	duration           time.Duration
-	domain             string
+	emailClassifier    *util.EmailClassifier
 	dischargerLocation string
 	revocationManager  revocation.RevocationManager
 }
@@ -29,8 +30,8 @@
 	OAuthProvider oauth.OAuthProvider
 	// The OAuth client IDs and names for the clients of the BlessUsingAccessToken RPCs.
 	AccessTokenClients []oauth.AccessTokenClient
-	// If non-empty, only email addresses from this domain will be blessed.
-	DomainRestriction string
+	// Determines prefixes used for blessing extensions based on email address.
+	EmailClassifier *util.EmailClassifier
 	// The object name of the discharger service. If this is empty then revocation caveats will not be granted.
 	DischargerLocation string
 	// The revocation manager that generates caveats and manages revocation.
@@ -45,13 +46,12 @@
 //
 // Blessings generated by this service carry a third-party revocation caveat if a
 // RevocationManager is specified by the params or they carry an ExpiryCaveat that
-// expires after the duration specified by the params. If domain is non-empty, then
-// blessings are generated only for email addresses from that domain.
+// expires after the duration specified by the params.
 func NewOAuthBlesserServer(p OAuthBlesserParams) identity.OAuthBlesserServerStub {
 	return identity.OAuthBlesserServer(&oauthBlesser{
 		oauthProvider:      p.OAuthProvider,
 		duration:           p.BlessingDuration,
-		domain:             p.DomainRestriction,
+		emailClassifier:    p.EmailClassifier,
 		dischargerLocation: p.DischargerLocation,
 		revocationManager:  p.RevocationManager,
 		accessTokenClients: p.AccessTokenClients,
@@ -69,15 +69,6 @@
 
 func (b *oauthBlesser) bless(ctx ipc.ServerContext, email, clientName string) (security.WireBlessings, string, error) {
 	var noblessings security.WireBlessings
-	if len(b.domain) > 0 && !strings.HasSuffix(email, "@"+b.domain) {
-		return noblessings, "", fmt.Errorf("domain restrictions preclude blessings for %q", email)
-	}
-	// Append clientName (e.g., "android", "chrome") to the email and then bless under that.
-	// Since blessings issued by this process do not have many caveats on them and typically
-	// have a large expiry duration, we include the clientName in the extension so that
-	// servers can explicitly distinguish these clients while specifying authorization policies
-	// (say, via ACLs).
-	extension := email + security.ChainSeparator + clientName
 	self := ctx.LocalPrincipal()
 	if self == nil {
 		return noblessings, "", fmt.Errorf("server error: no authentication happened")
@@ -92,6 +83,16 @@
 	if err != nil {
 		return noblessings, "", err
 	}
+	extension := strings.Join([]string{
+		b.emailClassifier.Classify(email),
+		email,
+		// Append clientName (e.g., "android", "chrome") to the email and then bless under that.
+		// Since blessings issued by this process do not have many caveats on them and typically
+		// have a large expiry duration, we include the clientName in the extension so that
+		// servers can explicitly distinguish these clients while specifying authorization policies
+		// (say, via ACLs).
+		clientName,
+	}, security.ChainSeparator)
 	blessing, err := self.Bless(ctx.RemoteBlessings().PublicKey(), ctx.LocalBlessings(), extension, caveat)
 	if err != nil {
 		return noblessings, "", err
diff --git a/services/identity/blesser/oauth_test.go b/services/identity/blesser/oauth_test.go
index 4b20fd8..12c3edc 100644
--- a/services/identity/blesser/oauth_test.go
+++ b/services/identity/blesser/oauth_test.go
@@ -29,7 +29,7 @@
 		t.Errorf("BlessUsingAccessToken failed: %v", err)
 	}
 
-	wantExtension := oauth.MockEmail + security.ChainSeparator + oauth.MockClient
+	wantExtension := "users" + security.ChainSeparator + oauth.MockEmail + security.ChainSeparator + oauth.MockClient
 	if extension != wantExtension {
 		t.Errorf("got extension: %s, want: %s", extension, wantExtension)
 	}
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index ebdf5b6..bd1fa92 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -22,6 +22,7 @@
 	"v.io/core/veyron/services/identity/oauth"
 	"v.io/core/veyron/services/identity/revocation"
 	"v.io/core/veyron/services/identity/server"
+	"v.io/core/veyron/services/identity/util"
 )
 
 var (
@@ -32,7 +33,7 @@
 	googleConfigWeb     = flag.String("google_config_web", "", "Path to JSON-encoded OAuth client configuration for the web application that renders the audit log for blessings provided by this provider.")
 	googleConfigChrome  = flag.String("google_config_chrome", "", "Path to the JSON-encoded OAuth client configuration for Chrome browser applications that obtain blessings from this server (via the OAuthBlesser.BlessUsingAccessToken RPC) from this server.")
 	googleConfigAndroid = flag.String("google_config_android", "", "Path to the JSON-encoded OAuth client configuration for Android applications that obtain blessings from this server (via the OAuthBlesser.BlessUsingAccessToken RPC) from this server.")
-	googleDomain        = flag.String("google_domain", "", "An optional domain name. When set, only email addresses from this domain are allowed to authenticate via Google OAuth")
+	emailClassifier     util.EmailClassifier
 
 	// Flags controlling the HTTP server
 	host      = flag.String("host", defaultHost(), "Hostname the HTTP server listens on. This can be the name of the host running the webserver, but if running behind a NAT or load balancer, this should be the host name that clients will connect to. For example, if set to 'x.com', Veyron identities will have the IssuerName set to 'x.com' and clients can expect to find the root name and public key of the signer at 'x.com/blessing-root'.")
@@ -41,6 +42,7 @@
 )
 
 func main() {
+	flag.Var(&emailClassifier, "email_classifier", "A comma-separated list of <domain>=<prefix> pairs. For example 'google.com=internal,v.io=trusted'. When specified, then the blessings generated for email address of <domain> will use the extension <prefix>/<email> instead of the default extension of users/<email>.")
 	flag.Usage = usage
 	flag.Parse()
 
@@ -57,7 +59,7 @@
 		}
 	}
 
-	googleoauth, err := oauth.NewGoogleOAuth(*googleConfigWeb, *googleDomain)
+	googleoauth, err := oauth.NewGoogleOAuth(*googleConfigWeb)
 	if err != nil {
 		vlog.Fatalf("Failed to setup GoogleOAuth: %v", err)
 	}
@@ -82,7 +84,8 @@
 		reader,
 		revocationManager,
 		googleOAuthBlesserParams(googleoauth, revocationManager),
-		caveats.NewBrowserCaveatSelector())
+		caveats.NewBrowserCaveatSelector(),
+		&emailClassifier)
 	s.Serve(ctx, &listenSpec, *host, *httpaddr, *tlsconfig)
 }
 
@@ -108,7 +111,7 @@
 	params := blesser.OAuthBlesserParams{
 		OAuthProvider:     oauthProvider,
 		BlessingDuration:  365 * 24 * time.Hour,
-		DomainRestriction: *googleDomain,
+		EmailClassifier:   &emailClassifier,
 		RevocationManager: revocationManager,
 	}
 	if clientID, err := getOAuthClientID(*googleConfigChrome); err != nil {
diff --git a/services/identity/identityd_test/main.go b/services/identity/identityd_test/main.go
index d9c8a23..72dfa70 100644
--- a/services/identity/identityd_test/main.go
+++ b/services/identity/identityd_test/main.go
@@ -21,8 +21,6 @@
 )
 
 var (
-	googleDomain = flag.String("google_domain", "", "An optional domain name. When set, only email addresses from this domain are allowed to authenticate via Google OAuth")
-
 	// Flags controlling the HTTP server
 	host      = flag.String("host", "localhost", "Hostname the HTTP server listens on. This can be the name of the host running the webserver, but if running behind a NAT or load balancer, this should be the host name that clients will connect to. For example, if set to 'x.com', Veyron identities will have the IssuerName set to 'x.com' and clients can expect to find the root name and public key of the signer at 'x.com/blessing-root'.")
 	httpaddr  = flag.String("httpaddr", "localhost:8125", "Address on which the HTTP server listens on.")
@@ -54,7 +52,6 @@
 	params := blesser.OAuthBlesserParams{
 		OAuthProvider:     oauthProvider,
 		BlessingDuration:  duration,
-		DomainRestriction: *googleDomain,
 		RevocationManager: revocationManager,
 	}
 
@@ -68,7 +65,8 @@
 		reader,
 		revocationManager,
 		params,
-		caveats.NewMockCaveatSelector())
+		caveats.NewMockCaveatSelector(),
+		nil)
 	s.Serve(ctx, &listenSpec, *host, *httpaddr, *tlsconfig)
 }
 
diff --git a/services/identity/oauth/googleoauth.go b/services/identity/oauth/googleoauth.go
index 64baa4e..1cbf32c 100644
--- a/services/identity/oauth/googleoauth.go
+++ b/services/identity/oauth/googleoauth.go
@@ -6,7 +6,6 @@
 	"fmt"
 	"net/http"
 	"os"
-	"strings"
 
 	"v.io/core/veyron2/vlog"
 )
@@ -17,14 +16,13 @@
 	// Console for API access.
 	clientID, clientSecret   string
 	scope, authURL, tokenURL string
-	domain                   string
 	// URL used to verify google tokens.
 	// (From https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
 	// and https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken)
 	verifyURL string
 }
 
-func NewGoogleOAuth(configFile, domainRestriction string) (OAuthProvider, error) {
+func NewGoogleOAuth(configFile string) (OAuthProvider, error) {
 	clientID, clientSecret, err := getOAuthClientIDAndSecret(configFile)
 	if err != nil {
 		return nil, err
@@ -36,7 +34,6 @@
 		authURL:      "https://accounts.google.com/o/oauth2/auth",
 		tokenURL:     "https://accounts.google.com/o/oauth2/token",
 		verifyURL:    "https://www.googleapis.com/oauth2/v1/tokeninfo?",
-		domain:       domainRestriction,
 	}, nil
 }
 
@@ -86,10 +83,6 @@
 	if gtoken.Audience != config.ClientId {
 		return "", fmt.Errorf("unexpected audience(%v) in GoogleIDToken", gtoken.Audience)
 	}
-	if len(g.domain) > 0 && !strings.HasSuffix(gtoken.Email, "@"+g.domain) {
-		return "", fmt.Errorf("domain restrictions preclude %q from using this service", gtoken.Email)
-	}
-
 	return gtoken.Email, nil
 }
 
diff --git a/services/identity/oauth/handler.go b/services/identity/oauth/handler.go
index e341a93..6fd22e1 100644
--- a/services/identity/oauth/handler.go
+++ b/services/identity/oauth/handler.go
@@ -70,8 +70,10 @@
 	// MacaroonBlessingService is the object name to which macaroons create by this HTTP
 	// handler can be exchanged for a blessing.
 	MacaroonBlessingService string
-	// If non-empty, only email addressses from this domain will be blessed.
-	DomainRestriction string
+	// EmailClassifier is used to decide the prefix used for blessing extensions.
+	// For example, if EmailClassifier.Classify("foo@bar.com") returns "guests",
+	// then the email foo@bar.com will receive the blessing "guests/foo@bar.com".
+	EmailClassifier *util.EmailClassifier
 	// OAuthProvider is used to authenticate and get a blessee email.
 	OAuthProvider OAuthProvider
 	// CaveatSelector is used to obtain caveats from the user when seeking a blessing.
@@ -318,10 +320,6 @@
 		util.HTTPBadRequest(w, r, err)
 		return
 	}
-	if len(h.args.DomainRestriction) > 0 && !strings.HasSuffix(email, "@"+h.args.DomainRestriction) {
-		util.HTTPBadRequest(w, r, fmt.Errorf("blessings for name %q are not allowed due to domain restriction", email))
-		return
-	}
 	outputMacaroon, err := h.csrfCop.NewToken(w, r, clientIDCookie, addCaveatsMacaroon{
 		ToolRedirectURL: inputMacaroon.RedirectURL,
 		ToolState:       inputMacaroon.State,
@@ -355,9 +353,12 @@
 		util.HTTPBadRequest(w, r, fmt.Errorf("failed to create caveats: %v", err))
 		return
 	}
-	name := inputMacaroon.Email
+	parts := []string{
+		h.args.EmailClassifier.Classify(inputMacaroon.Email),
+		inputMacaroon.Email,
+	}
 	if len(blessingExtension) > 0 {
-		name = name + security.ChainSeparator + blessingExtension
+		parts = append(parts, blessingExtension)
 	}
 	if len(caveats) == 0 {
 		util.HTTPBadRequest(w, r, fmt.Errorf("server disallows attempts to bless with no caveats"))
@@ -366,7 +367,7 @@
 	m := BlessingMacaroon{
 		Creation: time.Now(),
 		Caveats:  caveats,
-		Name:     name,
+		Name:     strings.Join(parts, security.ChainSeparator),
 	}
 	macBytes, err := vom.Encode(m)
 	if err != nil {
diff --git a/services/identity/server/identityd.go b/services/identity/server/identityd.go
index 1aafdd1..b415f20 100644
--- a/services/identity/server/identityd.go
+++ b/services/identity/server/identityd.go
@@ -26,6 +26,7 @@
 	"v.io/core/veyron/services/identity/handlers"
 	"v.io/core/veyron/services/identity/oauth"
 	"v.io/core/veyron/services/identity/revocation"
+	"v.io/core/veyron/services/identity/util"
 	services "v.io/core/veyron/services/security"
 	"v.io/core/veyron/services/security/discharger"
 )
@@ -49,6 +50,7 @@
 	revocationManager  revocation.RevocationManager
 	oauthBlesserParams blesser.OAuthBlesserParams
 	caveatSelector     caveats.CaveatSelector
+	emailClassifier    *util.EmailClassifier
 }
 
 // NewIdentityServer returns a IdentityServer that:
@@ -56,7 +58,7 @@
 // - auditor and blessingLogReader to audit the root principal and read audit logs
 // - revocationManager to store revocation data and grant discharges
 // - oauthBlesserParams to configure the identity.OAuthBlesser service
-func NewIdentityServer(oauthProvider oauth.OAuthProvider, auditor audit.Auditor, blessingLogReader auditor.BlessingLogReader, revocationManager revocation.RevocationManager, oauthBlesserParams blesser.OAuthBlesserParams, caveatSelector caveats.CaveatSelector) *identityd {
+func NewIdentityServer(oauthProvider oauth.OAuthProvider, auditor audit.Auditor, blessingLogReader auditor.BlessingLogReader, revocationManager revocation.RevocationManager, oauthBlesserParams blesser.OAuthBlesserParams, caveatSelector caveats.CaveatSelector, emailClassifier *util.EmailClassifier) *identityd {
 	return &identityd{
 		oauthProvider,
 		auditor,
@@ -64,6 +66,7 @@
 		revocationManager,
 		oauthBlesserParams,
 		caveatSelector,
+		emailClassifier,
 	}
 }
 
@@ -107,6 +110,7 @@
 		MacaroonBlessingService: naming.JoinAddressName(published[0], macaroonService),
 		OAuthProvider:           s.oauthProvider,
 		CaveatSelector:          s.caveatSelector,
+		EmailClassifier:         s.emailClassifier,
 	})
 	if err != nil {
 		vlog.Fatalf("Failed to create HTTP handler for oauth authentication: %v", err)
diff --git a/services/identity/util/classify.go b/services/identity/util/classify.go
new file mode 100644
index 0000000..33e2e95
--- /dev/null
+++ b/services/identity/util/classify.go
@@ -0,0 +1,70 @@
+package util
+
+import (
+	"fmt"
+	"strings"
+	"sync"
+)
+
+const defaultClass = "users"
+
+// EmailClassifier classifies/categorizes email addresses based on the domain.
+type EmailClassifier struct {
+	mu sync.RWMutex
+	m  map[string]string
+}
+
+// Classify returns the classification of email.
+func (c *EmailClassifier) Classify(email string) string {
+	if c == nil {
+		return defaultClass
+	}
+	parts := strings.Split(email, "@")
+	if len(parts) != 2 {
+		return defaultClass
+	}
+	domain := parts[1]
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	if class := c.m[domain]; len(class) > 0 {
+		return class
+	}
+	return defaultClass
+}
+
+// Set implements flag.Value.
+//
+// value should be a comma-separated list of <domain>=<class> pairs.
+func (c *EmailClassifier) Set(value string) error {
+	m := make(map[string]string)
+	for _, entry := range strings.Split(value, ",") {
+		pair := strings.Split(entry, "=")
+		if len(pair) != 2 {
+			return fmt.Errorf("invalid pair %q: must be in <domain>=<class> format", entry)
+		}
+		domain := strings.TrimSpace(pair[0])
+		class := strings.TrimSpace(pair[1])
+		if len(domain) == 0 {
+			return fmt.Errorf("empty domain in %q", entry)
+		}
+		if len(class) == 0 {
+			return fmt.Errorf("empty class in %q", entry)
+		}
+		m[domain] = class
+	}
+	c.mu.Lock()
+	c.m = m
+	c.mu.Unlock()
+	return nil
+}
+
+// Get implements flag.Getter.
+func (c *EmailClassifier) Get() interface{} {
+	return c
+}
+
+func (c *EmailClassifier) String() string {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	return fmt.Sprintf("%v", c.m)
+}
diff --git a/services/identity/util/classify_test.go b/services/identity/util/classify_test.go
new file mode 100644
index 0000000..6077ee4
--- /dev/null
+++ b/services/identity/util/classify_test.go
@@ -0,0 +1,28 @@
+package util
+
+import (
+	"flag"
+	"testing"
+)
+
+func TestEmailClassifier(t *testing.T) {
+	fs := flag.NewFlagSet("TestEmailClassifier", flag.PanicOnError)
+	var c EmailClassifier
+	fs.Var(&c, "myflag", "my usage")
+	if err := fs.Parse([]string{"--myflag", "foo.com=internal,bar.com=external"}); err != nil {
+		t.Fatal(err)
+	}
+	tests := []struct {
+		in, out string
+	}{
+		{"batman@foo.com", "internal"},
+		{"bugsbunny@foo.com.com", "users"},
+		{"daffyduck@bar.com", "external"},
+		{"joker@other.com", "users"},
+	}
+	for _, test := range tests {
+		if got := c.Classify(test.in); got != test.out {
+			t.Errorf("%q: Got %q, want %q", test.in, got, test.out)
+		}
+	}
+}
diff --git a/services/identity/util/sql_config.go b/services/identity/util/sql_config.go
deleted file mode 100644
index f375d63..0000000
--- a/services/identity/util/sql_config.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package util
-
-import (
-	"database/sql"
-	"fmt"
-	_ "github.com/go-sql-driver/mysql"
-)
-
-func DBFromConfigDatabase(database string) (*sql.DB, error) {
-	db, err := sql.Open("mysql", database+"?parseTime=true")
-	if err != nil {
-		return nil, fmt.Errorf("failed to create database with database(%v): %v", database, err)
-	}
-	if err := db.Ping(); err != nil {
-		return nil, err
-	}
-	return db, nil
-}
diff --git a/services/mgmt/application/impl/acl_test.go b/services/mgmt/application/impl/acl_test.go
index c16dd3f..2f5b710 100644
--- a/services/mgmt/application/impl/acl_test.go
+++ b/services/mgmt/application/impl/acl_test.go
@@ -42,7 +42,6 @@
 }
 
 func appRepository(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	args = args[1:]
 	if len(args) < 2 {
 		vlog.Fatalf("repository expected at least name and store arguments and optionally ACL flags per TaggedACLMapFromFlag")
 	}
@@ -105,11 +104,7 @@
 		t.Fatal(err)
 	}
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "repo")
-	defer os.RemoveAll(crDir)
-
-	// Make server credentials derived from the test harness.
-	_, nms := mgmttest.RunShellCommand(t, sh, crEnv, repoCmd, "repo", storedir)
+	_, nms := mgmttest.RunShellCommand(t, sh, nil, repoCmd, "repo", storedir)
 	pid := mgmttest.ReadPID(t, nms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -240,11 +235,7 @@
 		t.Fatal(err)
 	}
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "repo")
-	defer os.RemoveAll(crDir)
-
-	// Make a server with the same credential as test harness.
-	_, nms := mgmttest.RunShellCommand(t, sh, crEnv, repoCmd, "repo", storedir)
+	_, nms := mgmttest.RunShellCommand(t, sh, nil, repoCmd, "repo", storedir)
 	pid := mgmttest.ReadPID(t, nms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -373,8 +364,6 @@
 	if err := idp.Bless(veyron2.GetPrincipal(ctx), "self"); err != nil {
 		t.Fatal(err)
 	}
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "repo")
-	defer os.RemoveAll(crDir)
 
 	// Make an TAM for use on the command line.
 	expected := access.TaggedACLMap{
@@ -390,8 +379,7 @@
 		t.Fatal(err)
 	}
 
-	// Start a server with the same credential as test harness.
-	_, nms := mgmttest.RunShellCommand(t, sh, crEnv, repoCmd, "--veyron.acl.literal", b.String(), "repo", storedir)
+	_, nms := mgmttest.RunShellCommand(t, sh, nil, repoCmd, "--veyron.acl.literal", b.String(), "repo", storedir)
 	pid := mgmttest.ReadPID(t, nms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
diff --git a/services/mgmt/application/impl/dispatcher.go b/services/mgmt/application/impl/dispatcher.go
index a825137..6b13186 100644
--- a/services/mgmt/application/impl/dispatcher.go
+++ b/services/mgmt/application/impl/dispatcher.go
@@ -39,7 +39,7 @@
 		// (Re)set the root ACLs.
 		path := naming.Join("/acls", "data")
 		_, tag, err := getACL(store, path)
-		if !verror.Is(err, ErrNotFound.ID) {
+		if err != nil && !verror.Is(err, ErrNotFound.ID) {
 			return nil, err
 		}
 		if err := setACL(store, path, acls, tag); err != nil {
diff --git a/services/mgmt/binary/impl/acl_test.go b/services/mgmt/binary/impl/acl_test.go
index 67e468b..7f81a0f 100644
--- a/services/mgmt/binary/impl/acl_test.go
+++ b/services/mgmt/binary/impl/acl_test.go
@@ -40,7 +40,6 @@
 }
 
 func binaryd(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	args = args[1:]
 	if len(args) < 2 {
 		vlog.Fatalf("binaryd expected at least name and store arguments and optionally ACL flags per TaggedACLMapFromFlag")
 	}
diff --git a/services/mgmt/device/deviced/server.go b/services/mgmt/device/deviced/server.go
index 33d7919..7362b43 100644
--- a/services/mgmt/device/deviced/server.go
+++ b/services/mgmt/device/deviced/server.go
@@ -6,11 +6,13 @@
 
 	"v.io/lib/cmdline"
 
+	vexec "v.io/core/veyron/lib/exec"
 	"v.io/core/veyron/lib/signals"
 	_ "v.io/core/veyron/profiles/roaming"
 	"v.io/core/veyron/services/mgmt/device/config"
 	"v.io/core/veyron/services/mgmt/device/impl"
 	"v.io/core/veyron2"
+	"v.io/core/veyron2/mgmt"
 	"v.io/core/veyron2/vlog"
 )
 
@@ -25,6 +27,17 @@
 	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
+	var testMode bool
+	// If this device manager was started by another device manager, it must
+	// be part of a self update to test that this binary works. In that
+	// case, we need to disable a lot of functionality.
+	if handle, err := vexec.GetChildHandle(); err == nil {
+		if _, err := handle.Config.Get(mgmt.ParentNameConfigKey); err == nil {
+			testMode = true
+			vlog.Infof("TEST MODE")
+		}
+	}
+
 	server, err := veyron2.NewServer(ctx)
 	if err != nil {
 		vlog.Errorf("NewServer() failed: %v", err)
@@ -50,16 +63,20 @@
 	// implementation detail).
 
 	var exitErr error
-	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, func() { exitErr = cmdline.ErrExitCode(*restartExitCode) })
+	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, testMode, func() { exitErr = cmdline.ErrExitCode(*restartExitCode) })
 	if err != nil {
 		vlog.Errorf("Failed to create dispatcher: %v", err)
 		return err
 	}
-	if err := server.ServeDispatcher(*publishAs, dispatcher); err != nil {
-		vlog.Errorf("Serve(%v) failed: %v", *publishAs, err)
+	var publishName string
+	if testMode == false {
+		publishName = *publishAs
+	}
+	if err := server.ServeDispatcher(publishName, dispatcher); err != nil {
+		vlog.Errorf("Serve(%v) failed: %v", publishName, err)
 		return err
 	}
-	vlog.VI(0).Infof("Device manager published as: %v", *publishAs)
+	vlog.VI(0).Infof("Device manager published as: %v", publishName)
 	impl.InvokeCallback(ctx, name)
 
 	// Wait until shutdown.  Ignore duplicate signals (sent by agent and
diff --git a/services/mgmt/device/impl/app_service.go b/services/mgmt/device/impl/app_service.go
index 2d40769..383ab09 100644
--- a/services/mgmt/device/impl/app_service.go
+++ b/services/mgmt/device/impl/app_service.go
@@ -411,6 +411,10 @@
 	if _, err := newVersion(call.Context(), installationDir, envelope, ""); err != nil {
 		return "", err
 	}
+	if newOrigin, ok := config[mgmt.AppOriginConfigKey]; ok {
+		delete(config, mgmt.AppOriginConfigKey)
+		applicationVON = newOrigin
+	}
 	if err := saveOrigin(installationDir, applicationVON); err != nil {
 		return "", err
 	}
@@ -838,11 +842,16 @@
 		vlog.Errorf("WaitForReady(%v) failed: %v", childReadyTimeout, err)
 		return verror2.Make(ErrOperationFailed, nil)
 	}
+	pid := handle.ChildPid()
 	childName, err := listener.waitForValue(childReadyTimeout)
 	if err != nil {
 		return verror2.Make(ErrOperationFailed, nil)
 	}
-	info.AppCycleMgrName, info.Pid = childName, handle.Pid()
+
+	// Because suidhelper uses Go's in-built support for setuid forking,
+	// handle.Pid() is the pid of suidhelper, not the pid of the app
+	// so use the pid returned in the app's ready status.
+	info.AppCycleMgrName, info.Pid = childName, pid
 	if err := saveInstanceInfo(instanceDir, info); err != nil {
 		return err
 	}
diff --git a/services/mgmt/device/impl/device_service.go b/services/mgmt/device/impl/device_service.go
index 629a283..0ff8ead 100644
--- a/services/mgmt/device/impl/device_service.go
+++ b/services/mgmt/device/impl/device_service.go
@@ -43,15 +43,16 @@
 	"os/exec"
 	"path/filepath"
 	"reflect"
+	"strconv"
 	"strings"
 	"sync"
-	"time"
 
 	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/mgmt"
 	"v.io/core/veyron2/naming"
+	"v.io/core/veyron2/security"
 	"v.io/core/veyron2/services/mgmt/application"
 	"v.io/core/veyron2/services/mgmt/binary"
 	"v.io/core/veyron2/services/mgmt/device"
@@ -60,7 +61,9 @@
 	"v.io/core/veyron2/vlog"
 
 	vexec "v.io/core/veyron/lib/exec"
+	"v.io/core/veyron/lib/flags/consts"
 	"v.io/core/veyron/lib/netstate"
+	vsecurity "v.io/core/veyron/security"
 	"v.io/core/veyron/services/mgmt/device/config"
 	"v.io/core/veyron/services/mgmt/profile"
 )
@@ -102,6 +105,7 @@
 	config         *config.State
 	disp           *dispatcher
 	uat            BlessingSystemAssociationStore
+	securityAgent  *securityAgentState
 }
 
 // managerInfo holds state about a running device manager.
@@ -216,6 +220,7 @@
 
 func (s *deviceService) revertDeviceManager(ctx *context.T) error {
 	if err := updateLink(s.config.Previous, s.config.CurrentLink); err != nil {
+		vlog.Errorf("updateLink failed: %v", err)
 		return err
 	}
 	if s.restartHandler != nil {
@@ -278,6 +283,61 @@
 	cfg.Set(mgmt.ParentNameConfigKey, listener.name())
 	cfg.Set(mgmt.ProtocolConfigKey, "tcp")
 	cfg.Set(mgmt.AddressConfigKey, "127.0.0.1:0")
+
+	var p security.Principal
+	var agentHandle []byte
+	if s.securityAgent != nil {
+		// TODO(rthellend): Cleanup principal
+		handle, conn, err := s.securityAgent.keyMgrAgent.NewPrincipal(ctx, false)
+		if err != nil {
+			vlog.Errorf("NewPrincipal() failed %v", err)
+			return verror2.Make(ErrOperationFailed, nil)
+		}
+		agentHandle = handle
+		var cancel func()
+		if p, cancel, err = agentPrincipal(ctx, conn); err != nil {
+			vlog.Errorf("agentPrincipal failed: %v", err)
+			return verror2.Make(ErrOperationFailed, nil)
+		}
+		defer cancel()
+
+	} else {
+		credentialsDir := filepath.Join(workspace, "credentials")
+		var err error
+		if p, err = vsecurity.CreatePersistentPrincipal(credentialsDir, nil); err != nil {
+			vlog.Errorf("CreatePersistentPrincipal(%v, nil) failed: %v", credentialsDir, err)
+			return verror2.Make(ErrOperationFailed, nil)
+		}
+		cmd.Env = append(cmd.Env, consts.VeyronCredentials+"="+credentialsDir)
+	}
+	dmPrincipal := veyron2.GetPrincipal(ctx)
+	dmBlessings, err := dmPrincipal.Bless(p.PublicKey(), dmPrincipal.BlessingStore().Default(), "testdm", security.UnconstrainedUse())
+	if err := p.BlessingStore().SetDefault(dmBlessings); err != nil {
+		vlog.Errorf("BlessingStore.SetDefault() failed: %v", err)
+		return verror2.Make(ErrOperationFailed, nil)
+	}
+	if _, err := p.BlessingStore().Set(dmBlessings, security.AllPrincipals); err != nil {
+		vlog.Errorf("BlessingStore.Set() failed: %v", err)
+		return verror2.Make(ErrOperationFailed, nil)
+	}
+	if err := p.AddToRoots(dmBlessings); err != nil {
+		vlog.Errorf("AddToRoots() failed: %v", err)
+		return verror2.Make(ErrOperationFailed, nil)
+	}
+
+	if s.securityAgent != nil {
+		file, err := s.securityAgent.keyMgrAgent.NewConnection(agentHandle)
+		if err != nil {
+			vlog.Errorf("NewConnection(%v) failed: %v", agentHandle, err)
+			return err
+		}
+		defer file.Close()
+
+		fd := len(cmd.ExtraFiles) + vexec.FileOffset
+		cmd.ExtraFiles = append(cmd.ExtraFiles, file)
+		cfg.Set(mgmt.SecurityAgentFDConfigKey, strconv.Itoa(fd))
+	}
+
 	handle := vexec.NewParentHandle(cmd, vexec.ConfigOpt{cfg})
 	// Start the child process.
 	if err := handle.Start(); err != nil {
@@ -296,35 +356,14 @@
 	}
 	childName, err := listener.waitForValue(childReadyTimeout)
 	if err != nil {
+		vlog.Errorf("waitForValue(%v) failed: %v", childReadyTimeout, err)
 		return verror2.Make(ErrOperationFailed, ctx)
 	}
-	// Check that invoking Revert() succeeds.
+	// Check that invoking Stop() succeeds.
 	childName = naming.Join(childName, "device")
 	dmClient := device.DeviceClient(childName)
-	linkOld, pathOld, err := s.getCurrentFileInfo()
-	if err != nil {
-		return verror2.Make(ErrOperationFailed, ctx)
-	}
-	// Since the resolution of mtime for files is seconds, the test sleeps
-	// for a second to make sure it can check whether the current symlink is
-	// updated.
-	time.Sleep(time.Second)
-	if err := dmClient.Revert(ctx); err != nil {
-		return verror2.Make(ErrOperationFailed, ctx)
-	}
-	linkNew, pathNew, err := s.getCurrentFileInfo()
-	if err != nil {
-		return verror2.Make(ErrOperationFailed, ctx)
-	}
-	// Check that the new device manager updated the current symbolic link.
-	if !linkOld.ModTime().Before(linkNew.ModTime()) {
-		vlog.Errorf("New device manager test failed")
-		return verror2.Make(ErrOperationFailed, ctx)
-	}
-	// Ensure that the current symbolic link points to the same script.
-	if pathNew != pathOld {
-		updateLink(pathOld, s.config.CurrentLink)
-		vlog.Errorf("New device manager test failed")
+	if err := dmClient.Stop(ctx, 0); err != nil {
+		vlog.Errorf("Stop() failed: %v", err)
 		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	if err := handle.Wait(childWaitTimeout); err != nil {
@@ -432,11 +471,10 @@
 		return err
 	}
 
-	// TODO(rthellend): testDeviceManager always fails due to https://github.com/veyron/release-issues/issues/714
-	// Uncomment when the bug is fixed.
-	//if err := s.testDeviceManager(ctx, workspace, envelope); err != nil {
-	//	return err
-	//}
+	if err := s.testDeviceManager(ctx, workspace, envelope); err != nil {
+		vlog.Errorf("testDeviceManager failed: %v", err)
+		return err
+	}
 
 	if err := updateLink(filepath.Join(workspace, "deviced.sh"), s.config.CurrentLink); err != nil {
 		return err
@@ -470,10 +508,12 @@
 
 func (s *deviceService) Revert(call ipc.ServerContext) error {
 	if s.config.Previous == "" {
+		vlog.Errorf("Revert failed: no previous version")
 		return verror2.Make(ErrUpdateNoOp, call.Context())
 	}
 	updatingState := s.updating
 	if updatingState.testAndSetUpdating() {
+		vlog.Errorf("Revert failed: already in progress")
 		return verror2.Make(ErrOperationInProgress, call.Context())
 	}
 	err := s.revertDeviceManager(call.Context())
diff --git a/services/mgmt/device/impl/dispatcher.go b/services/mgmt/device/impl/dispatcher.go
index 5632858..7dc317e 100644
--- a/services/mgmt/device/impl/dispatcher.go
+++ b/services/mgmt/device/impl/dispatcher.go
@@ -34,6 +34,7 @@
 	updating       *updatingState
 	securityAgent  *securityAgentState
 	restartHandler func()
+	testMode       bool
 }
 
 // dispatcher holds the state of the device manager dispatcher.
@@ -72,7 +73,7 @@
 )
 
 // NewDispatcher is the device manager dispatcher factory.
-func NewDispatcher(principal security.Principal, config *config.State, restartHandler func()) (*dispatcher, error) {
+func NewDispatcher(principal security.Principal, config *config.State, testMode bool, restartHandler func()) (ipc.Dispatcher, error) {
 	if err := config.Validate(); err != nil {
 		return nil, fmt.Errorf("invalid config %v: %v", config, err)
 	}
@@ -95,6 +96,7 @@
 			callback:       newCallbackState(config.Name),
 			updating:       newUpdatingState(),
 			restartHandler: restartHandler,
+			testMode:       testMode,
 		},
 		config:    config,
 		uat:       uat,
@@ -121,6 +123,9 @@
 			}
 		}
 	}
+	if testMode {
+		return &testModeDispatcher{d}, nil
+	}
 	return d, nil
 }
 
@@ -166,8 +171,17 @@
 
 // TODO(rjkroege): Consider refactoring authorizer implementations to
 // be shareable with other components.
-func newAuthorizer(principal security.Principal, dir string, locks *acls.Locks) (security.Authorizer, error) {
-	rootTam, _, err := locks.GetPathACL(principal, dir)
+func (d *dispatcher) newAuthorizer() (security.Authorizer, error) {
+	if d.internal.testMode {
+		// In test mode, the device manager will not be able to read
+		// the ACLs, because they were signed with the key of the real
+		// device manager. It's not a problem because the
+		// testModeDispatcher overrides the authorizer anyway.
+		return nil, nil
+	}
+
+	dir := d.getACLDir()
+	rootTam, _, err := d.locks.GetPathACL(d.principal, dir)
 
 	if err != nil && os.IsNotExist(err) {
 		vlog.VI(1).Infof("GetPathACL(%s) failed: %v", dir, err)
@@ -194,7 +208,8 @@
 			i--
 		}
 	}
-	auth, err := newAuthorizer(d.principal, d.getACLDir(), d.locks)
+
+	auth, err := d.newAuthorizer()
 	if err != nil {
 		return nil, nil, err
 	}
@@ -214,6 +229,7 @@
 			config:         d.config,
 			disp:           d,
 			uat:            d.uat,
+			securityAgent:  d.internal.securityAgent,
 		})
 		return receiver, auth, nil
 	case appsSuffix:
@@ -252,9 +268,6 @@
 				return invoker, auth, nil
 			}
 		}
-		if err != nil {
-			return nil, nil, err
-		}
 		receiver := device.ApplicationServer(&appService{
 			callback:      d.internal.callback,
 			config:        d.config,
@@ -289,6 +302,27 @@
 	}
 }
 
+// testModeDispatcher is a wrapper around the real dispatcher. It returns the
+// exact same object as the real dispatcher, but the authorizer only allows
+// calls to "device".Stop().
+type testModeDispatcher struct {
+	realDispatcher ipc.Dispatcher
+}
+
+func (d *testModeDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
+	obj, _, err := d.realDispatcher.Lookup(suffix)
+	return obj, d, err
+}
+
+func (testModeDispatcher) Authorize(ctx security.Context) error {
+	if ctx.Suffix() == deviceSuffix && ctx.Method() == "Stop" {
+		vlog.Infof("testModeDispatcher.Authorize: Allow %q.%s()", ctx.Suffix(), ctx.Method())
+		return nil
+	}
+	vlog.Infof("testModeDispatcher.Authorize: Reject %q.%s()", ctx.Suffix(), ctx.Method())
+	return verror.Make(ErrInvalidSuffix, nil)
+}
+
 func newAppSpecificAuthorizer(sec security.Authorizer, config *config.State, suffix []string) (security.Authorizer, error) {
 	// TODO(rjkroege): This does not support <appname>.Start() to start all
 	// instances. Correct this.
diff --git a/services/mgmt/device/impl/impl_test.go b/services/mgmt/device/impl/impl_test.go
index d146f15..72402e9 100644
--- a/services/mgmt/device/impl/impl_test.go
+++ b/services/mgmt/device/impl/impl_test.go
@@ -30,6 +30,7 @@
 	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/ipc"
+	"v.io/core/veyron2/mgmt"
 	"v.io/core/veyron2/naming"
 	"v.io/core/veyron2/security"
 	"v.io/core/veyron2/services/mgmt/application"
@@ -42,6 +43,7 @@
 	"v.io/core/veyron2/vlog"
 
 	"v.io/core/veyron/lib/expect"
+	"v.io/core/veyron/lib/flags/consts"
 	"v.io/core/veyron/lib/modules"
 	"v.io/core/veyron/lib/signals"
 	"v.io/core/veyron/lib/testutil"
@@ -77,13 +79,17 @@
 	modules.RegisterChild(execScriptCmd, "", execScript)
 	modules.RegisterChild(deviceManagerCmd, "", deviceManager)
 	modules.RegisterChild(appCmd, "", app)
-	testutil.Init()
 
 	if modules.IsModulesProcess() {
 		return
 	}
 }
 
+func TestMain(m *testing.M) {
+	testutil.Init()
+	os.Exit(m.Run())
+}
+
 // TestHelperProcess is the entrypoint for the modules commands in a
 // a test subprocess.
 func TestHelperProcess(t *testing.T) {
@@ -105,7 +111,6 @@
 
 // execScript launches the script passed as argument.
 func execScript(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	args = args[1:]
 	if want, got := 1, len(args); want != got {
 		vlog.Fatalf("execScript expected %d arguments, got %d instead", want, got)
 	}
@@ -132,7 +137,6 @@
 func deviceManager(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	ctx, shutdown := testutil.InitForTest()
 
-	args = args[1:]
 	if len(args) == 0 {
 		vlog.Fatalf("deviceManager expected at least an argument")
 	}
@@ -160,11 +164,13 @@
 	// script prepared by a previous version of the device manager.
 	if len(args) > 0 {
 		if want, got := 4, len(args); want != got {
-			vlog.Fatalf("expected %d additional arguments, got %d instead", want, got)
+			vlog.Fatalf("expected %d additional arguments, got %d instead: %q", want, got, args)
 		}
 		configState.Root, configState.Helper, configState.Origin, configState.CurrentLink = args[0], args[1], args[2], args[3]
 	}
-	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, func() { fmt.Println("restart handler") })
+	blessings := fmt.Sprint(veyron2.GetPrincipal(ctx).BlessingStore().Default())
+	testMode := strings.HasSuffix(blessings, "/testdm")
+	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, testMode, func() { fmt.Println("restart handler") })
 	if err != nil {
 		vlog.Fatalf("Failed to create device manager dispatcher: %v", err)
 	}
@@ -180,7 +186,7 @@
 	if val, present := env["PAUSE_BEFORE_STOP"]; present && val == "1" {
 		modules.WaitForEOF(stdin)
 	}
-	if dispatcher.Leaking() {
+	if impl.DispatcherLeaking(dispatcher) {
 		vlog.Fatalf("device manager leaking resources")
 	}
 	return nil
@@ -253,7 +259,6 @@
 
 	veyron2.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
 
-	args = args[1:]
 	if expected, got := 1, len(args); expected != got {
 		vlog.Fatalf("Unexpected number of arguments: expected %d, got %d", expected, got)
 	}
@@ -363,9 +368,7 @@
 	// Set up a second version of the device manager. The information in the
 	// envelope will be used by the device manager to stage the next
 	// version.
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "child")
-	defer os.RemoveAll(crDir)
-	*envelope = envelopeFromShell(sh, crEnv, deviceManagerCmd, application.DeviceManagerTitle, "v2DM")
+	*envelope = envelopeFromShell(sh, nil, deviceManagerCmd, application.DeviceManagerTitle, "v2DM")
 	updateDevice(t, ctx, "factoryDM")
 
 	// Current link should have been updated to point to v2.
@@ -407,9 +410,7 @@
 	}
 
 	// Create a third version of the device manager and issue an update.
-	crDir, crEnv = mgmttest.CredentialsForChild(ctx, "child")
-	defer os.RemoveAll(crDir)
-	*envelope = envelopeFromShell(sh, crEnv, deviceManagerCmd, application.DeviceManagerTitle, "v3DM")
+	*envelope = envelopeFromShell(sh, nil, deviceManagerCmd, application.DeviceManagerTitle, "v3DM")
 	updateDevice(t, ctx, "v2DM")
 
 	scriptPathV3 := evalLink()
@@ -566,12 +567,9 @@
 	// Create a script wrapping the test target that implements suidhelper.
 	helperPath := generateSuidHelperScript(t, root)
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crDir)
-
 	// Set up the device manager.  Since we won't do device manager updates,
 	// don't worry about its application envelope and current link.
-	dmh, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+	dmh, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
 	mgmttest.ReadPID(t, dms)
 
 	// Create the local server that the app uses to let us know it's ready.
@@ -584,8 +582,17 @@
 	*envelope = envelopeFromShell(sh, []string{testEnvVarName + "=env-val-envelope"}, appCmd, "google naps", fmt.Sprintf("--%s=flag-val-envelope", testFlagName), "appV1")
 
 	// Install the app.  The config-specified flag value for testFlagName
-	// should override the value specified in the envelope above.
-	appID := installApp(t, ctx, device.Config{testFlagName: "flag-val-install"})
+	// should override the value specified in the envelope above, and the
+	// config-specified value for origin should override the value in the
+	// Install rpc argument.
+	mtName, ok := sh.GetVar(consts.NamespaceRootPrefix)
+	if !ok {
+		t.Fatalf("failed to get namespace root var from shell")
+	}
+	// This rooted name should be equivalent to the relative name "ar", but
+	// we want to test that the config override for origin works.
+	rootedAppRepoName := naming.Join(mtName, "ar")
+	appID := installApp(t, ctx, device.Config{testFlagName: "flag-val-install", mgmt.AppOriginConfigKey: rootedAppRepoName})
 	installationDebug := debug(t, ctx, appID)
 	// We spot-check a couple pieces of information we expect in the debug
 	// output.
@@ -593,7 +600,7 @@
 	// logic that assumes too much about the format?  This may be one
 	// argument in favor of making the output of Debug a struct instead of
 	// free-form string.
-	if !strings.Contains(installationDebug, "Origin: ar") {
+	if !strings.Contains(installationDebug, fmt.Sprintf("Origin: %v", rootedAppRepoName)) {
 		t.Fatalf("debug response doesn't contain expected info: %v", installationDebug)
 	}
 	if !strings.Contains(installationDebug, "Config: map[random_test_flag:flag-val-install]") {
@@ -802,15 +809,12 @@
 	root, cleanup := mgmttest.SetupRootDir(t, "devicemanager")
 	defer cleanup()
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crDir)
-
 	// Create a script wrapping the test target that implements suidhelper.
 	helperPath := generateSuidHelperScript(t, root)
 
 	// Set up the device manager.  Since we won't do device manager updates,
 	// don't worry about its application envelope and current link.
-	_, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+	_, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -896,12 +900,9 @@
 		t.Fatal(err)
 	}
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crDir)
-
 	// Set up the device manager.  Since we won't do device manager updates,
 	// don't worry about its application envelope and current link.
-	_, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
+	_, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -1042,15 +1043,12 @@
 	root, cleanup := mgmttest.SetupRootDir(t, "devicemanager")
 	defer cleanup()
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crDir)
-
 	// Create a script wrapping the test target that implements suidhelper.
 	helperPath := generateSuidHelperScript(t, root)
 
 	// Set up the device manager.  Since we won't do device manager updates,
 	// don't worry about its application envelope and current link.
-	_, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+	_, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -1212,15 +1210,12 @@
 	root, cleanup := mgmttest.SetupRootDir(t, "devicemanager")
 	defer cleanup()
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crDir)
-
 	// Create a script wrapping the test target that implements suidhelper.
 	helperPath := generateSuidHelperScript(t, root)
 
 	// Set up the device manager.  Since we won't do device manager updates,
 	// don't worry about its application envelope and current link.
-	_, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+	_, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -1298,10 +1293,8 @@
 	if err := idp.Bless(veyron2.GetPrincipal(otherCtx), "other"); err != nil {
 		t.Fatal(err)
 	}
-	crFile, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crFile)
 
-	_, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
+	_, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
@@ -1408,13 +1401,10 @@
 		t.Fatal(err)
 	}
 
-	crDir, crEnv := mgmttest.CredentialsForChild(ctx, "devicemanager")
-	defer os.RemoveAll(crDir)
-
 	// Create a script wrapping the test target that implements suidhelper.
 	helperPath := generateSuidHelperScript(t, root)
 
-	_, dms := mgmttest.RunShellCommand(t, sh, crEnv, deviceManagerCmd, "-mocksetuid", "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+	_, dms := mgmttest.RunShellCommand(t, sh, nil, deviceManagerCmd, "-mocksetuid", "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dms)
 	defer syscall.Kill(pid, syscall.SIGINT)
 
diff --git a/services/mgmt/device/impl/only_for_test.go b/services/mgmt/device/impl/only_for_test.go
index 082fc25..6f92afc 100644
--- a/services/mgmt/device/impl/only_for_test.go
+++ b/services/mgmt/device/impl/only_for_test.go
@@ -2,9 +2,11 @@
 
 import (
 	"flag"
+	"fmt"
 	"os"
 	"path/filepath"
 
+	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/services/mgmt/device"
 	"v.io/core/veyron2/vlog"
 )
@@ -20,8 +22,15 @@
 	return len(c.channels) > 0
 }
 
-func (d *dispatcher) Leaking() bool {
-	return d.internal.callback.leaking()
+func DispatcherLeaking(d ipc.Dispatcher) bool {
+	switch obj := d.(type) {
+	case *dispatcher:
+		return obj.internal.callback.leaking()
+	case *testModeDispatcher:
+		return obj.realDispatcher.(*dispatcher).internal.callback.leaking()
+	default:
+		panic(fmt.Sprintf("unexpected type: %T", d))
+	}
 }
 
 func init() {
diff --git a/services/mgmt/device/impl/util.go b/services/mgmt/device/impl/util.go
index 596ef71..54d90d2 100644
--- a/services/mgmt/device/impl/util.go
+++ b/services/mgmt/device/impl/util.go
@@ -29,7 +29,7 @@
 		vlog.Errorf("Download(%v) failed: %v", name, err)
 		return verror2.Make(ErrOperationFailed, nil)
 	}
-	path, perm := filepath.Join(workspace, fileName), os.FileMode(755)
+	path, perm := filepath.Join(workspace, fileName), os.FileMode(0755)
 	if err := ioutil.WriteFile(path, data, perm); err != nil {
 		vlog.Errorf("WriteFile(%v, %v) failed: %v", path, perm, err)
 		return verror2.Make(ErrOperationFailed, nil)
diff --git a/services/mgmt/lib/testutil/modules.go b/services/mgmt/lib/testutil/modules.go
index 23aa53e..dcfecf4 100644
--- a/services/mgmt/lib/testutil/modules.go
+++ b/services/mgmt/lib/testutil/modules.go
@@ -31,7 +31,7 @@
 
 // StartRootMT sets up a root mount table for tests.
 func StartRootMT(t *testing.T, sh *modules.Shell) (string, modules.Handle) {
-	h, err := sh.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0")
+	h, err := sh.Start(core.RootMTCommand, nil, "--veyron.tcp.address=127.0.0.1:0")
 	if err != nil {
 		t.Fatalf("failed to start root mount table: %s", err)
 	}
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 1812a12..f90a688 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -14,6 +14,8 @@
 
 	"v.io/core/veyron2/services/security/access"
 
+	"v.io/core/veyron2/services/security/access/object"
+
 	// The non-user imports are prefixed with "__" to prevent collisions.
 	__veyron2 "v.io/core/veyron2"
 	__context "v.io/core/veyron2/context"
@@ -188,7 +190,7 @@
 }
 
 func (s implApplicationServerStub) Describe__() []__ipc.InterfaceDesc {
-	return []__ipc.InterfaceDesc{ApplicationDesc, repository.ApplicationDesc, access.ObjectDesc}
+	return []__ipc.InterfaceDesc{ApplicationDesc, repository.ApplicationDesc, object.ObjectDesc}
 }
 
 // ApplicationDesc describes the Application interface.
diff --git a/services/mgmt/vtrace/impl/vtrace.go b/services/mgmt/vtrace/impl/vtrace.go
index 3aa22dd..066f7b2 100644
--- a/services/mgmt/vtrace/impl/vtrace.go
+++ b/services/mgmt/vtrace/impl/vtrace.go
@@ -10,7 +10,7 @@
 
 type vtraceService struct{}
 
-func (v *vtraceService) Trace(ctx ipc.ServerContext, id uniqueid.ID) (vtrace.TraceRecord, error) {
+func (v *vtraceService) Trace(ctx ipc.ServerContext, id uniqueid.Id) (vtrace.TraceRecord, error) {
 	store := vtrace.GetStore(ctx.Context())
 	tr := store.TraceRecord(id)
 	if tr == nil {
diff --git a/tools/application/doc.go b/tools/application/doc.go
index 31b8cfa..26deafa 100644
--- a/tools/application/doc.go
+++ b/tools/application/doc.go
@@ -38,9 +38,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
@@ -62,11 +72,12 @@
 Add the given envelope to the application for the given profiles.
 
 Usage:
-   application put <application> <profiles> <envelope>
+   application put <application> <profiles> [<envelope>]
 
 <application> is the full name of the application. <profiles> is a
 comma-separated list of profiles. <envelope> is the file that contains a
-JSON-encoded envelope.
+JSON-encoded envelope. If this file is not provided, the user will be prompted
+to enter the data manually.
 
 Application Remove
 
diff --git a/tools/binary/doc.go b/tools/binary/doc.go
index 3807988..cac49eb 100644
--- a/tools/binary/doc.go
+++ b/tools/binary/doc.go
@@ -36,9 +36,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
diff --git a/tools/build/doc.go b/tools/build/doc.go
index bd39613..d58afb3 100644
--- a/tools/build/doc.go
+++ b/tools/build/doc.go
@@ -33,9 +33,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
diff --git a/tools/debug/doc.go b/tools/debug/doc.go
index 3bf5c2f..248ac28 100644
--- a/tools/debug/doc.go
+++ b/tools/debug/doc.go
@@ -37,9 +37,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
@@ -173,7 +183,7 @@
 $ debug pprof run a/b/c heap --text $ debug pprof run a/b/c profile -gv
 
 The debug pprof run flags are:
- -pprofcmd=veyron go tool pprof
+ -pprofcmd=v23 go tool pprof
    The pprof command to use.
 
 Debug Pprof Proxy
diff --git a/tools/debug/impl.go b/tools/debug/impl.go
index a846c55..4d423ba 100644
--- a/tools/debug/impl.go
+++ b/tools/debug/impl.go
@@ -72,7 +72,7 @@
 }
 
 func doFetchTrace(ctx *context.T, wg *sync.WaitGroup, client vtracesvc.StoreClientStub,
-	id uniqueid.ID, traces chan *vtrace.TraceRecord, errors chan error) {
+	id uniqueid.Id, traces chan *vtrace.TraceRecord, errors chan error) {
 	defer wg.Done()
 
 	trace, err := client.Trace(ctx, id)
diff --git a/tools/mgmt/device/doc.go b/tools/mgmt/device/doc.go
index b760e71..c8f4780 100644
--- a/tools/mgmt/device/doc.go
+++ b/tools/mgmt/device/doc.go
@@ -75,21 +75,23 @@
 Install the given application.
 
 Usage:
-   device install <device> <application> [<config override>]
+   device install [flags] <device> <application>
 
 <device> is the veyron object name of the device manager's app service.
 
 <application> is the veyron object name of the application.
 
-<config override> is an optional JSON-encoded device.Config object, of the form:
-   '{"flag1":"value1","flag2":"value2"}'.
+The device install flags are:
+ -config={}
+   JSON-encoded device.Config object, of the form:
+   '{"flag1":"value1","flag2":"value2"}'
 
 Device Install-Local
 
 Install the given application, specified using a local path.
 
 Usage:
-   device install-local <device> <title> [ENV=VAL ...] binary [--flag=val ...]
+   device install-local [flags] <device> <title> [ENV=VAL ...] binary [--flag=val ...]
 
 <device> is the veyron object name of the device manager's app service.
 
@@ -98,6 +100,11 @@
 This is followed by an arbitrary number of environment variable settings, the
 local path for the binary to install, and arbitrary flag settings.
 
+The device install-local flags are:
+ -config={}
+   JSON-encoded device.Config object, of the form:
+   '{"flag1":"value1","flag2":"value2"}'
+
 Device Start
 
 Start an instance of the given application.
diff --git a/tools/mgmt/device/impl/impl.go b/tools/mgmt/device/impl/impl.go
index 8762b8a..2600b4e 100644
--- a/tools/mgmt/device/impl/impl.go
+++ b/tools/mgmt/device/impl/impl.go
@@ -17,29 +17,43 @@
 	Name:     "install",
 	Short:    "Install the given application.",
 	Long:     "Install the given application.",
-	ArgsName: "<device> <application> [<config override>]",
+	ArgsName: "<device> <application>",
 	ArgsLong: `
 <device> is the veyron object name of the device manager's app service.
 
 <application> is the veyron object name of the application.
+`,
+}
 
-<config override> is an optional JSON-encoded device.Config object, of the form:
-   '{"flag1":"value1","flag2":"value2"}'.`,
+type configFlag device.Config
+
+func (c *configFlag) String() string {
+	jsonConfig, _ := json.Marshal(c)
+	return string(jsonConfig)
+}
+func (c *configFlag) Set(s string) error {
+	if err := json.Unmarshal([]byte(s), c); err != nil {
+		return fmt.Errorf("Unmarshal(%v) failed: %v", s, err)
+	}
+	return nil
+}
+
+var configOverride configFlag = configFlag{}
+
+func init() {
+	cmdInstall.Flags.Var(&configOverride, "config", "JSON-encoded device.Config object, of the form: '{\"flag1\":\"value1\",\"flag2\":\"value2\"}'")
 }
 
 func runInstall(cmd *cmdline.Command, args []string) error {
-	if expectedMin, expectedMax, got := 2, 3, len(args); expectedMin > got || expectedMax < got {
-		return cmd.UsageErrorf("install: incorrect number of arguments, expected between %d and %d, got %d", expectedMin, expectedMax, got)
+	if expected, got := 2, len(args); expected != got {
+		return cmd.UsageErrorf("install: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	deviceName, appName := args[0], args[1]
-	var cfg device.Config
-	if len(args) > 2 {
-		jsonConfig := args[2]
-		if err := json.Unmarshal([]byte(jsonConfig), &cfg); err != nil {
-			return fmt.Errorf("Unmarshal(%v) failed: %v", jsonConfig, err)
-		}
-	}
-	appID, err := device.ApplicationClient(deviceName).Install(gctx, appName, cfg)
+	appID, err := device.ApplicationClient(deviceName).Install(gctx, appName, device.Config(configOverride))
+	// Reset the value for any future invocations of "install" or
+	// "install-local" (we run more than one command per process in unit
+	// tests).
+	configOverride = configFlag{}
 	if err != nil {
 		return fmt.Errorf("Install failed: %v", err)
 	}
diff --git a/tools/mgmt/device/impl/impl_test.go b/tools/mgmt/device/impl/impl_test.go
index 435d185..09e0a83 100644
--- a/tools/mgmt/device/impl/impl_test.go
+++ b/tools/mgmt/device/impl/impl_test.go
@@ -190,35 +190,35 @@
 		expectedTape interface{}
 	}{
 		{
-			[]string{"install", "blech"},
+			[]string{"blech"},
 			nil,
 			true,
 			nil,
 			nil,
 		},
 		{
-			[]string{"install", "blech1", "blech2", "blech3", "blech4"},
+			[]string{"blech1", "blech2", "blech3", "blech4"},
 			nil,
 			true,
 			nil,
 			nil,
 		},
 		{
-			[]string{"install", deviceName, appNameNoFetch, "not-valid-json"},
+			[]string{deviceName, appNameNoFetch, "not-valid-json"},
 			nil,
 			true,
 			nil,
 			nil,
 		},
 		{
-			[]string{"install", deviceName, appNameNoFetch},
+			[]string{deviceName, appNameNoFetch},
 			nil,
 			false,
 			InstallResponse{appId, nil},
 			InstallStimulus{"Install", appNameNoFetch, nil, application.Envelope{}, 0},
 		},
 		{
-			[]string{"install", deviceName, appNameNoFetch},
+			[]string{deviceName, appNameNoFetch},
 			cfg,
 			false,
 			InstallResponse{appId, nil},
@@ -231,8 +231,9 @@
 			if err != nil {
 				t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.config, err)
 			}
-			c.args = append(c.args, string(jsonConfig))
+			c.args = append([]string{fmt.Sprintf("--config=%s", string(jsonConfig))}, c.args...)
 		}
+		c.args = append([]string{"install"}, c.args...)
 		err := cmd.Execute(c.args)
 		if c.shouldErr {
 			if err == nil {
diff --git a/tools/mgmt/device/impl/local_install.go b/tools/mgmt/device/impl/local_install.go
index a8b8fb9..1598559 100644
--- a/tools/mgmt/device/impl/local_install.go
+++ b/tools/mgmt/device/impl/local_install.go
@@ -23,9 +23,6 @@
 	"v.io/lib/cmdline"
 )
 
-// TODO(caprita): Add a way to provide an origin for the app, so we can do
-// updates after it's been installed.
-
 var cmdInstallLocal = &cmdline.Command{
 	Run:      runInstallLocal,
 	Name:     "install-local",
@@ -41,6 +38,10 @@
 local path for the binary to install, and arbitrary flag settings.`,
 }
 
+func init() {
+	cmdInstallLocal.Flags.Var(&configOverride, "config", "JSON-encoded device.Config object, of the form: '{\"flag1\":\"value1\",\"flag2\":\"value2\"}'")
+}
+
 type openAuthorizer struct{}
 
 func (openAuthorizer) Authorize(security.Context) error { return nil }
@@ -226,7 +227,11 @@
 
 	objects["application"] = repository.ApplicationServer(envelopeInvoker(envelope))
 	appName := naming.Join(name, "application")
-	appID, err := device.ApplicationClient(deviceName).Install(gctx, appName, nil)
+	appID, err := device.ApplicationClient(deviceName).Install(gctx, appName, device.Config(configOverride))
+	// Reset the value for any future invocations of "install" or
+	// "install-local" (we run more than one command per process in unit
+	// tests).
+	configOverride = configFlag{}
 	if err != nil {
 		return fmt.Errorf("Install failed: %v", err)
 	}
diff --git a/tools/mgmt/device/impl/local_install_test.go b/tools/mgmt/device/impl/local_install_test.go
index 7abb65f..9a65931 100644
--- a/tools/mgmt/device/impl/local_install_test.go
+++ b/tools/mgmt/device/impl/local_install_test.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"encoding/json"
 	"fmt"
 	"os"
 	"reflect"
@@ -10,6 +11,7 @@
 
 	"v.io/core/veyron2/naming"
 	"v.io/core/veyron2/services/mgmt/application"
+	"v.io/core/veyron2/services/mgmt/device"
 
 	"v.io/core/veyron/tools/mgmt/device/impl"
 )
@@ -35,18 +37,19 @@
 		stderrSubstr string
 	}{
 		{
-			[]string{"install-local", deviceName}, "incorrect number of arguments",
+			[]string{deviceName}, "incorrect number of arguments",
 		},
 		{
-			[]string{"install-local", deviceName, appTitle}, "missing binary",
+			[]string{deviceName, appTitle}, "missing binary",
 		},
 		{
-			[]string{"install-local", deviceName, appTitle, "a=b"}, "missing binary",
+			[]string{deviceName, appTitle, "a=b"}, "missing binary",
 		},
 		{
-			[]string{"install-local", deviceName, appTitle, "foo"}, "binary foo not found",
+			[]string{deviceName, appTitle, "foo"}, "binary foo not found",
 		},
 	} {
+		c.args = append([]string{"install-local"}, c.args...)
 		if err := cmd.Execute(c.args); err == nil {
 			t.Fatalf("test case %d: wrongly failed to receive a non-nil error.", i)
 		} else {
@@ -69,20 +72,37 @@
 		t.Fatalf("Failed to stat %v: %v", binary, err)
 	}
 	binarySize := fi.Size()
+	cfg := device.Config{"someflag": "somevalue"}
 	for i, c := range []struct {
 		args         []string
+		config       device.Config
 		expectedTape interface{}
 	}{
 		{
-			[]string{"install-local", deviceName, appTitle, binary},
+			[]string{deviceName, appTitle, binary},
+			nil,
 			InstallStimulus{"Install", appNameAfterFetch, nil, application.Envelope{Title: appTitle, Binary: binaryNameAfterFetch}, binarySize},
 		},
 		{
-			[]string{"install-local", deviceName, appTitle, "ENV1=V1", "ENV2=V2", binary, "FLAG1=V1", "FLAG2=V2"},
+			[]string{deviceName, appTitle, binary},
+			cfg,
+			InstallStimulus{"Install", appNameAfterFetch, cfg, application.Envelope{Title: appTitle, Binary: binaryNameAfterFetch}, binarySize},
+		},
+		{
+			[]string{deviceName, appTitle, "ENV1=V1", "ENV2=V2", binary, "FLAG1=V1", "FLAG2=V2"},
+			nil,
 			InstallStimulus{"Install", appNameAfterFetch, nil, application.Envelope{Title: appTitle, Binary: binaryNameAfterFetch, Env: []string{"ENV1=V1", "ENV2=V2"}, Args: []string{"FLAG1=V1", "FLAG2=V2"}}, binarySize},
 		},
 	} {
 		tape.SetResponses([]interface{}{InstallResponse{appId, nil}})
+		if c.config != nil {
+			jsonConfig, err := json.Marshal(c.config)
+			if err != nil {
+				t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.config, err)
+			}
+			c.args = append([]string{fmt.Sprintf("--config=%s", string(jsonConfig))}, c.args...)
+		}
+		c.args = append([]string{"install-local"}, c.args...)
 		if err := cmd.Execute(c.args); err != nil {
 			t.Fatalf("test case %d: %v", i, err)
 		}
diff --git a/tools/mgmt/test.sh b/tools/mgmt/test.sh
index 7a28463..7cf1f9e 100755
--- a/tools/mgmt/test.sh
+++ b/tools/mgmt/test.sh
@@ -116,14 +116,15 @@
   local -r APPLICATIOND_NAME="applicationd"
   local -r DEVICED_APP_NAME="${APPLICATIOND_NAME}/deviced/test"
 
-  BIN_STAGING_DIR=$(shell::tmp_dir)
+  BIN_STAGING_DIR="${WORKDIR}/bin"
+  mkdir -p "${BIN_STAGING_DIR}"
   cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${INITHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
   shell_test::setup_server_test
 
   # Install and start device manager.
-  DM_INSTALL_DIR=$(shell::tmp_dir)
+  DM_INSTALL_DIR="${WORKDIR}/dm"
 
-  export VANADIUM_DEVICE_DIR="${DM_INSTALL_DIR}/dm"
+  export VANADIUM_DEVICE_DIR="${DM_INSTALL_DIR}"
 
   if [[ "${WITH_SUID}" == "--with_suid" ]]; then
     "${DEVICE_SCRIPT}" install "${BIN_STAGING_DIR}" --origin="${DEVICED_APP_NAME}" -- --veyron.tcp.address=127.0.0.1:0
@@ -170,7 +171,7 @@
   # the device ("alice/myworkstation") can talk to it.
   local -r BINARYD_NAME="binaryd"
   shell_test::start_server "${VRUN}" --name=myworkstation/binaryd "${BINARYD_BIN}" --name="${BINARYD_NAME}" \
-    --root_dir="$(shell::tmp_dir)/binstore" --veyron.tcp.address=127.0.0.1:0 --http=127.0.0.1:0 \
+    --root_dir="${WORKDIR}/binstore" --veyron.tcp.address=127.0.0.1:0 --http=127.0.0.1:0 \
     || shell_test::fail "line ${LINENO} failed to start binaryd"
 
   # Upload a binary to the binary server.  The binary we upload is binaryd
@@ -185,8 +186,9 @@
 
   # Start an application server under the blessing "alice/myworkstation/applicationd" so that
   # the device ("alice/myworkstation") can talk to it.
+  mkdir -p "${WORKDIR}/appstore"
   shell_test::start_server "${VRUN}" --name=myworkstation/applicationd "${APPLICATIOND_BIN}" --name="${APPLICATIOND_NAME}" \
-    --store="$(shell::tmp_dir)" --veyron.tcp.address=127.0.0.1:0 \
+    --store="${WORKDIR}/appstore" --veyron.tcp.address=127.0.0.1:0 \
     || shell_test::fail "line ${LINENO} failed to start applicationd"
 
   # Upload an envelope for our test app.
diff --git a/tools/mounttable/doc.go b/tools/mounttable/doc.go
index 15c9ec0..3b89c09 100644
--- a/tools/mounttable/doc.go
+++ b/tools/mounttable/doc.go
@@ -36,9 +36,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
diff --git a/tools/namespace/doc.go b/tools/namespace/doc.go
index 7aee2a4..44bcaf5 100644
--- a/tools/namespace/doc.go
+++ b/tools/namespace/doc.go
@@ -42,9 +42,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
diff --git a/tools/naming/simulator/shell_functions.go b/tools/naming/simulator/shell_functions.go
index 552635b..5a8f899 100644
--- a/tools/naming/simulator/shell_functions.go
+++ b/tools/naming/simulator/shell_functions.go
@@ -43,11 +43,11 @@
 }
 
 func mountServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	if err := checkArgs(args[1:], -3, "<mount point> <server> <ttl> [M][R]"); err != nil {
+	if err := checkArgs(args, -3, "<mount point> <server> <ttl> [M][R]"); err != nil {
 		return err
 	}
 	var opts []naming.MountOpt
-	for _, arg := range args[4:] {
+	for _, arg := range args[3:] {
 		for _, c := range arg {
 			switch c {
 			case 'R':
@@ -57,7 +57,7 @@
 			}
 		}
 	}
-	mp, server, ttlstr := args[1], args[2], args[3]
+	mp, server, ttlstr := args[0], args[1], args[2]
 	ttl, err := time.ParseDuration(ttlstr)
 	if err != nil {
 		return fmt.Errorf("failed to parse time from %q", ttlstr)
@@ -71,7 +71,7 @@
 }
 
 func namespaceCache(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	if err := checkArgs(args[1:], 1, "on|off"); err != nil {
+	if err := checkArgs(args, 1, "on|off"); err != nil {
 		return err
 	}
 	disable := true
@@ -90,10 +90,10 @@
 type resolver func(ctx *context.T, name string, opts ...naming.ResolveOpt) (me *naming.MountEntry, err error)
 
 func resolve(fn resolver, stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	if err := checkArgs(args[1:], 1, "<name>"); err != nil {
+	if err := checkArgs(args, 1, "<name>"); err != nil {
 		return err
 	}
-	name := args[1]
+	name := args[0]
 	me, err := fn(ctx, name)
 	if err != nil {
 		fmt.Fprintf(stdout, "RN=0\n")
diff --git a/tools/profile/doc.go b/tools/profile/doc.go
index 2a79b38..e50d9cb 100644
--- a/tools/profile/doc.go
+++ b/tools/profile/doc.go
@@ -37,9 +37,19 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
diff --git a/tools/profile/main.go b/tools/profile/main.go
index e9b7573..65f7187 100644
--- a/tools/profile/main.go
+++ b/tools/profile/main.go
@@ -1,5 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VANADIUM_ROOT/tools/go/src/tools/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/servicerunner/main.go b/tools/servicerunner/main.go
index 3e0b345..0631399 100644
--- a/tools/servicerunner/main.go
+++ b/tools/servicerunner/main.go
@@ -55,19 +55,12 @@
 }
 
 func main() {
-	ctx, shutdown := veyron2.Init()
-
 	if modules.IsModulesProcess() {
-		// TODO(suharshs): This is a hack and we should find a better way to parse flags in the modules.
-		// This is needed because the modules commands call veyron2.Init and multiple runtimes cannot
-		// be initialized simultaneously.
-		// In addition the modules read their args from flag.Args() (all flags after "--") which means
-		// the flags must still be parsed before calling modules.Dispatch(). Thus moving veyron2.Init
-		// below this clause solves nothing.
-		shutdown()
 		panicOnError(modules.Dispatch())
 		return
 	}
+
+	ctx, shutdown := veyron2.Init()
 	defer shutdown()
 
 	vars := map[string]string{}
@@ -78,7 +71,7 @@
 	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 
-	h, err := sh.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0")
+	h, err := sh.Start(core.RootMTCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0")
 	panicOnError(err)
 	panicOnError(updateVars(h, vars, "MT_NAME"))
 
@@ -90,15 +83,15 @@
 
 	// NOTE(sadovsky): The proxyd binary requires --protocol and --address flags
 	// while the proxyd command instead uses ListenSpec flags.
-	h, err = sh.Start(core.ProxyServerCommand, nil, "--", "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "test/proxy")
+	h, err = sh.Start(core.ProxyServerCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "test/proxy")
 	panicOnError(err)
 	panicOnError(updateVars(h, vars, "PROXY_NAME"))
 
-	h, err = sh.Start(core.WSPRCommand, nil, "--", "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "--veyron.proxy=test/proxy", "--identd=test/identd")
+	h, err = sh.Start(core.WSPRCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "--veyron.proxy=test/proxy", "--identd=test/identd")
 	panicOnError(err)
 	panicOnError(updateVars(h, vars, "WSPR_ADDR"))
 
-	h, err = sh.Start(core.TestIdentitydCommand, nil, "--", "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "--veyron.proxy=test/proxy", "--host=localhost", "--httpaddr=localhost:0")
+	h, err = sh.Start(core.TestIdentitydCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "--veyron.proxy=test/proxy", "--host=localhost", "--httpaddr=localhost:0")
 	panicOnError(err)
 	panicOnError(updateVars(h, vars, "TEST_IDENTITYD_NAME", "TEST_IDENTITYD_HTTP_ADDR"))
 
diff --git a/tools/vrpc/doc.go b/tools/vrpc/doc.go
index f5ff56d..df0d470 100644
--- a/tools/vrpc/doc.go
+++ b/tools/vrpc/doc.go
@@ -36,6 +36,13 @@
    directory to use for storing security credentials
  -veyron.namespace.root=[/ns.dev.v.io:8101]
    local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
  -veyron.vtrace.collect_regexp=