class_docstr: A map-to-arrays container, with deterministic Reservoir Sampling.
  
  Items are added with an associated key. Items may be retrieved by key, and
  a list of keys can also be retrieved. If size is not zero, then it dictates
  the maximum number of items that will be stored with each key. Once there are
  more items for a given key, they are replaced via reservoir sampling, such
  that each item has an equal probability of being included in the sample.
  
  Deterministic means that for any given seed and bucket size, the sequence of
  values that are kept for any given tag will always be the same, and that this
  is independent of any insertions on other tags. That is:
  
  >>> separate_reservoir = reservoir.Reservoir(10)
  >>> interleaved_reservoir = reservoir.Reservoir(10)
  >>> for i in range(100):
  >>>   separate_reservoir.AddItem('key1', i)
  >>> for i in range(100):
  >>>   separate_reservoir.AddItem('key2', i)
  >>> for i in range(100):
  >>>   interleaved_reservoir.AddItem('key1', i)
  >>>   interleaved_reservoir.AddItem('key2', i)
  
  separate_reservoir and interleaved_reservoir will be in identical states.
  
  See: https://en.wikipedia.org/wiki/Reservoir_sampling
  
  Adding items has amortized O(1) runtime.
  
  Fields:
    always_keep_last: Whether the latest seen sample is always at the
      end of the reservoir. Defaults to True.
    size: An integer of the maximum number of samples.
docstr: Creates a new reservoir.
  
  Args:
    size: The number of values to keep in the reservoir for each tag. If 0,
      all values will be kept.
    seed: The seed of the random number generator to use when sampling.
      Different values for |seed| will produce different samples from the same
      input items.
    always_keep_last: Whether to always keep the latest seen item in the
      end of the reservoir. Defaults to True.
  
  Raises:
    ValueError: If size is negative or not an integer.
docstr_tok: ["Creates","a","new","reservoir",".","Args",":","size",":","The","number","of","values","to","keep","in","the","reservoir","for","each","tag",".","If","0",",","all","values","will","be","kept",".","seed",":","The","seed","of","the","random","number","generator","to","use","when","sampling",".","Different","values","for","|seed|","will","produce","different","samples","from","the","same","input","items",".","always_keep_last",":","Whether","to","always","keep","the","latest","seen","item","in","the","end","of","the","reservoir",".","Defaults","to","True",".","Raises",":","ValueError",":","If","size","is","negative","or","not","an","integer","."]
code: def __init__(self, size, seed=0, always_keep_last=True):
      """Creates a new reservoir.
  
      Args:
        size: The number of values to keep in the reservoir for each tag. If 0,
          all values will be kept.
        seed: The seed of the random number generator to use when sampling.
          Different values for |seed| will produce different samples from the same
          input items.
        always_keep_last: Whether to always keep the latest seen item in the
          end of the reservoir. Defaults to True.
  
      Raises:
        ValueError: If size is negative or not an integer.
      """
      if size < 0 or size != round(size):
          raise ValueError(
              "size must be nonnegative integer, was %s" % size
          )
      self._buckets = collections.defaultdict(
          lambda: _ReservoirBucket(
              size, random.Random(seed), always_keep_last
          )
      )
      # _mutex guards the keys - creating new keys, retrieving by key, etc
      # the internal items are guarded by the ReservoirBuckets' internal mutexes
      self._mutex = threading.Lock()
      self.size = size
      self.always_keep_last = always_keep_last
  
file_path: tensorboard/tensorboard/backend/event_processing/reservoir.py
imports: import collections
  import random
  import threading
label_desc: Use image node_id 1 to create a new Reservoir object  with example: obj = Reservoir(size, seed, always_keep_last)