Sunday, 4 November 2012

HTML5 Canvas Performance

I've been doing quite a lot of development in ClojureScript+Clojure recently, specifically working with the HTML5 Canvas, WebGL and the various rendering libraries for these.

I'm essentially working on a 2D application with a combination of heavy server-side calculation and real-time canvas updates - on a frame by frame basis.

I was originally working with the fantastic three.js library but fancied having a go at doing direct Canvas rendering; if only because I'm a purist at heart and like to use as much of my own code as I can.

Anyway, after testing performance with Safari (my typical daily browser of choice) I was getting fairly slow rendering speeds, so of course I tried Chrome and Firefox to see how they performed. The following is the timings for the first 10 frames. Each frame is drawing 1000 objects composed of 3 vertices each.

Safari 6.0.1


439ms
433ms
435ms
436ms
429ms
431ms
436ms
435ms
444ms
435ms

Chrome 22

72ms
58ms
50ms
49ms
50ms
53ms
48ms
48ms
52ms
51ms

Firefox 16

192ms
206ms
169ms
186ms
167ms
164ms
186ms
196ms
187ms
172ms

Conclusion

It seems Chrome is doing more hardware acceleration than the other platforms and Safari has the most disappointing performance at all.

I'm at a crossroads at the moment - I'm tempted to move to Haskell to do what I want - I would fully expect to get rendering speeds in the 1-5ms range. 

I shall continue my adventures...


Monday, 8 October 2012

Cave building in Clojure+Clojurescript

I'm still messing around with Clojure and ClojureScript, trying to find the sweet spot of development as far as development environment and toolkits go.

I'm trying to get some performant Html5 canvas usage, so I've been tinkering with KineticJS recently. I've been struggling to get real-time (or near real-time) graphics so far without resorting to WebGL - which just feels like cheating. Surely canvas is hardware accelerated by the browser and should be fast enough?

So, this evening I put together a Compojure back-end with a single web service return JSON data. This uses a simple cave generating algorithm of mine which hopes to randomly produce realistic looking caves. It randomises every block, then uses smoothing, and finally adds some random shafts.

This JSON is then consumed by some ClojureScript client side code using Google Closure and KineticJS. Screenshot below:


So, what are my thoughts?

I'm disappointed in the rendering performance; I'm guessing I must be doing something wrong.

So, next step WebGL I wonder? I'm trying very hard to embrace the web development revolution - even though part of me still wants to write good old fashioned native code.

Sunday, 23 September 2012

Off on a tangent - ClojureScript

Okay, so I left my last post saying I wanted to do a flight simulator.

Well in my usual roundabout way I've been on a journey, I discovered ClojureScript (again, but did something useful with it this time) and attempted to use it in some way.

I also had a bit of a reminiscing moment about Elite, the classic BBC game. I managed to download some .X models for them and wanted to render them using ClojureScript.

The final piece was the incredibly powerful Three.js javascript library, this thing does amazing stuff with 3D graphics either on a HTML5 Canvas or using WebGL.

After a few hours I had a Compojure back end, a ClojureScript UI which showed a spinning Cobra MKIII - screenshot below:

So, my thoughts?

Well, ClojureScript is very nice, but the extra step of compiling down to JS is annoying and slows me down. Also, the syntax is very similar but there are enough differences to mean I can't translate seamlessly between it and real Clojure.

Source is here.

Monday, 27 August 2012

Okay..

After doing a whole bunch of messing around in O'Caml I've come to the conclusion that getting a working environment for 2D/3D development is just too much like hard work.

I've since been evaluating RubyGame (which is nice), but not overly happy with the speed, although it's very rapid for developing.

I've also dug out BlitzMax - now I bought a license for this a few years ago and did a lot of tinkering in it. It's a dialect of Basic but is amazingly easy to get things moving about on screen and there are a ton of game related libraries for it. However, the puritan in me doesn't like the fact it's not a standard language and the fact it's commercial. It is cross platform though, which is a nice bonus.

As usual, I go round in circles trying to make a decision - but choosing the language and using something new is often more interesting to me than the end result!

Let's see where this goes.

Thursday, 9 August 2012

A flight simulator

