Skip to content

Commit

Permalink
Reduce Call* for 24 builtins to just CallBuiltin and 3 special cases
Browse files Browse the repository at this point in the history
This noticeably speeds up most operations due to the reduced number
of opcodes (hmmm, maybe we should go further with this). Results below:

Before (-12.5% geo mean against master):

name                    old time/op  new time/op  delta
BinaryOperators-8        517ns ± 1%   568ns ± 0%   +9.92%  (p=0.008 n=5+5)
BuiltinSplitSpace-8     35.0µs ± 0%  35.6µs ± 0%   +1.68%  (p=0.008 n=5+5)
NativeFunc-8            10.8µs ± 1%  10.9µs ± 0%   +1.20%  (p=0.008 n=5+5)
BuiltinSub-8            13.5µs ± 0%  13.7µs ± 0%   +1.00%  (p=0.008 n=5+5)
BuiltinGsubAmpersand-8  16.1µs ± 1%  16.2µs ± 0%   +0.81%  (p=0.008 n=5+5)
BuiltinSplitRegex-8     86.7µs ± 1%  87.4µs ± 0%     ~     (p=0.151 n=5+5)
BuiltinSubAmpersand-8   13.5µs ± 1%  13.6µs ± 0%     ~     (p=0.095 n=5+5)
BuiltinGsub-8           16.1µs ± 1%  16.2µs ± 0%     ~     (p=0.151 n=5+5)
FuncCall-8              2.84µs ± 1%  2.83µs ± 0%     ~     (p=0.206 n=5+5)
SimplePattern-8          133ns ± 5%   135ns ± 1%     ~     (p=0.151 n=5+5)
ConcatSmall-8            748ns ± 2%   738ns ± 0%     ~     (p=0.151 n=5+5)
ConcatLarge-8           8.28ms ± 7%  8.03ms ± 2%     ~     (p=0.310 n=5+5)
RecursiveFunc-8         15.8µs ± 0%  15.7µs ± 0%   -0.26%  (p=0.008 n=5+5)
BuiltinIndex-8          4.62µs ± 1%  4.53µs ± 0%   -1.81%  (p=0.008 n=5+5)
SetField-8               943ns ± 2%   925ns ± 0%   -1.95%  (p=0.032 n=5+5)
ArrayOperations-8        684ns ± 2%   669ns ± 0%   -2.17%  (p=0.008 n=5+5)
BuiltinSprintf-8        9.72µs ± 0%  9.39µs ± 0%   -3.41%  (p=0.008 n=5+5)
BuiltinMatch-8          3.27µs ± 1%  3.14µs ± 3%   -4.08%  (p=0.008 n=5+5)
GetField-8               460ns ± 3%   441ns ± 0%   -4.32%  (p=0.008 n=5+5)
BuiltinSubstr-8         3.89µs ± 1%  3.71µs ± 0%   -4.61%  (p=0.008 n=5+5)
BuiltinLength-8         4.04µs ± 1%  3.81µs ± 0%   -5.72%  (p=0.008 n=5+5)
RegexMatch-8            1.25µs ± 3%  1.16µs ± 2%   -6.81%  (p=0.008 n=5+5)
ForInLoop-8             2.02µs ± 4%  1.82µs ± 3%   -9.73%  (p=0.008 n=5+5)
Comparisons-8            443ns ± 4%   398ns ± 0%  -10.10%  (p=0.016 n=5+4)
CondExpr-8               214ns ±11%   168ns ± 0%  -21.18%  (p=0.008 n=5+5)
SimpleBuiltins-8        1.02µs ± 0%  0.76µs ± 1%  -25.31%  (p=0.008 n=5+5)
AugAssign-8             1.48µs ± 1%  1.06µs ± 0%  -28.45%  (p=0.000 n=5+4)
IfStatement-8            240ns ± 2%   170ns ± 0%  -29.47%  (p=0.016 n=5+4)
Assign-8                 462ns ± 0%   304ns ± 0%  -34.24%  (p=0.008 n=5+5)
GlobalVars-8             484ns ± 1%   316ns ± 1%  -34.72%  (p=0.008 n=5+5)
ForLoop-8               4.59µs ± 5%  2.85µs ± 0%  -37.97%  (p=0.008 n=5+5)
LocalVars-8              514ns ± 0%   313ns ± 0%  -39.11%  (p=0.008 n=5+5)
IncrDecr-8               455ns ± 1%   180ns ± 1%  -60.55%  (p=0.008 n=5+5)
[Geo mean]              2.77µs       2.43µs       -12.50%

