Is there a delay moving between libraries in Python?
<p>So recently I decided to write a program to draw the mandelbrot set using turtle, and it works very well, except for one thing; it's quite slow, and it slows down as it draws. The way it draws is, if I remember correctly, as follows:</p>

<pre><code>def drawpoint(x,y,colour):
    t.color(colour)
    t.setpos(x,y)
    t.down()
    t.forward(1)
    t.up()
</code></pre>

<p>and the program in general calculates the point (using <code>math</code> (specifically its trigonometry) and its colour and then draws it.</p>

<p>I can't work out why it's so slow, because it's not exactly an astonishing set of calculations. I'm fairly sure it's to do with <code>turtle</code>, and I was wondering if:</p>

<p>a) Python is slowed down by moving between <code>math</code> and <code>turtle</code> <br />
b) Turtle slows down as you draw more points <br />
c) Something else entirely <br /></p>

<p>Is it any of these, and if so, how can I speed it up?</p>

<p>Since you didn't give a clock value to <strong><em>quite slow</em></strong>, I have to make assumptions.  (And I don't disagree with PM 2Ring that turtle.py may not be your best choice for this purpose.) I wrote a mandelbrot program, using generic turtle operations, which took nearly an hour to draw the 320 x 240 image below.  However, with a few turtle optimizations, I was able to get that down to just over a minute.  And there may be room to do better (see further below.)  Specific optimizations:</p>

<ul>
<li><p>Maximize the turtle drawing speed via <code>turtle.speed("fastest")</code></p></li>
<li><p>Use <code>screen.tracer(0, 0)</code> and <code>screen.update()</code> to do the bulk of the
drawing offscreen.  In my code below, I update on each
vertical slice of the image so you can see still its progress but
don't delay for each individual pixel to be drawn.</p></li>
<li><p>I found <em>stamping</em> my pixels to be more efficient than your
<code>forward(1)</code> approach.  This isn't intuitive as stamping keeps track
of the stamps and does a bunch of polygon operations but it still
times out better.  This many be because it avoids the pen up and down
operations.</p></li>
<li><p>Make the turtle invisible either from creation using
<code>turtle = Turtle(visible=False)</code> or later via <code>turtle.hideturtle()</code>.
No need to waste time drawing the turtle itself for every pixel.</p></li>
<li><p>Turn off <em>undo</em>.  (In the case of stamping, you can't turn it off
due to a bug in turtle.py, but) in general, if you're drawing lots and
don't plan to undo you, can <code>turtle.setundobuffer(None)</code> to
turn off this feature and not store every operation in a buffer.</p></li>
<li><p>As with any speed optimized program, avoid doing anything at runtime
that you can do ahead -- waste lots of space doing so if needed.
Avoid doing things at runtime that are redundant.  In my example
below, I tried to minimize time spent on setting colors by
precomputing the color values and avoiding <code>turtle.color(...)</code> if the
pen color is already set to the correct color.</p></li>
</ul>

<p><a href="https://i.stack.imgur.com/npFgc.png" rel="nofollow"><img src="https://i.stack.imgur.com/npFgc.png" alt="enter image description here"></a></p>

<pre><code>from turtle import Turtle, Screen

COORDINATES = (-2.0, -1.0, 1.0, 1.0)

WIDTH, HEIGHT = 320, 240

colors = {i: ((i &amp; 0b1111) &lt;&lt; 4, (i &amp; 0b111) &lt;&lt; 5, (i &amp; 0b11111) &lt;&lt; 3) for i in range(2 ** 5)}

def mandelbrot(turtle, minimum_x, minimum_y, maximum_x, maximum_y, iterations, width, height):

    step_x, step_y = (maximum_x - minimum_x) / width, (maximum_y - minimum_y) / height

    real = minimum_x

    current_color = 0

    while real &lt; maximum_x:

        imaginary = minimum_y

        while imaginary &lt; maximum_y:

            color = 0

            c, z = complex(real, imaginary), 0j

            for i in range(iterations):
                if abs(z) &gt;= 4.0:
                    color = i &amp; 31
                    break

                z = z * z + c

            if color != current_color:
                turtle.color(colors[color])
                current_color = color

            turtle.setpos(real, imaginary)
            turtle.stamp()
            imaginary += step_y

        screen.update()
        real += step_x

screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.setworldcoordinates(*COORDINATES)
screen.colormode(255)
screen.tracer(0, 0)

turtle = Turtle(visible=False)
turtle.speed("fastest")
turtle.setundobuffer(1)  # unfortunately setundobuffer(None|0) broken for turtle.stamp()

turtle.begin_poly()
# Yes, this is an empty polygon but produces a dot -- I don't know if this works on all platforms
turtle.end_poly()

screen.register_shape("pixel", turtle.get_poly())
turtle.shape("pixel")
turtle.up()

mandelbrot(turtle, *COORDINATES, 31, WIDTH, HEIGHT)

screen.exitonclick()
</code></pre>

<p>An unresolved issue is, as you noted, it slows down as draws.  It only takes 15 seconds to draw the first 2/3rds of the above image, the last third takes a minute.  I tried to find a reason but nothing so far.  An interesting twist is that the last 5% of the drawing speeds back up.</p>

python turtle-graphics