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  // TODO(#56378): #cgo noescape runCWithNoEscape
    17  
    18  void runCWithNoEscape(void *p) {
    19  }
    20  void runCWithoutNoEscape(void *p) {
    21  }
    22  */
    23  import "C"
    24  
    25  import (
    26  	"fmt"
    27  	"runtime"
    28  	"runtime/debug"
    29  	"unsafe"
    30  )
    31  
    32  const num = 100
    33  
    34  func init() {
    35  	register("CgoNoEscape", CgoNoEscape)
    36  }
    37  
    38  //go:noinline
    39  func withNoEscape() {
    40  	var str string
    41  	C.runCWithNoEscape(unsafe.Pointer(&str))
    42  }
    43  
    44  //go:noinline
    45  func withoutNoEscape() {
    46  	var str string
    47  	C.runCWithoutNoEscape(unsafe.Pointer(&str))
    48  }
    49  
    50  func CgoNoEscape() {
    51  	// make GC stop to see the heap objects allocated
    52  	debug.SetGCPercent(-1)
    53  
    54  	var stats runtime.MemStats
    55  	runtime.ReadMemStats(&stats)
    56  	preHeapObjects := stats.HeapObjects
    57  
    58  	for i := 0; i < num; i++ {
    59  		withNoEscape()
    60  	}
    61  
    62  	runtime.ReadMemStats(&stats)
    63  	nowHeapObjects := stats.HeapObjects
    64  
    65  	if nowHeapObjects-preHeapObjects >= num {
    66  		fmt.Printf("too many heap objects allocated, pre: %v, now: %v\n", preHeapObjects, nowHeapObjects)
    67  	}
    68  
    69  	runtime.ReadMemStats(&stats)
    70  	preHeapObjects = stats.HeapObjects
    71  
    72  	for i := 0; i < num; i++ {
    73  		withoutNoEscape()
    74  	}
    75  
    76  	runtime.ReadMemStats(&stats)
    77  	nowHeapObjects = stats.HeapObjects
    78  
    79  	if nowHeapObjects-preHeapObjects < num {
    80  		fmt.Printf("too few heap objects allocated, pre: %v, now: %v\n", preHeapObjects, nowHeapObjects)
    81  	}
    82  
    83  	fmt.Println("OK")
    84  }
    85  

View as plain text