After (-18.15% geo mean against master):

name                    old time/op  new time/op  delta
BuiltinSplitSpace-8     35.0µs ± 0%  35.7µs ± 0%   +1.80%  (p=0.008 n=5+5)
BuiltinGsubAmpersand-8  16.1µs ± 1%  16.2µs ± 0%   +0.74%  (p=0.008 n=5+5)
BuiltinSub-8            13.5µs ± 0%  13.6µs ± 0%   +0.65%  (p=0.008 n=5+5)
BuiltinSplitRegex-8     86.7µs ± 1%  88.0µs ± 0%     ~     (p=0.056 n=5+5)
BuiltinSubAmpersand-8   13.5µs ± 1%  13.6µs ± 0%     ~     (p=0.548 n=5+5)
BuiltinGsub-8           16.1µs ± 1%  16.3µs ± 0%     ~     (p=0.095 n=5+5)
SimplePattern-8          133ns ± 5%   134ns ± 2%     ~     (p=0.151 n=5+5)
ConcatLarge-8           8.28ms ± 7%  8.29ms ± 1%     ~     (p=0.690 n=5+5)
NativeFunc-8            10.8µs ± 1%  10.7µs ± 0%   -1.07%  (p=0.008 n=5+5)
BuiltinIndex-8          4.62µs ± 1%  4.50µs ± 0%   -2.63%  (p=0.008 n=5+5)
FuncCall-8              2.84µs ± 1%  2.72µs ± 0%   -4.11%  (p=0.008 n=5+5)
RecursiveFunc-8         15.8µs ± 0%  15.1µs ± 0%   -4.29%  (p=0.008 n=5+5)
BuiltinSprintf-8        9.72µs ± 0%  9.26µs ± 0%   -4.72%  (p=0.008 n=5+5)
BuiltinLength-8         4.04µs ± 1%  3.83µs ± 0%   -5.26%  (p=0.008 n=5+5)
BuiltinMatch-8          3.27µs ± 1%  3.06µs ± 0%   -6.56%  (p=0.008 n=5+5)
GetField-8               460ns ± 3%   430ns ± 1%   -6.71%  (p=0.008 n=5+5)
ConcatSmall-8            748ns ± 2%   688ns ± 0%   -8.02%  (p=0.008 n=5+5)
BuiltinSubstr-8         3.89µs ± 1%  3.57µs ± 0%   -8.14%  (p=0.008 n=5+5)
RegexMatch-8            1.25µs ± 3%  1.10µs ± 2%  -12.27%  (p=0.008 n=5+5)
ForInLoop-8             2.02µs ± 4%  1.77µs ± 4%  -12.33%  (p=0.008 n=5+5)
SetField-8               943ns ± 2%   813ns ± 0%  -13.83%  (p=0.008 n=5+5)
ArrayOperations-8        684ns ± 2%   566ns ± 0%  -17.18%  (p=0.008 n=5+5)
BinaryOperators-8        517ns ± 1%   419ns ± 0%  -18.89%  (p=0.008 n=5+5)
SimpleBuiltins-8        1.02µs ± 0%  0.75µs ± 0%  -26.09%  (p=0.008 n=5+5)
Comparisons-8            443ns ± 4%   315ns ± 1%  -28.82%  (p=0.008 n=5+5)
CondExpr-8               214ns ±11%   151ns ± 1%  -29.21%  (p=0.008 n=5+5)
AugAssign-8             1.48µs ± 1%  0.98µs ± 0%  -33.91%  (p=0.008 n=5+5)
IfStatement-8            240ns ± 2%   151ns ± 0%  -37.33%  (p=0.008 n=5+5)
LocalVars-8              514ns ± 0%   294ns ± 0%  -42.88%  (p=0.008 n=5+5)
Assign-8                 462ns ± 0%   261ns ± 0%  -43.54%  (p=0.008 n=5+5)
GlobalVars-8             484ns ± 1%   270ns ± 2%  -44.18%  (p=0.008 n=5+5)
ForLoop-8               4.59µs ± 5%  2.43µs ± 1%  -46.94%  (p=0.008 n=5+5)
IncrDecr-8               455ns ± 1%   149ns ± 0%  -67.32%  (p=0.016 n=5+4)
[Geo mean]              2.77µs       2.27µs       -18.15%
  • Loading branch information
