-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sync: add Map.Len method? #20680
Comments
What's the use-case? |
I am storing items filled by goroutines processing data into 2 separate maps. Once this is done, I need to compare the length of these 2 maps to perform a quick sanity check and decide on which branch to proceed for further processing. Previously I was using github.com/orcaman/concurrent-map and there was a |
This would normally be a Go 1.10 thing, but since this type is new in Go 1.9, I'll let @bcmills decide. The implementation might be hairy enough to warrant Go 1.10 anyway, especially if the representation needs to change and other code gets modified. |
Isn't the number you get out going to be a best-effort guess anyway? (Like len(channel)). Seems like an easy user workaround would be to maintain a parallel atomic int64 count. (I don't know if that'd also be a reasonable internal implementation or not.) |
In my case, I am retrieving the length of the map after all goroutines have finished. |
The I'm not opposed to the idea of adding a |
@bcmills Do not you think it's very rediculous that Go has a built in func len for map while sync.Map does not have a corresponding function func (Map)Len() int to get its size? |
@AlexStocks No, I don't think it's "very [ridiculous]". Concurrent data structures are not the same as unsynchronized data structures. The built-in We should decide the API of each type based on its own tradeoffs. Consistency is a benefit, but there are costs to weigh it against. |
I thank go1.9 sync.map length feature should be required. Of course, I'm just a suggestion. |
We didn't omit |
#21035 has more detail on some of the optimizations that might complicate an efficient implementation of |
@bcmills May I suggest to have some remark in the source comments saying something like This would ease understanding and adjust expectations of future users (who much more likely read source comments than old issues). ( And this should also be applied to other methods suggested elsewhere (such as |
I looked up the sourcecode of Range() and I think (knowing that the result could be wrong, see remark on Range() and above) this would be the solution for Len() return len(read.m) instead of the for loop in line 328 |
@maj-o Promoting the |
I believe that having a Hope this shows some use-cases for you. I can think of various situations where this simple functionality would reduce code by many lines. |
I think that does not justify adding a method to sync.Map, because it's easy to make your own derived type which just additionaly keeps the count/len information if you think such information is useful. |
If dirty has length oft N. |
My usecase for an O(1) So for my usecase, |
Hey guys, I just want to clarify on something here. What would you say the scope of requirements adding such functionally be? Like, to make a decision to add this utility function a part of the API, are you looking for a large quantity of developer need/want for the feature? Or are we just aiming to decide how it should work? I'm the former situation I believe that a count feature would just be expected by developers considering that the map type can be used in len() In the latter situation if it's something that we all want added, but comes down to deciding how it should operate, I think that leads to two potential situations: 1 - a somewhat ballpark count of the map would be necessary for an application. This could be non blocking and the result just needs to be close to the current state. 2 - a blocking function that needs to be timed for an absolute accurate count at the given moment. A utility function could be made for both scenarios. I think it is best to make at least the boilerplate functionality for developers to help evade bad practices due to niavity when using the API. Best practices with concurrency is not obvious to new developers and devs trying to adopt go. I do foresee newbies at least reading a godoc and being able to choose based on need. |
I'd like to add another use case, and am seeking alternative suggestions. My use case is with testing. I recently moved from a conventional map + With maps I can easily check I'm getting around this currently by wrapping the check in a function that iterates @bcmills Has there been any reconsideration for adding native |
@jessicayuen , add an atomic counter after every add/delete. If the atomic is zero the map is empty. This approach has a benefit. You can add a simple performance monitor (see the idea https://github.com/larytet-go/accumulator) on top of the atomic and watch the load of the map in the real-time. |
@jessicayuen, if the test fails, presumably you're going to need to know more about the failure mode than just the length of the map. (Which key or keys failed to be removed? Are the channels associated with those keys So you likely need that |
My use-case for this, since one was asked for earlier, is for efficient allocation of space in a regular mystuff := map[interface{}]interface{}{}
syncMap.Range(func (key, value interface{}) bool {
mystuff[key] = value
return true
}) and these maps get big, so that does a lot of reallocation. It'd be an improvement to be able to do: mystuff := make(map[interface{}]interface{}, syncMap.Len()) even if that's misleading because other things are added before the Range because it'll still help avoid reallocs. |
@ocket8888 , |
The actual Preparing the map ahead of time is out of the question for a litany of reasons, not the least of which being "I would have no idea how to even begin implementing that in this pile of fettucine code, and the very thought gives me shakes and dry heaves". Thanks for the suggestion, I think I'll probably do that at some point. |
@ocket8888 afaik |
From the sync.Map docs:
My case is the second. There are many goroutines reading, writing, and especially overwriting entries for disjoint sets of keys. Actually, to be specific, there are many goroutines writing and overwriting, and only one reading. |
@ocket8888 May be a custom lock free hashtable makes sense in your case? |
Can someone clarify if the stance changed on this? Revisiting this after over a year, I think this entire issue needs to be closed. We're beating a dead horse that's going nowhere. This became evident to me over time as I realized this feature doesn't matter. It's not a blocker for anything, coding around it is easy, and the only people wanting this are just asking for a convenience tool (I will admit that was the case that led me to being in this issue). That leads me to the solution. The blocker has already been expressed in this issue of "who needs it?" The way I see it, if we really want it, we have to go make it, market it, and maybe one day we might be able to show the interest it takes to get it into the standard library. Absent of that, this is a dead horse. Good luck comrades. I'm unsubscribing. |
Testing, I need to test if the elements on the map are exactly what I expect. |
Then you’d want to iterate over the map to asset that it’s contents are identical. |
When I implement a counter of stored keys internally I occasionally do the following:
In the call to MyStore() I increment the length counter Is there a chance to add a return value to the sync.Map.Store which returns Ok if the key did not exist in the map before the call? |
Just call it "BlockingLen" or "SlowLen" or "DontUseItLen" if you are worried users don't realize it is costly, but I don't think that hundreds (looks at the upvotes...) of peoples having to re-implement len by hand is very efficient... |
We waiting for it 4 years. |
We should put this issue through the proposal process since it's an API change. |
I think it's clear at this point that we are not going to add this method. In general making I'm closing this issue. |
What about providing this simple wrapper in stdlib? |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?1.9-beta1
What operating system and processor architecture are you using (
go env
)?Windows 10 64-bit
It would be really useful to have a
Length()
method onsync.Map
that can return the number of items in a map. Currently, I need to do something like this, which is quite tedious and not as readable:The text was updated successfully, but these errors were encountered: