3

I am looking for suggestions to a fast Map with Long keys. It will have a lot of read accesses and rather small write/update accesses. Performance should thus focus on read (get) access. It must be thread-safe. Some ideas:

  1. regular collection.Map[Long, _] has to box keys
  2. bare bones collection.mutable would have to wrap synchronized all the time, penalising read access
  3. bare bones collection.immutable could have unsynchronized read access if stored in a @volatile var. Update could synchronize.
  4. perhaps TMap from Scala-STM? But then a Ref[Map[Long, _]] probably is as good because concurrent reads should be allowed in STM

To me No. 3 sound best?

1
  • I think volatile will affect the collection itself, not its content.
    – user2889419
    Commented Feb 25, 2014 at 22:01

3 Answers 3

2

There is an immutable LongMap, and 2.11 will have a mutable LongMap. The latter is not thread-safe, but you could wrap accesses (probably with a read-write lock from java.util.concurrent, if you're mostly reading and can reason through possible deadlocks). If you have a lot of contention, you're unlikely to do much better than just using java.util.concurrent.ConcurrentHashMap; threading issues will be much more expensive then than a bit of extra boxing.

3
  • What is the largely in Note: This class is as of 2.8 largely superseded by HashMap. on LongMap?
    – som-snytt
    Commented Feb 26, 2014 at 6:21
  • Exactly, I saw the note about being obsolete. Also, since it is in the regular scala.collection type hierarchy, I think it will still box the keys, right?
    – 0__
    Commented Feb 26, 2014 at 9:21
  • @0__ - I am not terribly familiar with immutable.LongMap, but it shouldn't box the keys unless you use in a generic context (in which case it will both box and unbox them). It is true that immutable.LongMap hasn't been worked on much. The mutable one is brand new, though.
    – Rex Kerr
    Commented Feb 26, 2014 at 19:07
2

collection.Map isn't thread-safe by default, but has to use the SynchronizedMap trait which is just locking around all accesses - performance wise not so great, probably slower than a simple ConcurrentHashMap.

Using an immutable map and a volatile variable which is replaced when updating would work and would be the cheapest possible option read wise (can't get cheaper than a simple volatile read). Expensive when updating though.

No idea how good Scala's STM is, so certainly worth a try too.

One option you should definitely consider, would be Cliff's non-blocking hashmap though, see here. It does have a Long version so you avoid boxing and it's performance-wise hard to beat (depending on the situation faster to extremely faster compared to the ConcurrentHashMap in the java stdlib which again is a good deal quicker than just using a normal hashmap and locking around every access).

1
  • thanks for mentioning java.util.concurrent.ConcurrentHashMap, might be a good comparison in performance tests
    – 0__
    Commented Feb 26, 2014 at 9:20
1

Sounds like a good use of the either a regular HashMap or the fastutil Long2Object map and a ReentrantReadWriteLock. That lock will let you have multiple simultaneously open read locks, but write locks have to be exclusive. I'd still benchmark it against ConcurrentHashMap because its implementation is known to be pretty good.

Doh! You probably want a Scala answer and not the Java flavor.

1
  • Thanks! I don't care if it's Java or Scala, as long as its compact and open source.
    – 0__
    Commented Feb 26, 2014 at 9:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.