github.com/nikandfor/loc@v0.5.1/README.md (about)

     1  [![Documentation](https://pkg.go.dev/badge/github.com/nikandfor/loc)](https://pkg.go.dev/github.com/nikandfor/loc?tab=doc)
     2  [![Go workflow](https://github.com/nikandfor/json/actions/workflows/go.yml/badge.svg)](https://github.com/nikandfor/json/actions/workflows/go.yml)
     3  [![CircleCI](https://circleci.com/gh/nikandfor/loc.svg?style=svg)](https://circleci.com/gh/nikandfor/loc)
     4  [![codecov](https://codecov.io/gh/nikandfor/loc/tags/latest/graph/badge.svg)](https://codecov.io/gh/nikandfor/loc)
     5  [![GolangCI](https://golangci.com/badges/github.com/nikandfor/loc.svg)](https://golangci.com/r/github.com/nikandfor/loc)
     6  [![Go Report Card](https://goreportcard.com/badge/github.com/nikandfor/loc)](https://goreportcard.com/report/github.com/nikandfor/loc)
     7  ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/nikandfor/loc?sort=semver)
     8  
     9  # loc
    10  
    11  It's a fast, alloc-free and convinient version of `runtime.Caller`.
    12  
    13  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.
    14  
    15  It was born from [tlog](https://github.com/tlog-dev/tlog).
    16  
    17  ## What is similar
    18  
    19  Caller
    20  
    21  ```go
    22  pc := loc.Caller(1)
    23  ok := pc != 0
    24  name, file, line := pc.NameFileLine()
    25  e := pc.FuncEntry()
    26  
    27  // is similar to
    28  
    29  pc, file, line, ok := runtime.Caller(1) 
    30  f := runtime.FuncForPC(pc)
    31  name := f.Name()
    32  e := f.Entry()
    33  ```
    34  
    35  Callers
    36  
    37  ```go
    38  pcs := loc.Callers(1, 3)
    39  // or
    40  var pcsbuf [3]loc.PC
    41  pcs := loc.CallersFill(1, pcsbuf[:])
    42  
    43  for _, pc := range pcs {
    44      name, file, file := pc.NameFileLine()
    45  }
    46  
    47  // is similar to
    48  var pcbuf [3]uintptr
    49  n := runtime.Callers(2, pcbuf[:])
    50  
    51  frames := runtime.CallersFrames(pcbuf[:n])
    52  for {
    53      frame, more := frames.Next()
    54      
    55      _, _, _ = frame.Function, frame.File, frame.Line
    56  
    57      if !more {
    58          break
    59      }
    60  }
    61  ```
    62  
    63  ## What is different
    64  
    65  ### Normalized path
    66  
    67  `loc` returns cropped filepath.
    68  ```
    69  github.com/nikandfor/loc/func_test.go
    70  
    71  # vs
    72  
    73  /home/nik/nikandfor/loc/github.com/nikandfor/loc/func_test.go
    74  ```
    75  
    76  ### Performance
    77  
    78  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.
    79  
    80  It's up to 3.5x improve.
    81  
    82  ```
    83  BenchmarkLocationCaller-8              	 5844801	       201.8 ns/op	       0 B/op	       0 allocs/op
    84  BenchmarkLocationNameFileLine-8        	 7313388	       156.5 ns/op	       0 B/op	       0 allocs/op
    85  BenchmarkRuntimeCallerNameFileLine-8   	 1709940	       689.1 ns/op	     216 B/op	       2 allocs/op
    86  BenchmarkRuntimeCallerFileLine-8       	 1917613	       642.1 ns/op	     216 B/op	       2 allocs/op
    87  ```