Image Processing Example - PNWScala
The following example is based on the miniboxing presentation at PNWScala. A huge thanks to Thomas Lockney and the PNWScala organizers for the wonderful conference and the confreaks guys who recorded the presentation!
This page will guide you through the steps necessary to run the example in the presentation. The pureimage library is located at github.com/stephenjudkins/pureimage. The mock-up used for the presentation is located at github.com/VladUreche/image-example.
To start, clone the pureimage mock-up:
$ git clone https://github.com/VladUreche/image-example.git
Cloning into 'image-example'...
...
$ cd image-example
Let’s generate the Eclipse project files to load the project in the IDE:
$ sbt eclipse
[info] Loading global plugins from /home/sun/.sbt/0.13/plugins
...
[info] Done updating.
[info] Successfully created Eclipse project files for project(s):
[info] image-example
Cool. Now, all you need is the latest Scala IDE for Eclipse to load the project. Please use a version for Scala 2.11, in order to stay compatible with the rest of the project. Now, to load the project:
File
>Import ...
>General
>Existing Projects into Workspace
- point Eclipse to the
image-example
directory, selectimage-example
and hitFinish
You should see the project in Eclipse:

Open Test.scala
from package image.example
, located in src/main/scala
, and run it:

On my laptop, I got the following times:
Operation took 4192 milliseconds.
Operation took 4957 milliseconds.
Operation took 4755 milliseconds.
Operation took 3969 milliseconds.
Operation took 4073 milliseconds.
The miniboxing plugin generated a couple of warnings during compilation:

One such warning is:
The class image.example.Pixel would benefit from miniboxing type parameter Repr, since it is
instantiated by a primitive type.
So let’s go in and fix that. Open Pixel.scala
and mark the type parameter Repr
of class Pixel
by @miniboxed
:
abstract class Pixel[@miniboxed Repr: Manifest] {
def r(t: Repr): Double // red
def g(t: Repr): Double // green
def b(t: Repr): Double // blue
def a(t: Repr): Double // alpha
def pack(r: Double, g: Double, b: Double, a: Double): Repr
// to allow Image to build an array:
implicit def manifest = implicitly[Manifest[Repr]]
}

We can fix the other 8 warnings that appear and recompile. Surprisingly, after compiling again, we get an error:
The method map in class ImageImpl overrides method map in class Image therefore needs to
have the follwing type parameters marked with @miniboxed: type Repr2.

This is because we added the @miniboxed
annotation to method map
in Image
:
abstract class Image[Repr: Pixel] {
def width: Int
def height: Int
def apply(x: Int, y: Int): Repr
def map[@miniboxed Repr2: Pixel](f: Image[Repr] => Generator[Repr2]): Image[Repr2]
}
but did not add the annotation to method map
in ImageImpl
, which extends Image
:
private class ImageImpl[Repr: Pixel](val width: Int, val height: Int) extends Image[Repr] {
...
def map[Repr2: Pixel](f: Image[Repr] => Generator[Repr2]): Image[Repr2] = {
...
}
}
Let’s fix that:
private class ImageImpl[Repr: Pixel](val width: Int, val height: Int) extends Image[Repr] {
...
def map[@miniboxed Repr2: Pixel](f: Image[Repr] => Generator[Repr2]): Image[Repr2] = {
...
}
}
If we recompile, the error is gone, but we get another batch of 26 warnings
:

Let’s try to run the program now, despite the warnings:

So by adding a couple of annotations, we just shaved off one quarter of the running time:
Operation took 3082 milliseconds.
Operation took 2998 milliseconds.
Operation took 3017 milliseconds.
Operation took 2535 milliseconds.
Operation took 2615 milliseconds.
Maybe this miniboxing thing is actually worth it…
Let’s now address all the warnings. But let’s be smart about it:
- go to
Project
>Properties
(if that’s disabled, make sure theimage-example
project is selected) - in the window go to
Scala Compiler
and add-P:minibox:mark-all
to theAdditional command line parameters
field.
As explained in the command line options, the -P:minibox:mark-all
flag will mark all type parameters with @miniboxed
automatically.


Recompile and you should not see any more warnings. Now let’s run again:

Operation took 1346 milliseconds.
Operation took 1187 milliseconds.
Operation took 1178 milliseconds.
Operation took 1094 milliseconds.
Operation took 1163 milliseconds.
Wow, that’s four times faster than our initial running time. That’s what miniboxing can do for numeric-intensive applications!
Comments
Comments are always welcome! But to make the best use of them, please consider this:
- If you have questions or feedback regarding the content of this page, please leave us a comment!
- If you have general questions about the miniboxing plugin, please ask on the mailing List.
- If you found a bug, please let us know on the github issue tracker.
Thanks! Looking forward to your messages!
comments powered by Disqus