diff options
author | Fumitoshi Ukai <fumitoshi.ukai@gmail.com> | 2015-06-18 15:36:57 +0900 |
---|---|---|
committer | Fumitoshi Ukai <fumitoshi.ukai@gmail.com> | 2015-06-18 15:36:57 +0900 |
commit | b8acae94bc5b6494f51fe1acf32df5d72d412562 (patch) | |
tree | c0e114c693abdacc5690ec3adf8dd1161c8983d1 | |
parent | 7c9aa9f17d5f8f27aed62b5520b8fbc6be0103ac (diff) | |
download | kati-b8acae94bc5b6494f51fe1acf32df5d72d412562.tar.gz |
reduce runtime.convT2I -> runtime.newobject -> runtime.mallocgc
conversion from value to interface is more expensive than
conversion from pointer to interface.
package main
import "testing"
type I interface {
String() string
}
type val struct {
s string
}
func (v val) String() string { return v.s }
type ptr struct {
s string
}
func (p *ptr) String() string { return p.s }
func BenchmarkT2IForValue(b *testing.B) {
var intf I
for i := 0; i < b.N; i++ {
intf = val{"abc"}
}
_ = intf
}
func BenchmarkT2IForPtr(b *testing.B) {
var intf I
for i := 0; i < b.N; i++ {
intf = &ptr{"abc"}
}
_ = intf
}
% go test -bench . a_test.go
testing: warning: no tests to run
PASS
BenchmarkT2IForValue 20000000 90.9 ns/op
BenchmarkT2IForPtr 20000000 76.8 ns/op
ok command-line-arguments 3.539s
-rw-r--r-- | ast.go | 8 | ||||
-rw-r--r-- | dep.go | 2 | ||||
-rw-r--r-- | eval.go | 2 | ||||
-rw-r--r-- | expr.go | 22 | ||||
-rw-r--r-- | expr_test.go | 22 | ||||
-rw-r--r-- | func.go | 12 | ||||
-rw-r--r-- | main.go | 6 | ||||
-rw-r--r-- | serialize.go | 8 | ||||
-rw-r--r-- | var.go | 58 |
9 files changed, 70 insertions, 70 deletions
@@ -57,13 +57,13 @@ func (ast *AssignAST) evalRHS(ev *Evaluator, lhs string) Var { case ":=": var buf bytes.Buffer ast.rhs.Eval(&buf, ev) - return SimpleVar{value: buf.Bytes(), origin: origin} + return &SimpleVar{value: buf.Bytes(), origin: origin} case "=": - return RecursiveVar{expr: ast.rhs, origin: origin} + return &RecursiveVar{expr: ast.rhs, origin: origin} case "+=": prev := ev.LookupVarInCurrentScope(lhs) if !prev.IsDefined() { - return RecursiveVar{expr: ast.rhs, origin: origin} + return &RecursiveVar{expr: ast.rhs, origin: origin} } return prev.AppendVar(ev, ast.rhs) case "?=": @@ -71,7 +71,7 @@ func (ast *AssignAST) evalRHS(ev *Evaluator, lhs string) Var { if prev.IsDefined() { return prev } - return RecursiveVar{expr: ast.rhs, origin: origin} + return &RecursiveVar{expr: ast.rhs, origin: origin} default: panic(fmt.Sprintf("unknown assign op: %q", ast.op)) } @@ -260,7 +260,7 @@ func (db *DepBuilder) buildPlan(output string, neededBy string, tsvs Vars) (*Dep if vars != nil { for name, v := range vars { // TODO: Consider not updating db.vars. - tsv := v.(TargetSpecificVar) + tsv := v.(*TargetSpecificVar) restores = append(restores, db.vars.save(name)) restores = append(restores, tsvs.save(name)) switch tsv.op { @@ -127,7 +127,7 @@ func (ev *Evaluator) setTargetSpecificVar(assign *AssignAST, output string) { ev.currentScope = vars lhs, rhs := ev.evalAssignAST(assign) Logf("rule outputs:%q assign:%q=%q (flavor:%q)", output, lhs, rhs, rhs.Flavor()) - vars.Assign(lhs, TargetSpecificVar{v: rhs, op: assign.op}) + vars.Assign(lhs, &TargetSpecificVar{v: rhs, op: assign.op}) ev.currentScope = nil } @@ -26,7 +26,7 @@ import ( var ( errEndOfInput = errors.New("parse: unexpected end of input") - errNotLiteral = errors.New("valueNum: not literal") + errNotLiteral = errors.New("valueNum: not literal") bufFree = sync.Pool{ New: func() interface{} { return new(buffer) }, @@ -139,7 +139,7 @@ type varref struct { varname Value } -func (v varref) String() string { +func (v *varref) String() string { varname := v.varname.String() if len(varname) == 1 { return fmt.Sprintf("$%s", varname) @@ -147,7 +147,7 @@ func (v varref) String() string { return fmt.Sprintf("${%s}", varname) } -func (v varref) Eval(w io.Writer, ev *Evaluator) { +func (v *varref) Eval(w io.Writer, ev *Evaluator) { te := traceEvent.begin("var", v, traceEventMain) buf := newBuf() v.varname.Eval(buf, ev) @@ -157,13 +157,13 @@ func (v varref) Eval(w io.Writer, ev *Evaluator) { traceEvent.end(te) } -func (v varref) Serialize() SerializableVar { +func (v *varref) Serialize() SerializableVar { return SerializableVar{ Type: "varref", Children: []SerializableVar{v.varname.Serialize()}, } } -func (v varref) Dump(w io.Writer) { +func (v *varref) Dump(w io.Writer) { dumpByte(w, ValueTypeVarref) v.varname.Dump(w) } @@ -316,7 +316,7 @@ Loop: } if bytes.IndexByte(term, in[i+1]) >= 0 { expr = appendStr(expr, in[b:i], alloc) - expr = append(expr, varref{varname: literal("")}) + expr = append(expr, &varref{varname: literal("")}) i++ b = i break Loop @@ -388,7 +388,7 @@ func parseDollar(in []byte, alloc bool) (Value, int, error) { if in[1] >= '0' && in[1] <= '9' { return paramref(in[1] - '0'), 2, nil } - return varref{varname: str(in[1:2], alloc)}, 2, nil + return &varref{varname: str(in[1:2], alloc)}, 2, nil } term := []byte{paren, ':', ' '} var varname Expr @@ -410,7 +410,7 @@ Again: // ${n} return paramref(n), i + 1, nil } - return varref{varname: vname}, i + 1, nil + return &varref{varname: vname}, i + 1, nil case ' ': // ${e ...} switch token := e.(type) { @@ -424,7 +424,7 @@ Again: continue Again case ':': // ${varname:...} - colon := in[i:i+1] + colon := in[i : i+1] term = term[:2] term[1] = '=' // term={paren, '='}. e, n, err := parseExpr(in[i+1:], term, alloc) @@ -434,7 +434,7 @@ Again: i += 1 + n if in[i] == paren { varname = appendStr(varname, colon, alloc) - return varref{varname: varname}, i + 1, nil + return &varref{varname: varname}, i + 1, nil } // ${varname:xx=...} pat := e @@ -641,7 +641,7 @@ func matchExpr(expr, pat Expr) ([]Value, bool) { for i := range expr { if pat[i] == mv { switch expr[i].(type) { - case paramref, varref: + case paramref, *varref: matches = append(matches, expr[i]) continue } diff --git a/expr_test.go b/expr_test.go index dbf715a..9b776e0 100644 --- a/expr_test.go +++ b/expr_test.go @@ -47,11 +47,11 @@ func TestParseExpr(t *testing.T) { }, { in: "$foo", - val: Expr{varref{varname: literal("f")}, literal("oo")}, + val: Expr{&varref{varname: literal("f")}, literal("oo")}, }, { in: "$(foo)", - val: varref{varname: literal("foo")}, + val: &varref{varname: literal("foo")}, }, { in: "$(foo:.c=.o)", @@ -68,13 +68,13 @@ func TestParseExpr(t *testing.T) { fclosure: fclosure{ args: []Value{ literal("(subst"), - varref{ + &varref{ varname: literal("space"), }, - varref{ + &varref{ varname: literal(","), }, - varref{ + &varref{ varname: literal("foo"), }, }, @@ -89,15 +89,15 @@ func TestParseExpr(t *testing.T) { fclosure: fclosure{ args: []Value{ literal("(subst"), - varref{ + &varref{ varname: literal("space"), }, - varref{ + &varref{ varname: literal(""), }, Expr{ literal(","), - varref{ + &varref{ varname: literal("foo"), }, }, @@ -183,10 +183,10 @@ func TestParseExpr(t *testing.T) { fclosure: fclosure{ args: []Value{ literal("(and"), - varref{ + &varref{ varname: literal("TRUE"), }, - varref{ + &varref{ varname: literal("X"), }, }, @@ -245,7 +245,7 @@ func TestParseExpr(t *testing.T) { val: &funcEvalAssign{ lhs: "foo", op: ":=", - rhs: varref{ + rhs: &varref{ literal("bar"), }, }, @@ -809,7 +809,7 @@ func (f *funcCall) Eval(w io.Writer, ev *Evaluator) { for i, arg := range args { name := fmt.Sprintf("%d", i) restores = append(restores, ev.outVars.save(name)) - ev.outVars.Assign(name, SimpleVar{ + ev.outVars.Assign(name, &SimpleVar{ value: arg, origin: "automatic", // ?? }) @@ -985,22 +985,22 @@ func (f *funcEvalAssign) Eval(w io.Writer, ev *Evaluator) { } var vbuf bytes.Buffer expr.Eval(&vbuf, ev) - rvalue = SimpleVar{value: tmpval(vbuf.Bytes()), origin: "file"} + rvalue = &SimpleVar{value: tmpval(vbuf.Bytes()), origin: "file"} case "=": - rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"} + rvalue = &RecursiveVar{expr: tmpval(rhs), origin: "file"} case "+=": prev := ev.LookupVar(f.lhs) if prev.IsDefined() { rvalue = prev.Append(ev, string(rhs)) } else { - rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"} + rvalue = &RecursiveVar{expr: tmpval(rhs), origin: "file"} } case "?=": prev := ev.LookupVar(f.lhs) if prev.IsDefined() { return } - rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"} + rvalue = &RecursiveVar{expr: tmpval(rhs), origin: "file"} } Logf("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor()) ev.outVars.Assign(f.lhs, rvalue) @@ -1111,7 +1111,7 @@ func (f *funcForeach) Eval(w io.Writer, ev *Evaluator) { for ws.Scan() { word := ws.Bytes() ev.outVars.Assign(varname, - SimpleVar{ + &SimpleVar{ value: tmpval(word), origin: "automatic", }) @@ -216,19 +216,19 @@ func getDepGraph(clvars []string, targets []string) *DepGraph { if len(kv) < 2 { panic(fmt.Sprintf("A weird environ variable %q", kv)) } - vars.Assign(kv[0], RecursiveVar{ + vars.Assign(kv[0], &RecursiveVar{ expr: literal(kv[1]), origin: "environment", }) } - vars.Assign("MAKEFILE_LIST", SimpleVar{value: []byte{}, origin: "file"}) + vars.Assign("MAKEFILE_LIST", &SimpleVar{value: []byte{}, origin: "file"}) for _, v := range clvars { kv := strings.SplitN(v, "=", 2) Logf("cmdlinevar %q", kv) if len(kv) < 2 { panic(fmt.Sprintf("unexpected command line var %q", kv)) } - vars.Assign(kv[0], RecursiveVar{ + vars.Assign(kv[0], &RecursiveVar{ expr: literal(kv[1]), origin: "command line", }) diff --git a/serialize.go b/serialize.go index da8b0b5..4ee0b29 100644 --- a/serialize.go +++ b/serialize.go @@ -321,7 +321,7 @@ func DeserializeVar(sv SerializableVar) (r Value) { } return e case "varref": - return varref{varname: DeserializeSingleChild(sv)} + return &varref{varname: DeserializeSingleChild(sv)} case "paramref": v, err := strconv.Atoi(sv.V) if err != nil { @@ -353,18 +353,18 @@ func DeserializeVar(sv SerializableVar) (r Value) { return &funcNop{expr: sv.V} case "simple": - return SimpleVar{ + return &SimpleVar{ value: []byte(sv.V), origin: sv.Origin, } case "recursive": - return RecursiveVar{ + return &RecursiveVar{ expr: DeserializeSingleChild(sv), origin: sv.Origin, } case ":=", "=", "+=", "?=": - return TargetSpecificVar{ + return &TargetSpecificVar{ v: DeserializeSingleChild(sv).(Var), op: sv.Type, } @@ -33,45 +33,45 @@ type TargetSpecificVar struct { op string } -func (v TargetSpecificVar) Append(ev *Evaluator, s string) Var { - return TargetSpecificVar{ +func (v *TargetSpecificVar) Append(ev *Evaluator, s string) Var { + return &TargetSpecificVar{ v: v.v.Append(ev, s), op: v.op, } } -func (v TargetSpecificVar) AppendVar(ev *Evaluator, v2 Value) Var { - return TargetSpecificVar{ +func (v *TargetSpecificVar) AppendVar(ev *Evaluator, v2 Value) Var { + return &TargetSpecificVar{ v: v.v.AppendVar(ev, v2), op: v.op, } } -func (v TargetSpecificVar) Flavor() string { +func (v *TargetSpecificVar) Flavor() string { return v.v.Flavor() } -func (v TargetSpecificVar) Origin() string { +func (v *TargetSpecificVar) Origin() string { return v.v.Origin() } -func (v TargetSpecificVar) IsDefined() bool { +func (v *TargetSpecificVar) IsDefined() bool { return v.v.IsDefined() } -func (v TargetSpecificVar) String() string { +func (v *TargetSpecificVar) String() string { // TODO: If we add the info of |op| a test starts // failing. Shouldn't we use this only for debugging? return v.v.String() // return v.v.String() + " (op=" + v.op + ")" } -func (v TargetSpecificVar) Eval(w io.Writer, ev *Evaluator) { +func (v *TargetSpecificVar) Eval(w io.Writer, ev *Evaluator) { v.v.Eval(w, ev) } -func (v TargetSpecificVar) Serialize() SerializableVar { +func (v *TargetSpecificVar) Serialize() SerializableVar { return SerializableVar{ Type: v.op, Children: []SerializableVar{v.v.Serialize()}, } } -func (v TargetSpecificVar) Dump(w io.Writer) { +func (v *TargetSpecificVar) Dump(w io.Writer) { dumpByte(w, ValueTypeTSV) dumpString(w, v.op) v.v.Dump(w) @@ -83,28 +83,28 @@ type SimpleVar struct { origin string } -func (v SimpleVar) Flavor() string { return "simple" } -func (v SimpleVar) Origin() string { return v.origin } -func (v SimpleVar) IsDefined() bool { return true } +func (v *SimpleVar) Flavor() string { return "simple" } +func (v *SimpleVar) Origin() string { return v.origin } +func (v *SimpleVar) IsDefined() bool { return true } -func (v SimpleVar) String() string { return string(v.value) } -func (v SimpleVar) Eval(w io.Writer, ev *Evaluator) { +func (v *SimpleVar) String() string { return string(v.value) } +func (v *SimpleVar) Eval(w io.Writer, ev *Evaluator) { w.Write(v.value) } -func (v SimpleVar) Serialize() SerializableVar { +func (v *SimpleVar) Serialize() SerializableVar { return SerializableVar{ Type: "simple", V: string(v.value), Origin: v.origin, } } -func (v SimpleVar) Dump(w io.Writer) { +func (v *SimpleVar) Dump(w io.Writer) { dumpByte(w, ValueTypeSimple) dumpBytes(w, v.value) dumpString(w, v.origin) } -func (v SimpleVar) Append(ev *Evaluator, s string) Var { +func (v *SimpleVar) Append(ev *Evaluator, s string) Var { val, _, err := parseExpr([]byte(s), nil, false) if err != nil { panic(err) @@ -116,7 +116,7 @@ func (v SimpleVar) Append(ev *Evaluator, s string) Var { return v } -func (v SimpleVar) AppendVar(ev *Evaluator, val Value) Var { +func (v *SimpleVar) AppendVar(ev *Evaluator, val Value) Var { buf := bytes.NewBuffer(v.value) buf.WriteByte(' ') val.Eval(buf, ev) @@ -129,28 +129,28 @@ type RecursiveVar struct { origin string } -func (v RecursiveVar) Flavor() string { return "recursive" } -func (v RecursiveVar) Origin() string { return v.origin } -func (v RecursiveVar) IsDefined() bool { return true } +func (v *RecursiveVar) Flavor() string { return "recursive" } +func (v *RecursiveVar) Origin() string { return v.origin } +func (v *RecursiveVar) IsDefined() bool { return true } -func (v RecursiveVar) String() string { return v.expr.String() } -func (v RecursiveVar) Eval(w io.Writer, ev *Evaluator) { +func (v *RecursiveVar) String() string { return v.expr.String() } +func (v *RecursiveVar) Eval(w io.Writer, ev *Evaluator) { v.expr.Eval(w, ev) } -func (v RecursiveVar) Serialize() SerializableVar { +func (v *RecursiveVar) Serialize() SerializableVar { return SerializableVar{ Type: "recursive", Children: []SerializableVar{v.expr.Serialize()}, Origin: v.origin, } } -func (v RecursiveVar) Dump(w io.Writer) { +func (v *RecursiveVar) Dump(w io.Writer) { dumpByte(w, ValueTypeRecursive) v.expr.Dump(w) dumpString(w, v.origin) } -func (v RecursiveVar) Append(_ *Evaluator, s string) Var { +func (v *RecursiveVar) Append(_ *Evaluator, s string) Var { var expr Expr if e, ok := v.expr.(Expr); ok { expr = append(e, literal(" ")) @@ -170,7 +170,7 @@ func (v RecursiveVar) Append(_ *Evaluator, s string) Var { return v } -func (v RecursiveVar) AppendVar(ev *Evaluator, val Value) Var { +func (v *RecursiveVar) AppendVar(ev *Evaluator, val Value) Var { var buf bytes.Buffer buf.WriteString(v.expr.String()) buf.WriteByte(' ') |