Skip to content
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

object hash code #45

Open
mkeskells opened this issue Jan 30, 2018 · 1 comment
Open

object hash code #45

mkeskells opened this issue Jan 30, 2018 · 1 comment

Comments

@mkeskells
Copy link
Collaborator

is it faster to default the hash code or stamp it in?

lots of objects hashcode are frequent, e.g. Nil

126256	scala.collection.immutable.Nil$::hashCode()I

small saving - but is an override faster that the default?

@ackratos
Copy link
Collaborator

no obvious benefit:

Index: src/library/scala/collection/immutable/List.scala
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/library/scala/collection/immutable/List.scala	(revision c35b69aad76d0f3da449585708f792268a93a2b0)
+++ src/library/scala/collection/immutable/List.scala	(revision )
@@ -433,6 +433,7 @@
     case that1: scala.collection.GenSeq[_] => that1.isEmpty
     case _ => false
   }
+  override def hashCode() = scala.util.hashing.MurmurHash3.seqSeed
 }
 
 /** A non empty list characterized by a head and a tail.

on benchmark:

package scala.collection.immutable

import java.util.concurrent.TimeUnit

import org.openjdk.jmh.annotations._
import org.openjdk.jmh.infra.Blackhole

@BenchmarkMode(Array(Mode.AverageTime))
@Fork(2)
@Threads(1)
@Warmup(iterations = 10)
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
class EmptyListBenchmark {
  @OperationsPerInvocation(10000000)
  @Benchmark def hashCode(bh: Blackhole): Any = {
    for (1 <- 1 to 10000000) {
      val hashCode = Nil.hashCode()
      bh.consume(hashCode)
    }
  }
}

above is optimized version, below is baseline:

[info] Benchmark                    Mode  Cnt  Score   Error  Units
[info] EmptyListBenchmark.hashCode  avgt   20  3.392 ± 0.082  ns/op

[info] Benchmark                    Mode  Cnt  Score   Error  Units
[info] EmptyListBenchmark.hashCode  avgt   20  3.436 ± 0.108  ns/op

pkukielka pushed a commit that referenced this issue Apr 30, 2018
Abstractions for constrained collection types
pkukielka pushed a commit that referenced this issue Apr 30, 2018
`BuildFrom` is like `FromSpecificIterable` but with an extra `From`
argument, like in the final version of #45. `FromSpecificIterable`
existed conceptually in that version as `BuildFrom[Any, …]` but didn’t
have a separate type.

This new version has separate abstractions for buildable (strict)
collection types in the form of `StrictBuildFrom` and
`FromSpecificIterableWithBuilder`. Since we can get a surrogate builder
(through one of the new `Builder.from` methods) for any lazy collection
and we can restrict code to work only with strict collections via the
`Buildable` trait, this is not strictly necessary. The only reason for
separating the `Builder` abstractions is to avoid exposing them in
`FromSpecificIterable`. Even though everything can be built in a strict
way, these abstractions sit on top of the lazy ones, not below them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants