Skip to content

Commit 3067214

Browse files
committed
Optimize goroutine switching performance.
Avoid use of the `{...context}` syntax, which appears to have a significant performance penalty when used in a tight loop. In addition, apply a few further size and performance optimizations: skip unpacking $f from the context and instead fully construct it in the function epilogue.
1 parent cea2ae1 commit 3067214

File tree

3 files changed

+13
-19
lines changed

3 files changed

+13
-19
lines changed

compiler/package.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -819,21 +819,23 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
819819
localVarDefs := "" // Function-local var declaration at the top.
820820

821821
if len(c.Blocking) != 0 {
822+
if funcRef == "" {
823+
funcRef = "$b"
824+
functionName = " $b"
825+
}
826+
822827
localVars := append([]string{}, c.localVars...)
828+
// There are several special variables involved in handling blocking functions:
823829
// $r is sometimes used as a temporary variable to store blocking call result.
824830
// $c indicates that a function is being resumed after a blocking call when set to true.
825831
// $f is an object used to save and restore function context for blocking calls.
826-
localVars = append(localVars, "$r", "$c", "$f")
832+
localVars = append(localVars, "$r")
827833
// If a blocking function is being resumed, initialize local variables from the saved context.
828-
localVarDefs = fmt.Sprintf("var {%s} = $restore(this, {%s});\n", strings.Join(localVars, ", "), strings.Join(params, ", "))
834+
localVarDefs = fmt.Sprintf("var {%s, $c} = $restore(this, {%s});\n", strings.Join(localVars, ", "), strings.Join(params, ", "))
829835
// If the function gets blocked, save local variables for future.
830-
saveContext := fmt.Sprintf("$f = {...$f, $r, %s};", strings.Join(c.localVars, ", "))
836+
saveContext := fmt.Sprintf("var $f = {$blk: "+funcRef+", $c: true, $r, %s};", strings.Join(c.localVars, ", "))
831837

832-
if funcRef == "" {
833-
funcRef = "$b"
834-
functionName = " $b"
835-
}
836-
suffix = " if ($f === undefined) { $f = { $blk: " + funcRef + " }; } " + saveContext + "return $f;" + suffix
838+
suffix = " " + saveContext + "return $f;" + suffix
837839
} else if len(c.localVars) > 0 {
838840
// Non-blocking functions simply declare local variables with no need for restore support.
839841
localVarDefs = fmt.Sprintf("var %s;\n", strings.Join(c.localVars, ", "))

compiler/prelude/goroutines.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -225,17 +225,9 @@ var $block = function() {
225225
226226
var $restore = function(context, params) {
227227
if (context !== undefined && context.$blk !== undefined) {
228-
return {
229-
$f: context,
230-
$c: true,
231-
...context,
232-
};
233-
} else {
234-
return {
235-
$c: false,
236-
...params,
237-
};
228+
return context;
238229
}
230+
return params;
239231
}
240232
241233
var $send = function(chan, value) {

0 commit comments

Comments
 (0)