Okay, I've been digging through my old books and lamenting the loss of a few I threw away due to running out of space. Of those I threw away a few years ago were these:


  • A book on 80286 assembly language - Oh, how powerful was that processor! Search as I might I can't find it anywhere, although I know I bought my copy from Farnell (well, actually my father did, which means I was early teens).
  • Ralf Brown's PC Interrupts - This was essential to any DOS coder, this was jam packed with data. But as a big book with no current use it had to go. Here is a pic below of the front cover

Anyway, enough reminiscing. I did have a point!

Anyway, where were we?

I came across this book while looking through the bookcase:



Now, this is intriguing, but it's hard going. It covers rendering all the way up to polygons on a pixel by pixel basis - there was no blitting or 3D graphics cards back then! Also, there is great swathes of C++ code, hugely verbose but undoubtedly extremely fast for the time.

So, I've been having some thoughts. I really fancy the idea of doing my own flight simulator, maybe using the book as inspiration and stimulation. I do actually rather like the idea of being retro and doing pixel blitting, Bresenham's algorithm et al.

I don't want to use some old style imperative language though, I want to use something modern and functional (preferably).

Language Choice


So, what languages could I choose and what are the pros and cons?

Language Positives Negatives
ClojureJVM libraries, Java2D, Concurrency, funPoor debugging, slow?
F#Great IDE, performance, syntaxMono VM is slow, IDE is Windows only
HaskellPerformance, native binaryIs a pure language a good idea for such a stateful project?
O'CamlPerformance, native binarySingle threaded
ScalaGood compiler, performance, Java2D, JVM libraries, very similar to original C++Too similar to the original C++?!!

Now, what about some more fun languages to do this in? Here are some scripting choices, although they do have a performance hit of course.

Language Positives Negatives
PythonPygame, librariesNot functional
RubyNice syntax, librariesNot functional

Now, if I want something quickly then I suspect Ruby is the way to go as I'm more familiar with the syntax than python (despite it being better supported for this sort of thing).

I think Haskell might be too much of a challenge, and I think Scala will be too easy. I'm also thinking that as it's effectively a 'game' type application that a natively compiled languages might be best - although I'm quite aware that both O'Caml and Haskell have a VM.

Okay, I've make a decision - O'Caml it is. It natively compiles, it's fast and I like the syntax. I'm not overly familiar with the libraries so it'll be a fun exercise. Also, it's a functional language but I can if I feel naughty use mutable variables (or even OO).

Wednesday, 25 July 2012

Clojure poor performance - why?

The only glaring result from my functional language benchmarking (a strong word for what I did in all honesty) is the Clojure result.

