Calculation
-----------

There are two different datasets used for benchmarking obtained from the :mod:`contourpy.util` functions
:func:`~contourpy.util.data.simple` and :func:`~contourpy.util.data.random`.  The former is the sum
of two gaussians that results in a small number of relatively short contours.  The latter is random
data that results in a large number of small contours and a few large contours; this is an extreme
dataset designed to stress the contouring algorithms. Both have the option to generate masked data.

All of the results shown are for a single chunk with a problem size ``n`` (``== nx == ny``) of 1000.

As a guide to the complexity of the output, the unmasked datasets generate the following line
contours in the benchmarks

- ``simple``: 38 lines of about 36 thousand points.
- ``random``: 850 thousand lines of about 7.4 million points.

and the following filled contours

- ``simple``: 55 boundaries (39 outers and 16 holes) of about 76 thousand points.
- ``random``: 1.7 million boundaries (half each of outers and holes) of about 15 million points.

Contour lines
^^^^^^^^^^^^^

.. image:: ../_static/lines_simple_1000_light.svg
   :class: only-light

.. image:: ../_static/lines_simple_1000_dark.svg
   :class: only-dark

For the ``simple`` dataset above the performance of :ref:`serial` for contour lines is the same
regardless of :class:`~.LineType`. It is about the same as :ref:`mpl2005` and significantly faster
than :ref:`mpl2014` with a speedup of 1.8-1.9.

.. image:: ../_static/lines_random_1000_light.svg
   :class: only-light

.. image:: ../_static/lines_random_1000_dark.svg
   :class: only-dark

For the ``random`` dataset above the performance of :ref:`serial` varies significantly by
:class:`~.LineType`.  For ``LineType.SeparateCode`` :ref:`serial` is 10-20% faster than
:ref:`mpl2005`, and is about the same as :ref:`mpl2014` if masked and 10% slower if not masked.

Other :class:`~.LineType` are faster.  ``LineType.Separate`` has a speedup of about 1.4 compared to
``LineType.SeparateCode``; most of the difference here is the time taken to allocate the extra 850
thousand `NumPy`_ arrays (one per line) and a small amount is the time taken to calculate the
`Matplotlib`_ kind codes to put in them.

The chunked line types (``LineType.ChunkCombinedCode``, ``LineType.ChunkCombinedOffset`` and
``LineType.ChunkCombinedNan``) have similar timings with a speedup of 2.4-2.7 compared to
``LineType.SeparateCode``.  The big difference here again is in array allocation, for a single chunk
these two ``LineType`` allocate just two large arrays whereas ``LineType.SeparateCode`` allocates
1.7 million `NumPy`_ arrays, i.e. two per each line returned.

Filled contours
^^^^^^^^^^^^^^^
.. image:: ../_static/filled_simple_1000_light.svg
   :class: only-light

.. image:: ../_static/filled_simple_1000_dark.svg
   :class: only-dark

For the ``simple`` dataset above the performance of :ref:`serial` for filled contours is the same
regardless of :class:`~.FillType`.  It is about the same as :ref:`mpl2005` and significantly
faster than :ref:`mpl2014` with a speedup of 1.9-2.0.

.. image:: ../_static/filled_random_1000_light.svg
   :class: only-light

.. image:: ../_static/filled_random_1000_dark.svg
   :class: only-dark

For the ``random`` dataset above the performance of :ref:`serial` varies significantly by :class:`~.FillType`.
For ``FillType.OuterCode`` it is faster than :ref:`mpl2014` with a speedup of 1.5-1.7.  It is also
faster than :ref:`mpl2005` but only the ``corner_mask=False`` option is shown in full as the unmasked
benchmark here is off the scale at 11.7 seconds.  The :ref:`mpl2005` algorithm calculates points for
outer and hole boundaries in an interleaved format which need to be reordered, and this approach
scales badly for a large outer boundary containing many holes as occurs here for unmasked ``z``.

Other :class:`~.FillType` are faster, although ``FillType.OuterOffset`` is only marginally so as it
creates the same number of `NumPy`_ arrays as ``FillType.OuterCode`` but the arrays are shorter.

The other four :class:`~.FillType` can be grouped in pairs: ``FillType.ChunkCombinedCodeOffset`` and
``FillType.ChunkCombinedOffsetOffset`` have a speedup of 1.8-2.0 compared to
``FillType.OuterCode``; whereas ``FillType.ChunkCombinedCode`` and
``FillType.ChunkCombinedOffset`` are marginally faster with a speedup of 1.9-2.1.  The speed
improvement has the usual explanation that they only allocate a small number of arrays whereas
``FillType.OuterCode`` allocates 1.7 million arrays.  ``FillType.ChunkCombinedCode`` and
``FillType.ChunkCombinedOffset`` are slightly faster than the other two because they do not
determine the relationships between outer boundaries and their holes, they treat all boundaries the
same.
