- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Can I get an optimisation?
Sun, 2010-08-29, 18:15
Good to know. It also makes sense. I was running through an algorithm to determine if you could optimise the enumeration. They all rely on the premise that the code with the pattern match would get recompiled after the enumeration changes. As I've worked in too many projects, I know there will be the case where this doesn't happen and subtle bugs would be introduced. However, you could potentially make the optimisation available as a -Y option, and emit warnings if the enumeration + switch are in separate compilation units.
In any case, I was just curious if anyone had thought about this, or if it was even useful enough to pay attention to it.
On Sun, Aug 29, 2010 at 1:11 PM, Alex Cruise <alex@cluonflux.com> wrote:
In any case, I was just curious if anyone had thought about this, or if it was even useful enough to pay attention to it.
On Sun, Aug 29, 2010 at 1:11 PM, Alex Cruise <alex@cluonflux.com> wrote:
javac only emits a switch opcode when the switch statement is in the same compilation unit (i.e. file) as the enum is declared. Otherwise you get an if-then-else ladder.
-0xe1a
On Sun, Aug 29, 2010 at 9:52 AM, Josh Suereth <joshua.suereth@gmail.com> wrote:import annotation.switch
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
class Test {
def couldThisBeOptimised(x : WeekDay) = x match {
case Mon => "Case of the Mondays"
case Tue => "Ruby Tuesdays?"
case Fri => "Thank God!"
case _ => "Not an interesting day"
}
}
Just for fun, I tried to see if I could force this by hand:
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
val Mon_ID = Mon.id;
val Tue_ID = Tue.id;
val Wed_ID = Wed.id;
val Thu_ID = Thu.id;
val Fri_ID = Fri.id;
val Sat_ID = Sat.id;
val Sun_ID = Sun.id;
}
import WeekDay._
scala> def notOptimisedEnum(x : WeekDay) = (x.id : @switch) match {
| case Mon_ID => "Case of the Mondays"
| case Tue_ID => "Ruby Tuesdays?"
| case Fri_ID => "Thank God!"
| case _ => "Not an interesting day"
| }
<console>:13: error: could not emit switch for @switch annotated match
def notOptimisedEnum(x : WeekDay) = (x.id : @switch) match {
So, my question is: How relevant is emitting a tableswitch bytecode when pattern matching an Enumeration? This seems like a chalk against Scala enumerations (and for encoding enumerations inside Java). However, I haven't ever had a tight loop where I had to rely on the tableswitch bytecode for performance before, so I was wondering what everyone else thought here.
Mon, 2010-08-30, 12:17
#2
Re: {mailcleaner} Re: Can I get an optimisation?
True, but the order is known at compile time. If you can verify that the Enumeration class is closed, the compiler would know in what order IDs are created and hence you could perform the optimisation. Yes, this is more of a hack.
Also, upon reflection, I don't think anyone but my hardcore C coworkers would care about this table switch. If Java enumerations don't support it, then we're probably ok in Scala.
On Mon, Aug 30, 2010 at 5:30 AM, iulian dragos <iulian.dragos@epfl.ch> wrote:
Also, upon reflection, I don't think anyone but my hardcore C coworkers would care about this table switch. If Java enumerations don't support it, then we're probably ok in Scala.
On Mon, Aug 30, 2010 at 5:30 AM, iulian dragos <iulian.dragos@epfl.ch> wrote:
Unfortunately, this is impossible. A tableswitch requires that the alternatives are statically known, as int values. The weekday object is generating ids at runtime, so the method bytecode would need to be generated reflectively, probably ending up much slower than a bunch of ifs.
For instance, this works:
final val ONE = 1 final val TWO = 2 final val THREE = 3
def testOpt2(x: Int) = (x: @switch) match { case ONE => "a" case TWO => "b" case _ => "c" }
iulian
On Sun, Aug 29, 2010 at 7:16 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
Good to know. It also makes sense. I was running through an algorithm to determine if you could optimise the enumeration. They all rely on the premise that the code with the pattern match would get recompiled after the enumeration changes. As I've worked in too many projects, I know there will be the case where this doesn't happen and subtle bugs would be introduced. However, you could potentially make the optimisation available as a -Y option, and emit warnings if the enumeration + switch are in separate compilation units.
In any case, I was just curious if anyone had thought about this, or if it was even useful enough to pay attention to it.
On Sun, Aug 29, 2010 at 1:11 PM, Alex Cruise <alex@cluonflux.com> wrote:
javac only emits a switch opcode when the switch statement is in the same compilation unit (i.e. file) as the enum is declared. Otherwise you get an if-then-else ladder.
-0xe1a
On Sun, Aug 29, 2010 at 9:52 AM, Josh Suereth <joshua.suereth@gmail.com> wrote:import annotation.switch
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
class Test {
def couldThisBeOptimised(x : WeekDay) = x match {
case Mon => "Case of the Mondays"
case Tue => "Ruby Tuesdays?"
case Fri => "Thank God!"
case _ => "Not an interesting day"
}
}
Just for fun, I tried to see if I could force this by hand:
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
val Mon_ID = Mon.id;
val Tue_ID = Tue.id;
val Wed_ID = Wed.id;
val Thu_ID = Thu.id;
val Fri_ID = Fri.id;
val Sat_ID = Sat.id;
val Sun_ID = Sun.id;
}
import WeekDay._
scala> def notOptimisedEnum(x : WeekDay) = (x.id : @switch) match {
| case Mon_ID => "Case of the Mondays"
| case Tue_ID => "Ruby Tuesdays?"
| case Fri_ID => "Thank God!"
| case _ => "Not an interesting day"
| }
<console>:13: error: could not emit switch for @switch annotated match
def notOptimisedEnum(x : WeekDay) = (x.id : @switch) match {
So, my question is: How relevant is emitting a tableswitch bytecode when pattern matching an Enumeration? This seems like a chalk against Scala enumerations (and for encoding enumerations inside Java). However, I haven't ever had a tight loop where I had to rely on the tableswitch bytecode for performance before, so I was wondering what everyone else thought here.
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais
Tue, 2010-08-31, 00:07
#3
Re: {mailcleaner} Re: Can I get an optimisation?
On Mon, Aug 30, 2010 at 4:05 AM, Josh Suereth wrote:
> Also, upon reflection, I don't think anyone but my hardcore C coworkers
> would care about this table switch. If Java enumerations don't support it,
> then we're probably ok in Scala.
OpenJDK javac compiles enum switches to tableswitch, c.f.:
8: invokevirtual #4; //Method Test$Foo.ordinal:()I
11: iaload
12: tableswitch{ //1 to 3
1: 40;
2: 51;
3: 62;
default: 70 }
And it relies on internal compiler hackery to determine the static
value of the enum ordinals.
Tue, 2010-08-31, 09:07
#4
Re: {mailcleaner} Re: Can I get an optimisation?
On Mon, Aug 30, 2010 at 1:05 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
True, but the order is known at compile time. If you can verify that the Enumeration class is closed, the compiler would know in what order IDs are created and hence you could perform the optimisation. Yes, this is more of a hack.
It means the compiler has to know about the implementation of Value, so then Enumeration becomes a language feature, instead of a library class. I'm not sure it's worth it.
iulian
Also, upon reflection, I don't think anyone but my hardcore C coworkers would care about this table switch. If Java enumerations don't support it, then we're probably ok in Scala.
On Mon, Aug 30, 2010 at 5:30 AM, iulian dragos <iulian.dragos@epfl.ch> wrote:Unfortunately, this is impossible. A tableswitch requires that the alternatives are statically known, as int values. The weekday object is generating ids at runtime, so the method bytecode would need to be generated reflectively, probably ending up much slower than a bunch of ifs.
For instance, this works:
final val ONE = 1 final val TWO = 2 final val THREE = 3
def testOpt2(x: Int) = (x: @switch) match { case ONE => "a" case TWO => "b" case _ => "c" }
iulian
On Sun, Aug 29, 2010 at 7:16 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
Good to know. It also makes sense. I was running through an algorithm to determine if you could optimise the enumeration. They all rely on the premise that the code with the pattern match would get recompiled after the enumeration changes. As I've worked in too many projects, I know there will be the case where this doesn't happen and subtle bugs would be introduced. However, you could potentially make the optimisation available as a -Y option, and emit warnings if the enumeration + switch are in separate compilation units.
In any case, I was just curious if anyone had thought about this, or if it was even useful enough to pay attention to it.
On Sun, Aug 29, 2010 at 1:11 PM, Alex Cruise <alex@cluonflux.com> wrote:
javac only emits a switch opcode when the switch statement is in the same compilation unit (i.e. file) as the enum is declared. Otherwise you get an if-then-else ladder.
-0xe1a
On Sun, Aug 29, 2010 at 9:52 AM, Josh Suereth <joshua.suereth@gmail.com> wrote:import annotation.switch
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
class Test {
def couldThisBeOptimised(x : WeekDay) = x match {
case Mon => "Case of the Mondays"
case Tue => "Ruby Tuesdays?"
case Fri => "Thank God!"
case _ => "Not an interesting day"
}
}
Just for fun, I tried to see if I could force this by hand:
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
val Mon_ID = Mon.id;
val Tue_ID = Tue.id;
val Wed_ID = Wed.id;
val Thu_ID = Thu.id;
val Fri_ID = Fri.id;
val Sat_ID = Sat.id;
val Sun_ID = Sun.id;
}
import WeekDay._
scala> def notOptimisedEnum(x : WeekDay) = (x.id : @switch) match {
| case Mon_ID => "Case of the Mondays"
| case Tue_ID => "Ruby Tuesdays?"
| case Fri_ID => "Thank God!"
| case _ => "Not an interesting day"
| }
<console>:13: error: could not emit switch for @switch annotated match
def notOptimisedEnum(x : WeekDay) = (x.id : @switch) match {
So, my question is: How relevant is emitting a tableswitch bytecode when pattern matching an Enumeration? This seems like a chalk against Scala enumerations (and for encoding enumerations inside Java). However, I haven't ever had a tight loop where I had to rely on the tableswitch bytecode for performance before, so I was wondering what everyone else thought here.
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais
For instance, this works:
final val ONE = 1 final val TWO = 2 final val THREE = 3
def testOpt2(x: Int) = (x: @switch) match { case ONE => "a" case TWO => "b" case _ => "c" }
iulian
On Sun, Aug 29, 2010 at 7:16 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais