--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Greg has done some work recently on making our hashconsing use WeakHashMaps. I guess similar optimizations await us for other big sets that are needlessly retained.
--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
If you don't have a set specialized on integers, couldn't that actually cause _more_ GC with all the boxing? (More items to traverse.)
Is the compiler allowed to use tagged types? If Ints are being used as light-weight identifiers for Symbol, I'd want this documented and enforced by the type-system - things get cryptic really, really fast otherwise. Something like:trait UniquelyIdentifies[T]type SymbolId = Int with UniquelyIdentifies[Symbol]This SymbolId type has a natural bijection to/from Symbol - wrap up the symbol id and resolve an id via a lookup function.trait IdentityBijection[T, U] {def identify(u: U): T with UniquelyIdentifies[U]def resolve(t: T with UniquelyIdentifies[U]): U}I have no doubt that there are a bunch of places where this kind of thing goes on, with ints or strings or other structures acting as global or scoped identities for instances, and in many cases this won't be explicitly honoured in the types.
Matthew
On Friday, March 1, 2013 9:33:02 AM UTC+9, Matthew Pocock wrote:Is the compiler allowed to use tagged types? If Ints are being used as light-weight identifiers for Symbol, I'd want this documented and enforced by the type-system - things get cryptic really, really fast otherwise. Something like:trait UniquelyIdentifies[T]type SymbolId = Int with UniquelyIdentifies[Symbol]This SymbolId type has a natural bijection to/from Symbol - wrap up the symbol id and resolve an id via a lookup function.trait IdentityBijection[T, U] {def identify(u: U): T with UniquelyIdentifies[U]def resolve(t: T with UniquelyIdentifies[U]): U}I have no doubt that there are a bunch of places where this kind of thing goes on, with ints or strings or other structures acting as global or scoped identities for instances, and in many cases this won't be explicitly honoured in the types.
MatthewShouldn't value classes do the job here? In Haskell you're supposed to use newtype (if you want to avoid extra boxing), and value classes are supposed to be equivalent AFAIK. As in:class SymbolId(val v: Int) extends AnyValorcase class SymbolId(v: Int) extends AnyVal
The demands on the JIT compiler for value classes depends on how much you combine features. It's really just the standard stuff from implicit conversions and case classes,
except in this case the companion object apply and implicit conversions do literally nothing, so it's especially disappointing that they're there.
Well, not all is lost. Until a purity analysis arrives, the new optimizer can check (intra-method) whether a given module has been loaded (for all code-paths leading to the program point in question) and if so consider the side-effects (if any) of the module's constructor to have been honored. I'll add it to the TODO list. BTW, here's the latest incarnation of the new optimizer:
To give an example:
/** closures that are instantiated at least once, after dead code elimination */
val liveClosures: mutable.Set[Symbol] = new mutable.HashSet()
The class-symbols added to that set are reachable via other means, the Set[Symbol] is used just to demarcate a subset of interest:
for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) {
. . .
}
Miguel
http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
On Friday, March 1, 2013 12:57:31 AM UTC+1, Miguel Garcia wrote:
Just to clarify, in those cases where it's clear the Symbol are reachable and will stay so, e.g. via Trees.
Provided that's the case, Set[Symbol] as well as Maps with Symbol-keys; could use Int identities instead.
Miguel
http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
On Friday, March 1, 2013 12:36:35 AM UTC+1, Miguel Garcia wrote:
In the compiler, frequently a Set[Symbol] is used just for testing membership and adding symbols. In those cases, a Set[Int] containing symbol ids would equally do.
It's a low-hanging fruit that makes for lower GC.
Any disadvantages?
Miguel
http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Sure but why would a Set[Int] be more compact than a Set[Symbol]?
By the way, since symbol ids climb monotonically from 1, the high 12 or so bits will always be 0. That's almost a factor of two compression compared to 32 bits - and references can't even get down to 32.
--
How much time/space is spent on this compared to other things, by the way? I'd have thought it's minimal.
On 28 Mar 2013 22:48, "Paul Phillips" <pa...@improving.org> wrote:
> and references can't even get down to 32.
What do you mean? References are 32 bits by default with HotSpot for heaps smaller than 32 GB.
That aside, implementing a specialised int set for Symbols that is more efficient for the desired use cases is worth exploring.
Ismael
What do you mean? References are 32 bits by default with HotSpot for heaps smaller than 32 GB.
On Mar 28, 2013 8:28 PM, "Erik Osheim" <er...@plastic-idolatry.com> wrote:
>
> On Thu, Mar 28, 2013 at 07:30:17PM -0400, Rex Kerr wrote:
> > I'd be surprised if all these tricks were necessary, but this is an area
> > where factors of two improvement are quite possible.
>
> If you're willing to require the underlying array's size be a power of
> two (which it looks like it will be here), you can also get an
> improvement by storing a bitmask and using & rather than % to find
> positions.
That's pretty much what I said ("mask instead of using modulus").
>Also, pre-computing and storing the size at which you'll
> need to resize can make checkResize() a bit faster.
Oh goodness, not on a modern processor. You're much faster with a bit shift and an integer multiplication. Even floating point multiply could be faster.
>
> Also, I'd be tempted to do something a bit smarter than _ + 1 on hash
> collisions, since that can get ugly pretty quickly in some cases.
But it is lovely for avoiding cache misses, and it's a very fast operation, and it makes subtraction easy. Unless you expect periodic structure at some non-negligible power 2, I wouldn't worry about it. See my point about encoding continuations in the high bit, though.
>
> Sorry to be a backseat author here. If I get a minute I'll try
> benchmarking Miguel's example with some alternatives and see what seems
> to work best.
'k, I'll leave this one to you unless you suggest otherwise.
--Rex
Zero memory overhead for Java references (native references are still 64-bit and actual Java objects have more overhead in 64-bit JVMs). There is no CPU overhead for less than 4GB and low overhead for heaps between 4-32GB. Better cache utilisation is worth the CPU overhead in a lot of cases.
Best,
Ismael
On Thu, Mar 28, 2013 at 08:28:42PM -0400, Erik Osheim wrote:
> Sorry to be a backseat author here. If I get a minute I'll try
> benchmarking Miguel's example with some alternatives and see what seems
> to work best.
I'd be happy to clean up the Erik2 implementation and submit it to
Scala if that seems useful to someone. Also, if Rex or anyone else
cares to try to improve further or try an alternate approach I'd be
interested to see the results.
On Thu, Mar 28, 2013 at 11:48 PM, Erik Osheim <er...@plastic-idolatry.com> wrote:On Thu, Mar 28, 2013 at 08:28:42PM -0400, Erik Osheim wrote:
> Sorry to be a backseat author here. If I get a minute I'll try
> benchmarking Miguel's example with some alternatives and see what seems
> to work best.
I'd be happy to clean up the Erik2 implementation and submit it to
Scala if that seems useful to someone. Also, if Rex or anyone else
cares to try to improve further or try an alternate approach I'd be
interested to see the results.
I don't really have any ideas left that you haven't already implemented; Erik2 looks like a good overall winner. I guess I'll try a batched IntSet, but these usually lose to flat schemes.