Source file src/runtime/testdata/testprogcgo/cgonoescape.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  // #cgo noescape annotations for a C function means its arguments won't escape to heap.
     8  
     9  // We assume that there won't be 100 new allocated heap objects in other places,
    10  // i.e. runtime.ReadMemStats or other runtime background works.
    11  // So, the tests are:
    12  // 1. at least 100 new allocated heap objects after invoking withoutNoEscape 100 times.
    13  // 2. less than 100 new allocated heap objects after invoking withoutNoEscape 100 times.
    14  
    15  /*
    16  #cgo noescape runCWithNoEscape
    17  #cgo nocallback runCWithNoEscape
    18  
    19  void runCWithNoEscape(void *p) {
    20  }
    21  void runCWithoutNoEscape(void *p) {
    22  }
    23  */
    24  import "C"
    25  
    26  import (
    27  	"fmt"
    28  	"runtime"
    29  	"runtime/debug"
    30  	"unsafe"
    31  )
    32  
    33  const num = 100
    34  
    35  func init() {
    36  	register("CgoNoEscape", CgoNoEscape)
    37  }
    38  
    39  //go:noinline
    40  func withNoEscape() {
    41  	var str string
    42  	C.runCWithNoEscape(unsafe.Pointer(&str))
    43  }
    44  
    45  //go:noinline
    46  func withoutNoEscape() {
    47  	var str string
    48  	C.runCWithoutNoEscape(unsafe.Pointer(&str))
    49  }
    50  
    51  func CgoNoEscape() {
    52  	// make GC stop to see the heap objects allocated
    53  	debug.SetGCPercent(-1)
    54  
    55  	var stats runtime.MemStats
    56  	runtime.ReadMemStats(&stats)
    57  	preHeapObjects := stats.HeapObjects
    58  
    59  	for i := 0; i < num; i++ {
    60  		withNoEscape()
    61  	}
    62  
    63  	runtime.ReadMemStats(&stats)
    64  	nowHeapObjects := stats.HeapObjects
    65  
    66  	if nowHeapObjects-preHeapObjects >= num {
    67  		fmt.Printf("too many heap objects allocated, pre: %v, now: %v\n", preHeapObjects, nowHeapObjects)
    68  	}
    69  
    70  	runtime.ReadMemStats(&stats)
    71  	preHeapObjects = stats.HeapObjects
    72  
    73  	for i := 0; i < num; i++ {
    74  		withoutNoEscape()
    75  	}
    76  
    77  	runtime.ReadMemStats(&stats)
    78  	nowHeapObjects = stats.HeapObjects
    79  
    80  	if nowHeapObjects-preHeapObjects < num {
    81  		fmt.Printf("too few heap objects allocated, pre: %v, now: %v\n", preHeapObjects, nowHeapObjects)
    82  	}
    83  
    84  	fmt.Println("OK")
    85  }
    86  

View as plain text