github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/collection/skipmap/readme.md (about)

     1  <p align="center">
     2    <img src="https://raw.githubusercontent.com/zhangyunhao116/public-data/master/skipmap-logo.png"/>
     3  </p>
     4  
     5  ## Introduction
     6  
     7  skipmap is a high-performance concurrent map based on skip list. In typical pattern(one million operations, 90%LOAD 9%STORE 1%DELETE), the skipmap up to 3x ~ 10x faster than the built-in sync.Map.
     8  
     9  The main idea behind the skipmap is [A Simple Optimistic Skiplist Algorithm](<https://people.csail.mit.edu/shanir/publications/LazySkipList.pdf>).
    10  
    11  Different from the sync.Map, the items in the skipmap are always sorted, and the `Load` and `Range` operations are wait-free (A goroutine is guaranteed to complete a operation as long as it keeps taking steps, regardless of the activity of other goroutines).
    12  
    13  
    14  
    15  ## Features
    16  
    17  - Concurrent safe API with high-performance.
    18  - Wait-free Load and Range operations.
    19  - Sorted items.
    20  
    21  
    22  
    23  ## When should you use skipmap
    24  
    25  In these situations, `skipmap` is better
    26  
    27  - **Sorted elements is needed**.
    28  - **Concurrent calls multiple operations**. such as use both `Load` and `Store` at the same time.
    29  
    30  In these situations, `sync.Map` is better
    31  
    32  - Only one goroutine access the map for most of the time, such as insert a batch of elements and then use only `Load` (use built-in map is even better).
    33  
    34  
    35  
    36  ## QuickStart
    37  
    38  ```go
    39  package main
    40  
    41  import (
    42  	"fmt"
    43  
    44  	"github.com/bytedance/gopkg/collection/skipmap"
    45  )
    46  
    47  func main() {
    48  	l := skipmap.NewInt()
    49  
    50  	for _, v := range []int{10, 12, 15} {
    51  		l.Store(v, v+100)
    52  	}
    53  
    54  	v, ok := l.Load(10)
    55  	if ok {
    56  		fmt.Println("skipmap load 10 with value ", v)
    57  	}
    58  
    59  	l.Range(func(key int, value interface{}) bool {
    60  		fmt.Println("skipmap range found ", key, value)
    61  		return true
    62  	})
    63  
    64  	l.Delete(15)
    65  	fmt.Printf("skipmap contains %d items\r\n", l.Len())
    66  }
    67  
    68  ```
    69  
    70  
    71  
    72  ## Benchmark
    73  
    74  Go version: go1.16.2 linux/amd64
    75  
    76  CPU: AMD 3700x(8C16T), running at 3.6GHz
    77  
    78  OS: ubuntu 18.04
    79  
    80  MEMORY: 16G x 2 (3200MHz)
    81  
    82  ![benchmark](https://raw.githubusercontent.com/zhangyunhao116/public-data/master/skipmap-benchmark.png)
    83  
    84  ```shell
    85  $ go test -run=NOTEST -bench=. -benchtime=100000x -benchmem -count=20 -timeout=60m  > x.txt
    86  $ benchstat x.txt
    87  ```
    88  
    89  ```
    90  name                                            time/op
    91  Int64/Store/skipmap-16                           158ns ±12%
    92  Int64/Store/sync.Map-16                          700ns ± 4%
    93  Int64/Load50Hits/skipmap-16                     10.1ns ±14%
    94  Int64/Load50Hits/sync.Map-16                    14.8ns ±23%
    95  Int64/30Store70Load/skipmap-16                  50.6ns ±20%
    96  Int64/30Store70Load/sync.Map-16                  592ns ± 7%
    97  Int64/1Delete9Store90Load/skipmap-16            27.5ns ±13%
    98  Int64/1Delete9Store90Load/sync.Map-16            480ns ± 4%
    99  Int64/1Range9Delete90Store900Load/skipmap-16    34.2ns ±26%
   100  Int64/1Range9Delete90Store900Load/sync.Map-16   1.00µs ±12%
   101  String/Store/skipmap-16                          171ns ±15%
   102  String/Store/sync.Map-16                         873ns ± 4%
   103  String/Load50Hits/skipmap-16                    21.3ns ±38%
   104  String/Load50Hits/sync.Map-16                   19.9ns ±12%
   105  String/30Store70Load/skipmap-16                 75.6ns ±16%
   106  String/30Store70Load/sync.Map-16                 726ns ± 5%
   107  String/1Delete9Store90Load/skipmap-16           34.3ns ±20%
   108  String/1Delete9Store90Load/sync.Map-16           584ns ± 5%
   109  String/1Range9Delete90Store900Load/skipmap-16   41.0ns ±21%
   110  String/1Range9Delete90Store900Load/sync.Map-16  1.17µs ± 8%
   111  
   112  name                                            alloc/op
   113  Int64/Store/skipmap-16                            112B ± 0%
   114  Int64/Store/sync.Map-16                           128B ± 0%
   115  Int64/Load50Hits/skipmap-16                      0.00B     
   116  Int64/Load50Hits/sync.Map-16                     0.00B     
   117  Int64/30Store70Load/skipmap-16                   33.0B ± 0%
   118  Int64/30Store70Load/sync.Map-16                  81.2B ±11%
   119  Int64/1Delete9Store90Load/skipmap-16             10.0B ± 0%
   120  Int64/1Delete9Store90Load/sync.Map-16            57.9B ± 5%
   121  Int64/1Range9Delete90Store900Load/skipmap-16     10.0B ± 0%
   122  Int64/1Range9Delete90Store900Load/sync.Map-16     261B ±17%
   123  String/Store/skipmap-16                           144B ± 0%
   124  String/Store/sync.Map-16                          152B ± 0%
   125  String/Load50Hits/skipmap-16                     15.0B ± 0%
   126  String/Load50Hits/sync.Map-16                    15.0B ± 0%
   127  String/30Store70Load/skipmap-16                  54.0B ± 0%
   128  String/30Store70Load/sync.Map-16                 96.9B ±12%
   129  String/1Delete9Store90Load/skipmap-16            27.0B ± 0%
   130  String/1Delete9Store90Load/sync.Map-16           74.2B ± 4%
   131  String/1Range9Delete90Store900Load/skipmap-16    27.0B ± 0%
   132  String/1Range9Delete90Store900Load/sync.Map-16    257B ±10%
   133  
   134  name                                            allocs/op
   135  Int64/Store/skipmap-16                            3.00 ± 0%
   136  Int64/Store/sync.Map-16                           4.00 ± 0%
   137  Int64/Load50Hits/skipmap-16                       0.00     
   138  Int64/Load50Hits/sync.Map-16                      0.00     
   139  Int64/30Store70Load/skipmap-16                    0.00     
   140  Int64/30Store70Load/sync.Map-16                   1.00 ± 0%
   141  Int64/1Delete9Store90Load/skipmap-16              0.00     
   142  Int64/1Delete9Store90Load/sync.Map-16             0.00     
   143  Int64/1Range9Delete90Store900Load/skipmap-16      0.00     
   144  Int64/1Range9Delete90Store900Load/sync.Map-16     0.00     
   145  String/Store/skipmap-16                           4.00 ± 0%
   146  String/Store/sync.Map-16                          5.00 ± 0%
   147  String/Load50Hits/skipmap-16                      1.00 ± 0%
   148  String/Load50Hits/sync.Map-16                     1.00 ± 0%
   149  String/30Store70Load/skipmap-16                   1.00 ± 0%
   150  String/30Store70Load/sync.Map-16                  2.00 ± 0%
   151  String/1Delete9Store90Load/skipmap-16             1.00 ± 0%
   152  String/1Delete9Store90Load/sync.Map-16            1.00 ± 0%
   153  String/1Range9Delete90Store900Load/skipmap-16     1.00 ± 0%
   154  String/1Range9Delete90Store900Load/sync.Map-16    1.00 ± 0%
   155  ```