Is there a way to run a single benchmark with sbt-jmh? - scala

I am working on a big sbt project and there is some functionality that I want to benchmark. I decided that I will be using jmh, thus I enabled the sbt-jmh plugin.
I wrote an initial test benchmark that looks like this:
import org.openjdk.jmh.annotations.Benchmark
class TestBenchmark {
#Benchmark
def functionToBenchMark = {
5 + 5
}
}
However, when I try to run it with jmh:run -i 20 -wi 10 -f1 -t1 .*TestBenchmark.* I get java.lang.InternalError: Malformed class name. I have freshly rebuilt the project and everything compiles and runs just fine.
The first printed message says
Processing 6718 classes from /path-to-repo/target/scala-2.11/classes
with "reflection" generator
I find it weird that the plugin tries to reflect the whole project (I guess including classes within the standard library). Before rebuilding I was getting NoClassDefFoundError, although the project was otherwise working well.
Since there are plenty of classes within the project and I cannot make sure that every little bit conforms to jmh's requirements, I was wondering if there's a way to overcome this issue and focus and reflect only the relevant classes that are annotated with #Benchmark?
My sbt version is 0.13.6 and the sbt-jmh version is 0.2.25.

So this is an issue with Scala and Class.getSimpleClassName.
Its not abonormal in Scala to have types like this:
object Outer {
sealed trait Inner
object Inner {
case object Inner1 extends
case object Inner2 extends Inner
}
}
With the above calling Outer.Inner.Inner1.getClass().getSimpleName() will throw the exception your seeing.
I don't think it uses the full project, but only for things that are directly referred to in the State or Benchmark.
Once I had my bench file written that way it worked.

Related

duplicate package objects in main and test

I have a package object defined in both main and the test code tree as shown below. When I execute the program with sbt run the one in the main code tree takes effect. Whereas when I run the test cases (sbt test) the package object defined in the test code tree takes effect. For eg
src/main/scala/com/example/package.scala
package object core {
val foo = "Hello World"
}
src/test/scala/com/example/package.scala
package object core {
val foo = "Goodbye World"
}
on sbt run the value of com.example.core.foo is Hello World. on sbt test the value of com.example.core.foo is Goodbye World
Is this just a quirk of SBT or is it a well defined scala/sbt trait?. I currently use this behaviour for dependency injection by defining my module bindings for production and test in their corresponding package objects. This is an advisable approach?
Scala looks for package objects in your current path, so it's a well defined behavior. Since your code in test and main resides in different places it finds different val foos.
The way you are using this mechanism is very similar to using implicits. General advice with implicits and implicit resolution is not to abuse it. I think in this case it's not the best way of providing dependencies.
You always have to consider what scope you are in - if you are using a class defined in main in test scope how do you use foo from main, and how do you use foo from test - whenever you need one or the other. You have to think already about how it will work and consider various scenarios. What if your test class is in a different package, which foo would you get, does it depend on where your tested class is declared?
Make dependency injection more explicit and don't spend mental cycles on it, or run a chance to get someone confused.

Does Scala have a global object or class?

I know programmers are supposed to wrap their code in an application object:
object Hello extends App {
println("Hello, World")
}
It is required in Eclipse, if I ever want to get any output. However, when I tried to write some code (very casually) in Emacs, I write like this:
class Pair[+T](val first: T, val second: T)
trait Friend[-T] {
def befriend(someone: T)
}
def makeFriendWith(s: Student, f: Friend[Student]) {
f.befriend(s)
}
It seems like there is no universal object or class that wraps over the function makeFriendWith. Is Scala like JavaScript, everything is attached to a global object? If not, what is this function attached to?
Also why can this work in console (I complied it with scala command and it worked) but does not work in Eclipse? What's the use of the Application object?
Scala doesn't have top-level defs, but your script can be run by either the REPL or the scala script runner.
The precise behavior of your script depends on which way you run it.
The REPL can run scripts line-by-line or whole hog. (Compare :paste and :paste -raw versus :load or -i init.script and the future option -I init.script.)
There is an issue about sensitive scripting. The script runner should realize if you're trying to run an App.
There is another effort to make scripting a compiler phase that is easily customized. Scroll to Scripter.scala for code comments about its current heuristics.
In short, your defs must be wrapped in a top-level entity, but exactly how that happens is context-dependent.
There was a recent effort to make an alternative baked-in wrapping scheme available for the REPL.
None of this is mandated by the language spec, any more than special rules pertaining to sbt build files are defined by the language.
You can define methods like this only in the console, which (behind the scenes) automatically wraps them in an anonymous class for you.
Outside of the console, there's no such luxury.
As a JVM language, Scala cannot truly create any top-level entities other than classes and interfaces.
It does, however, have the notion of a "package object" which creates the illusion of value entites (val, var and def) not enclosed in a class or trait.
See http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html for information on package objects.
You can run code like this directly in Eclipse: use Scala worksheet. IntelliJ IDEA Scala plugin supports it as well.

