What's the correct posture to run scala script

I wrote the scala script, and run it from command line with “scala script.sc”.
This is slow. I have tested it, for the same task, perl run 2 second, ruby 3 second, scala 4 second. I think for a script the parser starts up too slow.
I tried to use “scalac script.sc” to compile it, but without an entry function it can’t be compiled.
So may I ask how to run scala script (most time from command line) more quickly?

Thank you.

I don’t think it is worth it for a small script, but the best way to make it fast would be to use GraalVM to create a native image… but really, that probably would require a lot just for saving a couple of seconds.

1 Like

scala-cli does a pretty good job with making all but the first run fast:

% echo 'println("hi there")' > script.sc
% time scala-cli script.sc
Compiling project (Scala 3.0.2, JVM)
Compiled project (Scala 3.0.2, JVM)
hi there
scala-cli script.sc  3.75s user 0.70s system 23% cpu 19.285 total
% time scala-cli script.sc
hi there
scala-cli script.sc  1.53s user 0.27s system 99% cpu 1.810 total
%

scala-cli also supports Scala Native with --native, which gets it down to 1.1s on my machine.

scala-cli is pretty new and still under very active development, so you might hit some bumps, but its future looks bright.

Perhaps eventually it will support the GraalVM route that Luis mentioned: Generate GraalVM native images from package sub-command · Issue #298 · VirtusLab/scala-cli · GitHub

2 Likes

Thank you Seth. This is a great tool. for now I think it could be having some bugs.

$ time scala-cli -q scala-set.sc 
(send,21835)
(message,19172)
(unsubscribe,16515)
(2021,15340)
(list,14130)
(mailing,13025)
(file,12323)
(mail,12052)
(jan,11759)
(email,10633)
(flink,10238)
(pm,9855)
(group,9496)
(code,9482)
(problem,9458)
(data,9291)
(received,8714)
(2022,8621)
(return,8505)
(2020,8409)

real	2m6.948s
user	2m7.423s
sys	0m0.425s

$ time scala scala-set.sc 
(send,21835)
(message,19172)
(unsubscribe,16515)
(2021,15340)
(list,14130)
(mailing,13025)
(file,12323)
(mail,12052)
(jan,11759)
(email,10633)
(flink,10238)
(pm,9855)
(group,9496)
(code,9482)
(problem,9458)
(data,9291)
(received,8714)
(2022,8621)
(return,8505)
(2020,8409)

real	0m5.503s
user	0m7.662s
sys	0m0.234s

$ cat scala-set.sc 
import scala.io.Source

val li = Source.fromFile("words.txt").getLines()
val set_sw = Source.fromFile("stopwords.txt").getLines().toSet
val hash = scala.collection.mutable.Map[String,Int]()


for (x <- li) {
    if ( ! set_sw.contains(x) ) {
      if (hash.contains(x)) hash(x) += 1 else hash(x) = 1
    }
}

val sorted = hash.toList.sortBy(-_._2)
sorted.take(20).foreach {println}

This is not the first time to run scala-cli certainly.

And the test sets could be found here.

Thanks.

There are a few ways on Scala 2. The second invocation of -save is fast, as is running from the jar.

➜  cat hello.scala

object Test extends App {
  val who = args.headOption.getOrElse("world")
  println {
    s"hello, $who!"
  }
}
➜  scala hello.scala
hello, world!
➜  scala hello.scala Seth
hello, Seth!
➜  scala -save hello.scala Seth
hello, Seth!
➜  scala -save hello.scala Seth
hello, Seth!
➜  scala -save hello.scala Martin
hello, Martin!
➜  rm hello.jar
➜  scalac -d myapp.jar hello.scala
➜  scala myapp.jar Lukas
hello, Lukas!
➜  rm myapp.jar
➜  cat hello.sc
val who = args.headOption.getOrElse("world")
println {
  s"hello, $who!"
}
➜  scala -save hello.sc Guillaume
hello, Guillaume!
➜  scala -save hello.sc Jamie
hello, Jamie!
➜  scalac -Xscript Hi hello.sc
➜  ls Hi.class
Hi.class
➜  scalac -Xscript Hi -d hi.jar -Xmain-class Hi hello.sc
➜  scala hi.jar Nicolas
hello, Nicolas!
➜  scalac -Xscript Hi -d hi.jar hello.sc
➜  scala hi.jar Nicolas
hello, Nicolas!
1 Like