tlog.app/go/loc@v0.6.2-0.20231112073106-b6382a0ac518/README.md (about)

     1  [![Documentation](https://pkg.go.dev/badge/tlog.app/go/loc)](https://pkg.go.dev/tlog.app/go/loc?tab=doc)
     2  [![Go workflow](https://github.com/tlog-dev/loc/actions/workflows/go.yml/badge.svg)](https://github.com/tlog-dev/loc/actions/workflows/go.yml)
     3  [![CircleCI](https://circleci.com/gh/tlog-dev/loc.svg?style=svg)](https://circleci.com/gh/tlog-dev/loc)
     4  [![codecov](https://codecov.io/gh/tlog-dev/loc/tags/latest/graph/badge.svg)](https://codecov.io/gh/tlog-dev/loc)
     5  [![Go Report Card](https://goreportcard.com/badge/tlog.app/go/loc)](https://goreportcard.com/report/tlog.app/go/loc)
     6  ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/tlog-dev/loc?sort=semver)
     7  
     8  # loc
     9  
    10  It's a fast, alloc-free and convinient version of `runtime.Caller`.
    11  
    12  Performance benefits are available when using the `nikandfor_loc_unsafe` build tag. This relies on the internal runtime implementation, which means that older versions of the package may not compile with future versions of Go. Without the tag, it is safe to use with any version of Go.
    13  
    14  It was born from [tlog](https://tlog.app/go/tlog).
    15  
    16  ## What is similar
    17  
    18  Caller
    19  
    20  ```go
    21  pc := loc.Caller(1)
    22  ok := pc != 0
    23  name, file, line := pc.NameFileLine()
    24  e := pc.FuncEntry()
    25  
    26  // is similar to
    27  
    28  pc, file, line, ok := runtime.Caller(1) 
    29  f := runtime.FuncForPC(pc)
    30  name := f.Name()
    31  e := f.Entry()
    32  ```
    33  
    34  Callers
    35  
    36  ```go
    37  pcs := loc.Callers(1, 3)
    38  // or
    39  var pcsbuf [3]loc.PC
    40  pcs := loc.CallersFill(1, pcsbuf[:])
    41  
    42  for _, pc := range pcs {
    43      name, file, file := pc.NameFileLine()
    44  }
    45  
    46  // is similar to
    47  var pcbuf [3]uintptr
    48  n := runtime.Callers(2, pcbuf[:])
    49  
    50  frames := runtime.CallersFrames(pcbuf[:n])
    51  for {
    52      frame, more := frames.Next()
    53      
    54      _, _, _ = frame.Function, frame.File, frame.Line
    55  
    56      if !more {
    57          break
    58      }
    59  }
    60  ```
    61  
    62  ## What is different
    63  
    64  ### Normalized path
    65  
    66  `loc` returns cropped filepath.
    67  ```
    68  github.com/nikandfor/loc/func_test.go
    69  
    70  # vs
    71  
    72  /home/nik/nikandfor/loc/github.com/nikandfor/loc/func_test.go
    73  ```
    74  
    75  ### Performance
    76  
    77  In `loc` the full cycle (get pc than name, file and line) takes 360=200+160 (200+0 when you repeat) ns whereas runtime takes 690 (640 without func name) + 2 allocs per each frame.
    78  
    79  It's up to 3.5x improve.
    80  
    81  ```
    82  BenchmarkLocationCaller-8              	 5844801	       201.8 ns/op	       0 B/op	       0 allocs/op
    83  BenchmarkLocationNameFileLine-8        	 7313388	       156.5 ns/op	       0 B/op	       0 allocs/op
    84  BenchmarkRuntimeCallerNameFileLine-8   	 1709940	       689.1 ns/op	     216 B/op	       2 allocs/op
    85  BenchmarkRuntimeCallerFileLine-8       	 1917613	       642.1 ns/op	     216 B/op	       2 allocs/op
    86  ```