Issue with using Macros in SBT

Assume you have two SBT projects, one called A and another called B
A has a subproject called macro, that follows the exact same pattern as showed here (http://www.scala-sbt.org/0.13.0/docs/Detailed-Topics/Macro-Projects.html). In other words, A has a subproject macro with a package that exposes a macro (lets called it macrotools). Now both projects, A and B, use the macrotools package (and A and B are strictly separate projects, B uses A via dependancies in SBT, with A using publish-local)
Now, A using A's macrotools package is fine, everything works correctly. However when B uses A macrotools package, the following error happens
java.lang.IllegalAccessError: tried to access method com.monetise.waitress.types.Married$.<init>()V from class com.monetise.waitress.types.RelationshipStatus$
For those wondering, the macro is this one https://stackoverflow.com/a/13672520/1519631, so in other words, this macro is what is inside the macrotools package
This is also related to my earlier question Macro dependancy appearing in POM/JAR, except that I am now using SBT 0.13, and I am following the altered guide for SBT 0.13
The code being referred to above is, in this case, this is what is in B, and A is com.monetise.incredients.macros.tools (which is a dependency specified in build.sbt)
package com.monetise.waitress.types
import com.monetise.ingredients.macros.tools.SealedContents
sealed abstract class RelationshipStatus(val id:Long, val formattedName:String)
case object Married extends RelationshipStatus(0,"Married")
case object Single extends RelationshipStatus(1,"Single")
object RelationshipStatus {
// val all:Set[RelationshipStatus] = Set(
// Married,Single
// )
val all:Set[RelationshipStatus] = SealedContents.values[RelationshipStatus]
}
As you can see, when I use whats commented, the code works fine (the job of the macro is to fill the Set with all the case objects in an ADT). When I use the macro version, i.e. SealedContents.values[RelationshipStatus] is when I hit the java.lang.IllegalAccessError
EDIT
Here are the repos containing the projects
https://github.com/mdedetrich/projectacontainingmacro
https://github.com/mdedetrich/projectb
Note that I had to do some changes, which I forgot about earlier. Because the other project needs to depend on the macro as well, the following 2 lines to disable macro publishing have been commented out
publish := {},
publishLocal := {}
In the build.scala. Also note this is a runtime, not a compile time error
EDIT 2
Created a github issue here https://github.com/sbt/sbt/issues/874
This issue is unrelated to SBT. It looks like the macro from Iteration over a sealed trait in Scala? that you're using has a bug. Follow the link to see a fix.

Moving a package-private class—should I consider that binary incompatible?

Because of an issue with package name aux under Windows, I am moving a helper class within the package hierarchy of my library from
de.sciss.scalainterpreter.aux
to
de.sciss.scalainterpreter
The class is private to the library, i.e. private[scalainterpreter] object Helper.
Now using the Typesafe Migration-Manager, obviously it reports that the change is not compatible:
Found 2 binary incompatibiities
===============================
* class de.sciss.scalainterpreter.aux.Helper does not have a correspondent
in new version
* object de.sciss.scalainterpreter.aux.Helper does not have a correspondent
in new version
But I suspect that if client code does not call into either object, the interfaces are still compatible, and thus I can use a minor version increase to indicate the change, and allow those two versions to be used interchangeably.
Correct?
You are not specifying if Helper was already package private before the move. So I'll treat both cases:
If it was already package private:
I suspect that the migration manager reports an incompatibility only because it must stay conservative: packages are open in scala (like in java), which means that client code might very well define a class package scalainterpreter.
So by moving Helper, you would indeed break that class.
However let's be pragmatic: de.sciss.scalainterpreter.aux is your package (and so should be their sub-packages), and nobody should define their own classes there.
With this additional prerequiste, moving Helper is indeed a binary compatible change toward client scala code.
As for client java code, it's a bit different because even if Helper is package private, its visibility is still public as far as the JVM is concerned, and thus the java compiler will happily let client code access Helper (thus client java code might very well already access Helper, despite it being declared package private).
If it was not package private before the move:
Well, tough luck. Client code could very well already access Helper, and the move will certainly break that. As a side note, you can employ a little trick to make the change source-compatible, but alas not binary-compatible. Just add the following file:
package de.sciss
package object scalainterpreter {
object aux {
val Helper = _root_.de.sciss.scalainterpreter.Helper
}
}
With the above, you can still access Helper as de.sciss.scalainterpreter.aux.Helper, and it still compiles under windows (unlike defining a package aux, which does not compile because of the reserved meaning as a file name).
But again, this is not binary compatible, only source compatible.
It's easy to see how inlining can break client code, since the inlined code essentially bleeds into the client interface. This example really asks for a linkage error; we can experiment and do things like javap | grep Helper, but at some level you have to let scalac do its job.
package lib {
object Lib {
//import util.Helper
#inline def result = Helper.help
}
//package util {
private [lib] object Helper {
#inline def help = "Does this help?"
}
//}
}
Sample innocently bystanding client:
package client
object Test {
import lib.Lib
def main(args: Array[String]) {
println(Lib.result)
}
}
Changing package of package-private class:
$ scala -cp "classes;target" client.Test
Does this help?
apm#halyard ~/tmp/taking-it-private
$ vi lib.scala
apm#halyard ~/tmp/taking-it-private
$ rm -rf classes/*
apm#halyard ~/tmp/taking-it-private
$ smalac -d classes -optimise lib.scala
apm#halyard ~/tmp/taking-it-private
$ smala -cp "classes;target" client.Test
java.lang.ClassNotFoundException: lib.util.Helper$
Javap shows why. [Namely, the call is inlined but it still wants to init the module.]
I haven't followed the discussions, but for example there are links at:
https://github.com/scala/scala/pull/1133
and other discussions on the ML about what expectations about binary compatibility are valid.
https://groups.google.com/forum/?fromgroups=#!topic/scala-internals/sJ-xnWL_8PE
Simply put, no reason why it wouldn't be. Linkage happens around signatures; since the object in question is scoped to the compilation unit, clients cannot (or rather, should not) be using it, and binary compatibility is therefore not an issue.

What are the limitations and walkarounds of Scala interpreter?

What kind of constructs need 'scalac' compile and how to make an equivalent that will work in interpreter?
Edit: I want to use scala instead of python as a scripting language. (with #!/usr/bin/scala)
You ought to be able to do anything in the REPL that you can do in outside code. Keep in mind that:
Things that refer to each other circularly need to be inside one block. So the following can't be entered as-is; you have to wrap it inside some other object:
class C(i : Int) { def succ = C(i+1) }
object C { def apply(i: Int) = new C(i) }
The execution environment is somewhat different, so benchmarking timings will not always come out the same way as if you run them from compiled code.
You enter the execution path a different way; if you want to call a main method, though, you certainly can from inside the REPL.
You can't just cut-and-paste an entire library into the REPL and have it work exactly like the library did; the REPL has a different structure than normal packages do. So drop the "package" declarations during testing.
EDIT: after reading your question again, I have to admit, that I didn't really answer it ;). But maybe it still helps.
I know of two limitations of interpreter (or REPL), when it comes to loading scala files (in order to interactively test them).
You can't load scala files with package definitions in them. REPL complains and does not load all class is the scala file to be loaded. It read that it has to do with the fact that files that are loaded into the REPL are treated as an object . . . which of course can't have any package definitions in them.
REPL is strange (or a little bit unpredictable) when there are class files of loaded scala files on the classpath. Check out this question by myself and especially my 2 last comments to the second answer.
Furthermore there is a problem with circular dependencies, that I don't know a workaround for: Suppose there is a Class A that uses Class B which again needs A to do it's job. Of course you can't define A since there is no definition of B and vice versa. Providing a dummy for one of those doesn't work either:
scala> class A {
| def alterString(s:String) = s
| def printStuff(s:String) = println(alterString(s))
| }
defined class A
scala> class B {
| val prefix = "this is a test: "
| def doJob() = new A() printStuff "1 2 3"
| }
defined class B
scala> class A {
| def alterString(s:String) = new B().prefix + s
| def printStuff(s:String) = println(alterString(s))
| }
defined class A
scala> new B().doJob()
1 2 3
scala>
Although I already provided a newer definition of A, class B still used the one that was present when I defined it.
I think everything in Scala will work from the interpreter as well (which I believe just calls the compiler under the hood anyway).
Do you suspect something to not work? Or is this a trick/interview question (I suppose anything that want to directly interact with the class loader or class files may behave differently in the two environments, but I have no idea really).