2
votes

I have written a javascript program which plots the Mandelbrot set with the normal pretty colours approaching the boundary. I was planning on adding a zoom function next but it is far far too slow for this to be sensible.

I have posted the most important portion of the code here:

while (x * x < 2 && y * y < 2 && iteration < max_iteration) {
            xtemp = (x * x) - (y * y) + xcord;
            y = (2 * x * y) + ycord;
            x = xtemp;
            iteration = iteration + 1;
        }

and have linked to a jsfiddle with the whole page here: http://jsfiddle.net/728dn2m0/

I have a few global variables which I could take into the main loop but that would result in additional calculations for every single pixel. I read on another SO question that an alternative to the 1x1 rectangle was to use image data but the performance difference was disputed. Another possibility would be rewriting the while statement as some other conditional loop but I'm not convinced that would give me the gains I'm looking for.

I'd consider myself a newbie so I'm happy to hear comments on any aspect of the code but what I'm really after is something which will massively increase performance. I suspect I'm being unreasonable in my expectations of what javascript in the browser can manage but I hope that I'm missing something significant and there are big gains to be found.

Thanks in advance, Andrew

2
As there is no specific problem in the strictest sense, the question might be more suitable for code review. - Codor
I'm happy to move it if that would be better. Is it possible to move a question or do I need to create a new question and somehow delete this one? - user1977132
My remark was more a suggestion. I checked the jsfiddle and I am a bit surprised on the performance; I noticed that your escape condition is not what is usually done; I think it should be x*x+y*y<2 instead of x*x < 2 && y*y<2. - Codor
I've tried changing the escape condition as you've suggested but there's no change in performance. This from wikipedia: "Because no complex number with a real or imaginary part greater than 2 can be part of the set, a common bailout is to escape when either coefficient exceeds 2." That's why I coded the escape condition as two independent tests. I'm at GMT+7 so am about to go to bed I'll not get to reply again for about another 17 hours. I haven't lost interest! - user1977132
@user1977132: "either coefficient exceeds 2" is (x < 2 && y < 2). - karatedog

2 Answers

1
votes

Using setInterval as an external loop construct slows the calculation down. You set it to 5 ms for a single pixel, however the entire Mandelbrot map calculation can be done within 1 second. So a single call to your function draws a pixel very quickly and then waits about the 99.99% of that 5 milliseconds.

I replaced

if (m<=(width+1))

with

while (m<=(width+1))

and removed the setInterval.

This way the entire calculation is done in one step, without refresh to the screen and without using setInterval as an external loop construct. I forked your script and modified it: http://jsfiddle.net/karatedog/2o4gjrv2/6/

In the script I modified the bailout condition from (x*x < 2 && y*y < 2) to (x < 2 && y < 2) just as I suggested in a previous comment and revealed some hidden pixel, check the difference!

0
votes

I had indeed missed something significant. The timer I had used in order to prevent the page hanging while the set was plotted was limiting the code to one pixel every 5 milliseconds, in other words 200 pixels per second. Not clever!

I am now plotting one line at a time and it runs a lot better. Not yet real time but it is a lot quicker.

Thanks for the ideas. I will look into the escape condition to see what it should be.

A new jsfiddle with the revised code is here: http://jsfiddle.net/da1qyh9y/

and the for statement I've added is here:

function main_loop() {
if (m<=(width+1)) {
    var n;
    for (n=0; n<height; n=n+1) {