benhoyt committed Jan 23, 2022
1 parent b985deb commit 71e2560
Show file tree
Hide file tree
Showing 5 changed files with 455 additions and 413 deletions.
50 changes: 25 additions & 25 deletions internal/compiler/compiler.go
Expand Up @@ -716,9 +716,9 @@ func (c *compiler) expr(expr ast.Expr) {
}
return
case lexer.F_SUB, lexer.F_GSUB:
op := CallSub
op := BuiltinSub
if e.Func == lexer.F_GSUB {
op = CallGsub
op = BuiltinGsub
}
var target ast.Expr = &ast.FieldExpr{&ast.NumExpr{0}} // default value and target is $0
if len(e.Args) == 3 {
Expand All @@ -727,7 +727,7 @@ func (c *compiler) expr(expr ast.Expr) {
c.expr(e.Args[0])
c.expr(e.Args[1])
c.expr(target)
c.add(op)
c.add(CallBuiltin, Opcode(op))
c.assign(target)
return
}
Expand All @@ -737,59 +737,59 @@ func (c *compiler) expr(expr ast.Expr) {
}
switch e.Func {
case lexer.F_ATAN2:
c.add(CallAtan2)
c.add(CallBuiltin, Opcode(BuiltinAtan2))
case lexer.F_CLOSE:
c.add(CallClose)
c.add(CallBuiltin, Opcode(BuiltinClose))
case lexer.F_COS:
c.add(CallCos)
c.add(CallBuiltin, Opcode(BuiltinCos))
case lexer.F_EXP:
c.add(CallExp)
c.add(CallBuiltin, Opcode(BuiltinExp))
case lexer.F_FFLUSH:
if len(e.Args) > 0 {
c.add(CallFflush)
c.add(CallBuiltin, Opcode(BuiltinFflush))
} else {
c.add(CallFflushAll)
c.add(CallBuiltin, Opcode(BuiltinFflushAll))
}
case lexer.F_INDEX:
c.add(CallIndex)
c.add(CallBuiltin, Opcode(BuiltinIndex))
case lexer.F_INT:
c.add(CallInt)
c.add(CallBuiltin, Opcode(BuiltinInt))
case lexer.F_LENGTH:
if len(e.Args) > 0 {
c.add(CallLengthArg)
c.add(CallBuiltin, Opcode(BuiltinLengthArg))
} else {
c.add(CallLength)
c.add(CallBuiltin, Opcode(BuiltinLength))
}
case lexer.F_LOG:
c.add(CallLog)
c.add(CallBuiltin, Opcode(BuiltinLog))
case lexer.F_MATCH:
c.add(CallMatch)
c.add(CallBuiltin, Opcode(BuiltinMatch))
case lexer.F_RAND:
c.add(CallRand)
c.add(CallBuiltin, Opcode(BuiltinRand))
case lexer.F_SIN:
c.add(CallSin)
c.add(CallBuiltin, Opcode(BuiltinSin))
case lexer.F_SPRINTF:
c.add(CallSprintf, opcodeInt(len(e.Args)))
case lexer.F_SQRT:
c.add(CallSqrt)
c.add(CallBuiltin, Opcode(BuiltinSqrt))
case lexer.F_SRAND:
if len(e.Args) > 0 {
c.add(CallSrandSeed)
c.add(CallBuiltin, Opcode(BuiltinSrandSeed))
} else {
c.add(CallSrand)
c.add(CallBuiltin, Opcode(BuiltinSrand))
}
case lexer.F_SUBSTR:
if len(e.Args) > 2 {
c.add(CallSubstrLength)
c.add(CallBuiltin, Opcode(BuiltinSubstrLength))
} else {
c.add(CallSubstr)
c.add(CallBuiltin, Opcode(BuiltinSubstr))
}
case lexer.F_SYSTEM:
c.add(CallSystem)
c.add(CallBuiltin, Opcode(BuiltinSystem))
case lexer.F_TOLOWER:
c.add(CallTolower)
c.add(CallBuiltin, Opcode(BuiltinTolower))
case lexer.F_TOUPPER:
c.add(CallToupper)
c.add(CallBuiltin, Opcode(BuiltinToupper))
default:
panic(fmt.Sprintf("unexpected function: %s", e.Func))
}
Expand Down
4 changes: 4 additions & 0 deletions internal/compiler/disassembler.go
Expand Up @@ -315,6 +315,10 @@ func (d *disassembler) disassemble(prefix string) error {
offset := d.fetch()
d.writeOpf("ForIn %s %s 0x%04x", d.varName(varScope, varIndex), d.arrayName(arrayScope, arrayIndex), d.ip+int(offset))

case CallBuiltin:
builtinOp := BuiltinOp(d.fetch())
d.writeOpf("CallBuiltin %s", builtinOp)

case CallSplit:
arrayScope := ast.VarScope(d.fetch())
arrayIndex := int(d.fetch())
Expand Down
105 changes: 61 additions & 44 deletions internal/compiler/opcode_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 38 additions & 31 deletions internal/compiler/opcodes.go
@@ -1,6 +1,6 @@
package compiler

//go:generate go run golang.org/x/tools/cmd/stringer@v0.1.8 -type=Opcode,AugOp
//go:generate go run golang.org/x/tools/cmd/stringer@v0.1.8 -type=Opcode,AugOp,BuiltinOp

// Opcode represents a single virtual machine instruction (or argument). The
// comments beside each opcode show any arguments that instruction consumes.
Expand Down Expand Up @@ -52,12 +52,12 @@ const (
IncrArrayLocal // amount arrayIndex

// Augmented assignment (also used for pre-increment and pre-decrement)
AugAssignField // operation
AugAssignGlobal // operation index
AugAssignLocal // operation index
AugAssignSpecial // operation index
AugAssignArrayGlobal // operation arrayIndex
AugAssignArrayLocal // operation arrayIndex
AugAssignField // augOp
AugAssignGlobal // augOp index
AugAssignLocal // augOp index
AugAssignSpecial // augOp index
AugAssignArrayGlobal // augOp arrayIndex
AugAssignArrayLocal // augOp arrayIndex

// Stand-alone regex expression /foo/
Regex // regexIndex
Expand Down Expand Up @@ -104,33 +104,10 @@ const (
BreakForIn

// Builtin functions
CallAtan2
CallClose
CallCos
CallExp
CallFflush
CallFflushAll
CallGsub
CallIndex
CallInt
CallLength
CallLengthArg
CallLog
CallMatch
CallRand
CallSin
CallBuiltin // builtinOp
CallSplit // arrayScope arrayIndex
CallSplitSep // arrayScope arrayIndex
CallSprintf // numArgs
CallSqrt
CallSrand
CallSrandSeed
CallSub
CallSubstr
CallSubstrLength
CallSystem
CallTolower
CallToupper

// User and native functions
CallUser // funcIndex numArrayArgs [arrayScope1 arrayIndex1 ...]
Expand Down Expand Up @@ -163,3 +140,33 @@ const (
AugOpPow
AugOpMod
)

// BuiltinOp represents a builtin function call.
type BuiltinOp int32

const (
BuiltinAtan2 BuiltinOp = iota
BuiltinClose
BuiltinCos
BuiltinExp
BuiltinFflush
BuiltinFflushAll
BuiltinGsub
BuiltinIndex
BuiltinInt
BuiltinLength
BuiltinLengthArg
BuiltinLog
BuiltinMatch
BuiltinRand
BuiltinSin
BuiltinSqrt
BuiltinSrand
BuiltinSrandSeed
BuiltinSub
BuiltinSubstr
BuiltinSubstrLength
BuiltinSystem
BuiltinTolower
BuiltinToupper
)

0 comments on commit 71e2560

Please sign in to comment.