diff --git a/teavm-samples/teavm-samples-benchmark/README.md b/teavm-samples/teavm-samples-benchmark/README.md
new file mode 100644
index 000000000..7cc449341
--- /dev/null
+++ b/teavm-samples/teavm-samples-benchmark/README.md
@@ -0,0 +1,23 @@
+TeaVM, GWT, HotSport JBox2D Benchmark
+=====================================
+
+Compares the speed of execution on a complex [JBox2D](http://www.jbox2d.org/) CPU extensive
+computation. JavaScript produced by TeaVM and GWT can be compared by running
+
+```
+$ mvn clean install
+```
+
+then just open the generated HTML versions
+
+```
+$ open target/teavm-samples-benchmark-*-SNAPSHOT/index.html
+```
+
+In addition to that one can run the same demo with classical HotSpot virtual machine. Just try:
+
+```
+$ mvn -Pfx exec:java
+```
+
+
diff --git a/teavm-samples/teavm-samples-benchmark/pom.xml b/teavm-samples/teavm-samples-benchmark/pom.xml
index bbf7e22d0..a0851d244 100644
--- a/teavm-samples/teavm-samples-benchmark/pom.xml
+++ b/teavm-samples/teavm-samples-benchmark/pom.xml
@@ -33,16 +33,19 @@
org.teavm
teavm-classlib
${project.version}
+ provided
org.teavm
teavm-jso
${project.version}
+ provided
org.teavm
teavm-dom
${project.version}
+ provided
org.jbox2d
@@ -54,6 +57,7 @@
jbox2d-library
2.2.1.1
sources
+ provided
com.google.gwt
@@ -61,6 +65,16 @@
2.7.0
provided
+
+ com.dukescript.canvas
+ html5-canvas
+ 0.7.2
+
+
+ org.netbeans.html
+ net.java.html.boot
+ 1.1
+
@@ -77,43 +91,69 @@
- org.teavm
- teavm-maven-plugin
- ${project.version}
+ maven-jar-plugin
+ 2.5
-
- web-client
- prepare-package
-
- build-javascript
-
-
- ${project.build.directory}/generated/js/teavm
- org.teavm.samples.benchmark.teavm.BenchmarkStarter
- SEPARATE
- true
- true
-
-
+
+ prepare-package
+
+ jar
+
+
+
+
+ org.teamvm.samples.benchmark.htmljava.BenchmarkStarter
+ true
+ lib/
+ false
+
+
+
+ **/gwt/*
+ **/teavm/*
+
+
+
- org.codehaus.mojo
- gwt-maven-plugin
- 2.7.0
-
-
-
- compile
-
-
- 9
-
- - org.jbox2d:jbox2d-library
-
-
-
-
+ org.teavm
+ teavm-maven-plugin
+ ${project.version}
+
+
+ web-client
+ prepare-package
+
+ build-javascript
+
+
+ ${project.build.directory}/generated/js/teavm
+ org.teavm.samples.benchmark.teavm.BenchmarkStarter
+ SEPARATE
+ false
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ gwt-maven-plugin
+ 2.7.0
+
+
+
+ compile
+
+
+ 9
+
+ - org.jbox2d:jbox2d-library
+
+
+
+
org.apache.maven.plugins
@@ -127,10 +167,47 @@
org.apache.maven.plugins
maven-source-plugin
+
+ org.netbeans.html
+ html4j-maven-plugin
+ 1.1
+
+
+
+ process-js-annotations
+
+
+
+
org.apache.maven.plugins
maven-javadoc-plugin
+
+
+ fx
+
+
+ org.netbeans.html
+ net.java.html.boot.fx
+ 1.1
+ runtime
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.3.2
+
+ org.teavm.samples.benchmark.htmljava.BenchmarkFX
+
+
+
+
+
+
\ No newline at end of file
diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/htmljava/BenchmarkFX.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/htmljava/BenchmarkFX.java
new file mode 100644
index 000000000..780cefcd2
--- /dev/null
+++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/htmljava/BenchmarkFX.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2015 Jaroslav Tulach.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.teavm.samples.benchmark.htmljava;
+
+import net.java.html.boot.BrowserBuilder;
+
+public final class BenchmarkFX {
+ private BenchmarkFX() {
+ }
+
+ public static void main(String... args) {
+ BrowserBuilder.newBrowser().loadPage("fx.html")
+ .loadClass(BenchmarkStarter.class)
+ .invoke("main")
+ .showAndWait();
+ System.exit(0);
+ }
+
+}
diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/htmljava/BenchmarkStarter.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/htmljava/BenchmarkStarter.java
new file mode 100644
index 000000000..a949a7d8a
--- /dev/null
+++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/htmljava/BenchmarkStarter.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2015 Jaroslav Tulach.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.teavm.samples.benchmark.htmljava;
+
+import com.dukescript.api.canvas.GraphicsContext2D;
+import com.dukescript.api.canvas.Style;
+import com.dukescript.canvas.html.HTML5Graphics;
+import java.util.Timer;
+import java.util.TimerTask;
+import net.java.html.BrwsrCtx;
+import net.java.html.js.JavaScriptBody;
+import org.jbox2d.collision.shapes.CircleShape;
+import org.jbox2d.collision.shapes.PolygonShape;
+import org.jbox2d.collision.shapes.Shape;
+import org.jbox2d.collision.shapes.ShapeType;
+import org.jbox2d.common.Vec2;
+import org.jbox2d.dynamics.Body;
+import org.jbox2d.dynamics.Fixture;
+import org.teavm.samples.benchmark.Scene;
+
+public final class BenchmarkStarter {
+ private BenchmarkStarter() {
+ }
+
+ private static final Timer TIMER = new Timer("Make Step");
+ private static final Scene scene = new Scene();
+ private static double startMillisecond;
+ private static int currentSecond;
+ private static double timeSpentCalculating;
+ private static BrwsrCtx ctx;
+
+ public static void main(String[] args) {
+ startMillisecond = System.currentTimeMillis();
+ ctx = BrwsrCtx.findDefault(BenchmarkStarter.class);
+ makeStep();
+ }
+
+ static void makeStep() {
+ ctx.execute(new Runnable() {
+ @Override
+ public void run() {
+ makeStep0();
+ }
+ });
+ }
+
+ private static void makeStep0() {
+ double start = System.currentTimeMillis();
+ scene.calculate();
+ double end = System.currentTimeMillis();
+ int second = (int)((System.currentTimeMillis() - startMillisecond) / 1000);
+ if (second > currentSecond) {
+ publishResults(second, timeSpentCalculating);
+ timeSpentCalculating = 0;
+ currentSecond = second;
+ }
+ timeSpentCalculating += end - start;
+ render();
+ TIMER.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ makeStep();
+ }
+ }, scene.timeUntilNextStep());
+ }
+
+ private static void render() {
+ GraphicsContext2D context = HTML5Graphics.getOrCreate("benchmark-canvas");
+ context.setFillStyle(new Style.Color("white"));
+ context.setStrokeStyle(new Style.Color("grey"));
+ context.fillRect(0, 0, 600, 600);
+ context.save();
+ context.translate(0, 600);
+ context.scale(1, -1);
+ context.scale(100, 100);
+ context.setLineWidth(0.01);
+ for (Body body = scene.getWorld().getBodyList(); body != null; body = body.getNext()) {
+ Vec2 center = body.getPosition();
+ context.save();
+ context.translate(center.x, center.y);
+ context.rotate(body.getAngle());
+ for (Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture.getNext()) {
+ Shape shape = fixture.getShape();
+ if (shape.getType() == ShapeType.CIRCLE) {
+ CircleShape circle = (CircleShape)shape;
+ context.beginPath();
+ context.arc(circle.m_p.x, circle.m_p.y, circle.getRadius(), 0, Math.PI * 2, true);
+ context.closePath();
+ context.stroke();
+ } else if (shape.getType() == ShapeType.POLYGON) {
+ PolygonShape poly = (PolygonShape)shape;
+ Vec2[] vertices = poly.getVertices();
+ context.beginPath();
+ context.moveTo(vertices[0].x, vertices[0].y);
+ for (int i = 1; i < poly.getVertexCount(); ++i) {
+ context.lineTo(vertices[i].x, vertices[i].y);
+ }
+ context.closePath();
+ context.stroke();
+ }
+ }
+ context.restore();
+ }
+ context.restore();
+ }
+
+ @JavaScriptBody(args = { "second", "timeSpentCalculating" }, body =
+ "var resultTableBody = document.getElementById('result-table-body');\n" +
+ "var row = document.createElement(\"tr\");\n" +
+ "resultTableBody.appendChild(row);\n" +
+ "var secondCell = document.createElement(\"td\");\n" +
+ "row.appendChild(secondCell);\n" +
+ "secondCell.appendChild(document.createTextNode(second));\n" +
+ "var timeCell = document.createElement(\"td\");\n" +
+ "row.appendChild(timeCell);\n" +
+ "timeCell.appendChild(document.createTextNode(timeSpentCalculating));\n"
+ )
+ private static native void publishResults(int second, double time);
+}
diff --git a/teavm-samples/teavm-samples-benchmark/src/main/resources/org/teavm/samples/benchmark/htmljava/fx.html b/teavm-samples/teavm-samples-benchmark/src/main/resources/org/teavm/samples/benchmark/htmljava/fx.html
new file mode 100644
index 000000000..f37320506
--- /dev/null
+++ b/teavm-samples/teavm-samples-benchmark/src/main/resources/org/teavm/samples/benchmark/htmljava/fx.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+ HotSpot/JavaFX jbox2d benchmark
+
+
+ HotSpot/JavaFX performance
+
+
+
+
+
+
+ Second |
+ Time spent computing, ms |
+
+
+
+
+
+