graalvm / graalvm-demos

This repository contains example applications to illustrate the different capabilities of GraalVM
http://graalvm.org
Universal Permissive License v1.0
574 stars 153 forks source link

fastr_javaui and slow #7

Closed MartyIX closed 6 years ago

MartyIX commented 6 years ago

Hi,

I have modified com.oracle.truffle.r.fastrjavaui.FastRJavaCmd to generate very simple chart and to print epoch milliseconds after every step it takes:

package com.oracle.truffle.r.fastrjavaui;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import static java.awt.image.BufferedImage.TYPE_INT_RGB;

public class FastRJavaCmd {

    private static final int WIDTH = 700;
    private static final int HEIGHT = 500;

    public static void main(String[] args) {

        System.out.println("1) " + System.currentTimeMillis());

        Context context = Context.newBuilder("R").allowAllAccess(true).build();

        System.out.println("2) " + System.currentTimeMillis());

        // This R function opens FastR graphics device passing it Graphics2D object,
        // then it plots the graph and closes the device
        String src =
                "function(g, w, h, clustersCount, x, y) { " +
                        "   grDevices:::awt(w, h, g);" +
                        "   cars <- c(1, 3, 6, 4, 9);" +
                        "   print(plot(cars));" +
                        "   dev.off();" + // # Turn off device driver (to flush output to png)
                        "   NULL;" +
                        "}";

        Value showPlot = context.eval("R", src);

        System.out.println("3) " + System.currentTimeMillis());

        // Instead of drawing to a component, we use BufferedImage for headless testing
        // Note: one can achieve this with "png" built-in directly in R,
        // this is only example of what can be done
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_RGB);

        System.out.println("4) " + System.currentTimeMillis());

        Graphics2D graphics = (Graphics2D) image.getGraphics();

        System.out.println("5) " + System.currentTimeMillis());

        graphics.setBackground(new Color(255, 255, 255));

        System.out.println("6) " + System.currentTimeMillis());

        graphics.clearRect(0, 0, WIDTH, HEIGHT);

        System.out.println("7) " + System.currentTimeMillis());

        // The MAGIC happens HERE: we invoke R plotting code and pass it graphics object
        showPlot.execute(graphics, WIDTH, HEIGHT, 4, "Sepal.Width", "Sepal.Length");

        System.out.println("8) " + System.currentTimeMillis());

        // Save the image to file
        String dest = System.getProperty("fastrjavaui.dest", "test.png");

        System.out.println("9) " + System.currentTimeMillis());

        try {
            ImageIO.write(image, "png", new File(dest));
            System.out.println("10) " + System.currentTimeMillis());

        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("SUCCESS");
    }
}

The output on my compute is:

1) 1526451609161
2) 1526451609371
3) 1526451618500   <<<< It is slow here
4) 1526451618537
5) 1526451618610
6) 1526451618610
7) 1526451618611
NULL
8) 1526451620894
9) 1526451620894
10) 1526451621052
SUCCESS
DONE

real    0m12,367s
user    0m34,820s
sys 0m1,150s

What might be the performance bottleneck?

Environment:

Regards, Martin

shelajev commented 6 years ago

hi, @MartyIX, evaluating a script for the first time is going to take some time. It needs to load the script, load the language standard library, evaluate all that and so on. It does quite a bit of work there, so I think it's normal that it takes some time. If you eval different scripts in the same context it should be faster. Executing the scripts will eventually allow the JIT compiler compile the code efficiently.

Also, can you please elaborate what you mean by the bottleneck?

MartyIX commented 6 years ago

@shelajev I see.

Also, can you please elaborate what you mean by the bottleneck?

Well, the bottleneck is the fact that it compiles too much every time I run the program. And 12 seconds is quite a lot for me. I would like to get rid of this overhead. Can compilation to native code help me here?

Originally, we had a python script to generate charts for us. However, I wasn't happy about having multiple programming languages in our project as it complicates many things, so we rewrote the plotting script to Java. Then I have encountered news about Graal and I was happy, that I'll have only Java code with R script to generate plots. But I need it to be quick. So that's what I'm solving right now to make the picture complete. :-) Anyway, I don't want to complain, it's just I don't know too much about inner workings of Graal.