Code Monkey home page Code Monkey logo

syncmap's Introduction

syncmap

https://godoc.org/github.com/a8m/syncmap LICENSE Build Status Go Report Card

A typed implementation of the Go sync.Map using code generation.

Install

go get -u github.com/a8m/syncmap@master

Examples:

  1. Using CLI
$ syncmap -name IntMap "map[int]int"
$ syncmap -name RequestMap -pkg mypkg "map[string]*http.Request"

Or:

$ go run github.com/a8m/syncmap -name IntMap "map[int]int"
  1. Using go generate.

    • Add a directive with map definition:
      //go:generate go run github.com/a8m/syncmap -name WriterMap map[string]io.Writer
      
      //go:generate go run github.com/a8m/syncmap -name Requests map[string]*http.Request
    • Then, run go generate on this package.

    See testdata/gen.go for more examples.

How does it work?

syncmap didn't copy the code of sync/map.go and replace its identifiers. Instead, it reads the sync/map.go from your GOROOT, parses it into an *ast.File, and runs a few mutators that bring it to the desired state. Check the code for more information.

How can we make sure it will continue to work? - I'm running a daily CI test on TravisCI.

Benchmark

Benchmark tests were taken from the sync package.

BenchmarkLoadMostlyHits/*main.DeepCopyMap-8         	100000000	        15.1 ns/op
BenchmarkLoadMostlyHits/*main.RWMutexMap-8          	30000000	        54.4 ns/op
BenchmarkLoadMostlyHits/*sync.Map-8                 	100000000	        14.0 ns/op
BenchmarkLoadMostlyHits/*main.IntMap-8              	300000000	        5.65 ns/op <--

BenchmarkLoadMostlyMisses/*main.DeepCopyMap-8       	200000000	        10.2 ns/op
BenchmarkLoadMostlyMisses/*main.RWMutexMap-8        	30000000	        59.2 ns/op
BenchmarkLoadMostlyMisses/*sync.Map-8               	100000000	        11.3 ns/op
BenchmarkLoadMostlyMisses/*main.IntMap-8            	300000000	        4.05 ns/op <--

BenchmarkLoadOrStoreBalanced/*main.RWMutexMap-8     	 3000000	        400 ns/op
BenchmarkLoadOrStoreBalanced/*sync.Map-8            	 3000000	        400 ns/op
BenchmarkLoadOrStoreBalanced/*main.IntMap-8         	 5000000	        233 ns/op <--

BenchmarkLoadOrStoreUnique/*main.RWMutexMap-8       	 2000000	        744 ns/op
BenchmarkLoadOrStoreUnique/*sync.Map-8              	 2000000	        903 ns/op
BenchmarkLoadOrStoreUnique/*main.IntMap-8           	 3000000	        388 ns/op <--

BenchmarkLoadOrStoreCollision/*main.DeepCopyMap-8   	200000000	        7.29 ns/op
BenchmarkLoadOrStoreCollision/*main.RWMutexMap-8    	20000000	        97.5 ns/op
BenchmarkLoadOrStoreCollision/*sync.Map-8           	200000000	        9.11 ns/op
BenchmarkLoadOrStoreCollision/*main.IntMap-8        	500000000	        3.14 ns/op <--

BenchmarkRange/*main.DeepCopyMap-8                  	  500000	        4479 ns/op
BenchmarkRange/*main.RWMutexMap-8                   	   30000	        56834 ns/op
BenchmarkRange/*sync.Map-8                          	  300000	        4464 ns/op
BenchmarkRange/*main.IntMap-8                       	1000000000	        2.38 ns/op <--

BenchmarkAdversarialAlloc/*main.DeepCopyMap-8       	 2000000	        826 ns/op
BenchmarkAdversarialAlloc/*main.RWMutexMap-8        	20000000	        73.6 ns/op
BenchmarkAdversarialAlloc/*sync.Map-8               	 5000000	        303 ns/op
BenchmarkAdversarialAlloc/*main.IntMap-8            	10000000	        182 ns/op <--

BenchmarkAdversarialDelete/*main.DeepCopyMap-8      	10000000	        204 ns/op
BenchmarkAdversarialDelete/*main.RWMutexMap-8       	20000000	        78.3 ns/op
BenchmarkAdversarialDelete/*sync.Map-8              	20000000	        72.2 ns/op
BenchmarkAdversarialDelete/*main.IntMap-8           	100000000	        14.2 ns/op <--

Running benchmark with -benchmem

BenchmarkLoadMostlyHits/*main.DeepCopyMap-8         100000000	  12.7 ns/op	  7 B/op	  0 allocs/op
BenchmarkLoadMostlyHits/*main.RWMutexMap-8          30000000	  53.6 ns/op	  7 B/op	  0 allocs/op
BenchmarkLoadMostlyHits/*sync.Map-8                 100000000	  16.3 ns/op	  7 B/op	  0 allocs/op
BenchmarkLoadMostlyHits/*main.IntMap-8              200000000	  6.02 ns/op	  0 B/op	  0 allocs/op <--

BenchmarkLoadMostlyMisses/*main.DeepCopyMap-8       200000000	  7.99 ns/op	  7 B/op	  0 allocs/op
BenchmarkLoadMostlyMisses/*main.RWMutexMap-8        30000000	  52.6 ns/op	  7 B/op	  0 allocs/op
BenchmarkLoadMostlyMisses/*sync.Map-8               200000000	  8.87 ns/op	  7 B/op	  0 allocs/op
BenchmarkLoadMostlyMisses/*main.IntMap-8            1000000000	  2.88 ns/op	  0 B/op	  0 allocs/op <--

BenchmarkLoadOrStoreBalanced/*main.RWMutexMap-8     3000000	  357 ns/op	  71 B/op	  2 allocs/op
BenchmarkLoadOrStoreBalanced/*sync.Map-8            3000000	  417 ns/op	  70 B/op	  3 allocs/op
BenchmarkLoadOrStoreBalanced/*main.IntMap-8         5000000	  202 ns/op	  42 B/op	  1 allocs/op <--

BenchmarkLoadOrStoreUnique/*main.RWMutexMap-8       2000000	  648 ns/op	  178 B/op	  2 allocs/op
BenchmarkLoadOrStoreUnique/*sync.Map-8              2000000	  745 ns/op	  163 B/op	  4 allocs/op
BenchmarkLoadOrStoreUnique/*main.IntMap-8           3000000	  368 ns/op	  74 B/op	  2 allocs/op <--

BenchmarkLoadOrStoreCollision/*main.DeepCopyMap-8   300000000	  5.90 ns/op	  0 B/op	  0 allocs/op
BenchmarkLoadOrStoreCollision/*main.RWMutexMap-8    20000000	  94.5 ns/op	  0 B/op	  0 allocs/op
BenchmarkLoadOrStoreCollision/*sync.Map-8           200000000	  7.55 ns/op	  0 B/op	  0 allocs/op
BenchmarkLoadOrStoreCollision/*main.IntMap-8        1000000000	  2.68 ns/op	  0 B/op	  0 allocs/op <--

BenchmarkRange/*main.DeepCopyMap-8                  500000	  3376 ns/op	  0 B/op	  0 allocs/op
BenchmarkRange/*main.RWMutexMap-8                   30000	  56675 ns/op	  16384 B/op	  1 allocs/op
BenchmarkRange/*sync.Map-8                          500000	  3587 ns/op	  0 B/op	  0 allocs/op
BenchmarkRange/*main.IntMap-8                       2000000000	  1.75 ns/op	  0 B/op	  0 allocs/op <--

BenchmarkAdversarialAlloc/*main.DeepCopyMap-8       2000000	  761 ns/op	  535 B/op	  1 allocs/op
BenchmarkAdversarialAlloc/*main.RWMutexMap-8        20000000	  67.9 ns/op	  8 B/op	  1 allocs/op
BenchmarkAdversarialAlloc/*sync.Map-8               5000000	  264 ns/op	  51 B/op	  1 allocs/op
BenchmarkAdversarialAlloc/*main.IntMap-8            10000000	  176 ns/op	  28 B/op	  0 allocs/op <--

BenchmarkAdversarialDelete/*main.DeepCopyMap-8      10000000	  194 ns/op	  168 B/op	  1 allocs/op
BenchmarkAdversarialDelete/*main.RWMutexMap-8       20000000	  76.9 ns/op	  25 B/op	  1 allocs/op
BenchmarkAdversarialDelete/*sync.Map-8              20000000	  60.8 ns/op	  18 B/op	  1 allocs/op
BenchmarkAdversarialDelete/*main.IntMap-8           100000000	  13.1 ns/op	  0 B/op	  0 allocs/op <--

LICENSE

I am providing code in the repository to you under MIT license. Because this is my personal repository, the license you receive to my code is from me and not my employer (Facebook)

syncmap's People

Contributors

a8m avatar owen5mith avatar yangjuncode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

syncmap's Issues

syncmap: function was deleted

Hi @a8m ,

No matter which example command you mentioned in the doc' I'm always ending with this error:

sneko@sneko XXXXX % go run github.com/a8m/syncmap -name IntMap "map[int]int"
syncmap: function was deleted

I also tried directly yncmap -name IntMap "map[int]int" but same error.

Any idea of what I'm missing that triggers (?)

expect(len(g.funcs) == 0, "function was deleted")

Thank you,

The case BenchmarkRange seems has some problem ?

// syncmap code:
	b.Run(fmt.Sprintf("%T", &IntMap{}), func(b *testing.B) {
		m := &IntMap{}
		// setup:

		// reset:
		b.ResetTimer()

		// perG:
		perG := func(b *testing.B, pb *testing.PB, i int, m *IntMap) {
			for ; pb.Next(); i++ {
				m.Range(func(_, _ int) bool { return true })
			}
		}
		var i int64
		b.RunParallel(func(pb *testing.PB) {
			id := int(atomic.AddInt64(&i, 1) - 1)
			perG(b, pb, id*b.N, m)
		})
	})

seems the setup function is nil, then the map is empy, so at the benrchmark result, it seems vary fast

not work on go 1.18 any more

the simple cli: syncmap -name TsysLicMap -pkg mypkg "map[string]*http.Request"
generate the code type is any.

func (m *TsysLicMap) Load(key any) (value any, ok bool) 

Can different custom packages for key and value is possible?

Hi @a8m ,

Currently using a basic

syncmap -name UserChannelsMap -pkg xmap -o ./types/xmap/user_channels_map.go "map[string]string"

will work.

If I want to use a custom type:

syncmap -name UserChannelsMap -pkg xmap -o ./types/xmap/user_channels_map.go "map[string]*UserChannelList"

I need to make sure UserChannelList is in the same package than the one exported for the file (here xmap). I could arrange myself to do so, but it brings some complexity.

Last case, I want to use like an "enum" for the keys, in my case it's defined in my own constant package, how could I deal with this? From what I understand it's not possible, the syncmap would have to manage some add of imports, no?

syncmap -name UserChannelsMap -pkg xmap -o ./types/xmap/user_channels_map.go "map[constant.NameID]*UserChannelList"

Maybe I missed something ๐Ÿค”

Thank you,

EDIT: a workaround could be that aside my exported file (having package xmap) I could declare type aliases for both the key and the value types, like:

import ...

type NameID = constant.NameID
type UserChannelList = entity.UserChannelList

EDIT2: in all cases, I should make sure it won't bring circular loop if the XXXMap was needed in one of those packages ^^

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.