Now, let me be upfront here - I love Clojure. I've always loved the lisp family of languages, but always found Common Lisp a little clunky sometimes (although very quick). Clojure is great, it has all the benefits of the JVM, but with modern data structures and some good concurrency constructs. It's functional, immutable and has macros support (as you'd expect).

It's also dynamic, with lots of boxing going on if you're not careful. I thought this was the reason for the slowdown, but after doing a lot of optimising using type hints and the new numerics supports in 1.3 I got very little improvement in performance. I even dropped records and used maps, even though it's counter-intuitive...but all to no avail.

I thought it could be the trig and maths at fault, so the first thing I tried was to use memoize to cache the results of the travel calculations. However, this made only a small improvement.

It was when I commented out the various trig calls that I got a change in the results. It went down from 51s to 10s.

Right.

So I started to do some digging and came across the following:

https://blogs.oracle.com/jag/entry/transcendental_meditation
http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html

These seems to suggest it's not using the hardware fcos/fsin some/most of the time - that to achieve the JVM required accuracy software implementations are used.

Do some googling and you'll find many more articles on this.

So beware!

I'm still not sure why Scala doesn't seem to suffer? Maybe the libraries have workarounds?

But it gives me confidence that Clojure is close enough performance wise to be practical for my purposes.

Functional languages - A performance comparison


Okay, I've decided to write a blog - one of those things I've been meaning to do for longer than I can remember. Now this isn't going to be the most exciting blog in the world, but you never know - it might well be useful to somebody.

I'm going to start off with a little project I did recently. I'm into functional programming, but am acutely aware that there is a performance penalty associated with anything immutable and/or recursive. In recent years there has been substantial effort in optimising compilers and VMs for functional languages, and performance is approaching that of more conventional imperative mutable languages.

Now, I've got a whole brain full of ideas I want to try out, but just for fun you understand. However, as a man who feels fluent in several languages and competent in at least a dozen more, I've decided to try and pick one and try and master it fully. Of course, this won't happen, but it's at least a worthy goal.

Now, there are various metrics about a language and platform:

  • Performance
  • Syntax including conciseness and expressiveness
  • Libraries and platform support

In this post I'm going to tackle the first item. There is the famous Computer Language Benchmarks Game, but this hampers functional languages in certain ways, for example it doesn't allow lazy evaluation.

So, instead I put together my own little benchmark. Now, I admit this is fairly simple and it doesn't use some functional features such as currying or lazy evaluation; however it does use recursion and immutability. Also, I've tried to keep the code idiomatic but still following the same basic algorithm each time. It would be possible to do optimisations in each language or be more idiomatic (by modifying the algorithm) but I avoided this.

The problem to solve is a simple one - there are 10 people with 500 places to visit (this is stored in a CSV file), however they can only visit 10 each. I use a brute force method of finding possible journeys, basically recurse through each resource in turn, then choose the 10 nearest places in turn (using the Haversine formula). I then fold this to get a total travel distance, which I ensure is the same across each implementation. This makes good use of recursion, some heavy lifting with fold/map, some file access and a bit of simple trig.

The source is on github.

Results


Haskell
-------
Lines: 83


1 - 0m0.025s
10 - 0m0.090s
100 - 0m0.773s
1000 - 0m7.677s
10000 - 1m17.865s



F# (Mono)
---------
Lines: 83


1 - 0m0.155s
10 - 0m0.378s
100 - 0m2.641s
1000 - 0m25.487s (SGen - 0m19.399s)
10000 - 4m9.381s (.NET in VM 1m28.366)


F# (.NET)
---------
Lines: 83


1 - 0m0.123s
10 - 0m0.199s
100 - 0m.948s
1000 - 0m8.39s
10000 - 1m23.619s



Scala
-----
Lines: 82


1 - 0m1.028s
10 - 0m1.375s
100 - 0m2.253s
1000 - 0m11.959s
10000 - 1m44.669s


Clojure
-------
Lines: 88


1 - 0m1.511s
10 - 0m2.317s
100 - 0m7.022s
1000 - 0m51.575s
10000 - 8m50.565s


OCaml
-----
Lines: 88


1 - 0m0.015s
10 - 0m0.118s
100 - 0m1.162s
1000 - 0m11.162s
10000 - 1m51.518s


Some very interesting results, some things I've noticed:
  • Haskell is the fastest but Scala seems to be accelerating in performance. HotSpot compiler maybe?
  • The F# performance is a lot better on the real VM and on the new SGen GC.
  • Clojure is strangely slow, but I'll cover why I think this is the case in a later blog.
  • The native compiled languages show a very quick 1 iteration time.
  • Clojure has the longest 1 iteration time, but this is to be expected.
  • They are all very similar on number of lines, however each implementation is very similar in code.
  • The memory usage was significantly (as in 1/100) lower for Haskell and O'Caml - although I didn't measure this precisely.

Conclusion

I'm not sure there is one, all the languages I tested are close enough to be interchangeable with the exception of Clojure (which I'm going to cover in a different post).

Which language did I find easiest? F# - the IDE and debugger makes such a difference.
The hardest? Haskell, but once I'd got it to compile it worked first time.

Table & Graph

To make it clear, here is a quick graph I've put together a table (the top number is iterations) and a graph.






1
10
100
1000
10000
Haskell
0.025
0.090
0.773
7.677
77.865
F# .NET
0.123
0.199
0.948
8.39
83.619
Scala
1.028
1.375
2.253
11.959
104.669
O’Caml
0.015
0.118
1.162
11.162
111.518
F# Mono
0.155
0.378
2.641
25.487
249.381
Clojure
1.511
2.317
7.022
51.575
530.565