/// <summary>
        ///     Adds a new recorded value to the sample
        /// </summary>
        public void Update(long value)
        {
            var count = _count.IncrementAndGet();

            if (count <= _values.Length)
            {
                var index = (int)count - 1;
                Interlocked.Exchange(ref _values[index], value);
            }
            else
            {
                var random = Math.Abs(Random.NextLong()) % count;
                if (random < _values.Length)
                {
                    var index = (int)random;
                    Interlocked.Exchange(ref _values[index], value);
                }
            }
        }
        private void Update(long value, long timestamp)
        {
            _lock.EnterReadLock();
            try
            {
                var priority = Weight(timestamp - _startTime) / Random.NextLong();
                var newCount = _count.IncrementAndGet();
                if (newCount <= _reservoirSize)
                {
                    _values.AddOrUpdate(priority, value, (p, v) => v);
                }
                else
                {
                    var first = _values.Keys.First();
                    if (first < priority)
                    {
                        _values.AddOrUpdate(priority, value, (p, v) => v);

                        long removed;
                        while (!_values.TryRemove(first, out removed))
                        {
                            first = _values.Keys.First();
                        }
                    }
                }
            }
            finally
            {
                _lock.ExitReadLock();
            }

            var now  = DateTime.Now.Ticks;
            var next = _nextScaleTime.Get();

            if (now >= next)
            {
                Rescale(now, next);
            }
        }