Op Hashing & Caching
====================

  NUKE attempts to cache data and minimize generation of duplicate data.  The main way in which it does this
  is its hashing system.  Every Op, after it has been constructed for a particular OutputContext (frame/view/proxy setting)
  has a hash.  This hash is used as a key for the data, and other Ops with the same Hash are treated as having the
  same data.

  The default hash of an Op is derived from the following sources:

  * The hashes of all its inputs, generated for the same frame/view/proxy setting as that Op.
  * The hashes of all the knob values at that frame/view.

  This means that a generator Op, with no input, and no animations on its knobs, produces the same hash for frame 1 and frame 2.
  Similarly, it produces the same hash for the left and right view.  In fact, the Ops at frame 1 and frame 2 are unified
  into the same Op.  This default behavior can be changed in various ways.

  Overriding Op::append(Hash& hash) can be used to introduce extra data into the hash.  In particular, a generator that wishes
  to produce different outputs at different times, even without the knobs being animated, could implement Op::append like so:

  .. code-block:: c

    void Op::append(Hash& hash)
    {
      hash.append(outputContext().frame());
    }

  This results in the frame number being taken into account in the hash, and therefore frame 1 being different from frame 2.
  It is also possible to exclude particular knobs from being taken into account when calculating a hash.  Suppose there is a
  knob that does nothing in itself, but is just there to provide an input for a button.  When the button is pressed, 
  some calculations are done that change other knobs, which does result in a change in the image.  The hash should then change, but it
  shouldn't have changed merely because some knob whose value was not used was altered.

  In order to do this, the NO_RERENDER flag should be set on the knob - it doesn't contribute towards the hash, and therefore
  doesn't cause a rerender when it is changed.
  
  Apart from deciding whether or not to recalculate at all (by checking whether the hash remains the same and unifying
  duplicate Ops on the same node), the hashes are used as indexes for caching.  The Viewer and the DiskCache node store
  all data passing through them to the file system and use the Op hash as a key directly.  There is another in-memory cache
  that is used when NUKE identifies that data would otherwise have to be generated twice or more.

  This is invoked in the case where a node is used as the input at more than one point in the node tree.

  Other cases also exist: passing a count of two or more, or simply making two different requests to the same Iop covering overlapping
  regions from the same Iop result in an in-memory cache being created, as will creating a Tile or Interest in engine().

  The cache will exist until NUKE runs out of memory and decides to free it.
