/// <summary>
        /// Helper method that chunks up the work done by the handler.
        /// The method returns true while there is more work to be done by the handler.
        /// quantum parameter determines the size of one chunck of work to be done by the handler.
        /// </summary>
        /// <param name="quantum">The current quantum allocation. Each call updates so that the handler will more likely hit the ideal time it takes for each chunck of work</param>
        /// <param name="handler">The handler to call that does the work being throttled</param>
        /// <returns>Returns true if there is more work to be done by the handler. false otherwise.</returns>
        private bool SelfThrottlingWorker(ref int quantum, QuantizedWorkHandler handler)
        {
            int  work;
            int  workDone;
            bool workRemaining = true;

            if (this.throttlingLimit > 0)
            {
                work     = this.throttlingLimit;
                workDone = handler(work);
            }
            else
            {
                work = quantum;
                this.throttlingWorkerWatch.Restart();
                workDone = handler(work);
                this.throttlingWorkerWatch.Stop();
                long duration = this.throttlingWorkerWatch.ElapsedMilliseconds;
                if (workDone > 0 && duration > 0)
                {
                    long adjustedQuantum = (workDone * this.idealDuration) / duration;
                    quantum = Math.Max(this.minimumQuantum, (int)Math.Min(adjustedQuantum, int.MaxValue));
                }
            }

            if (workDone < work)
            {
                workRemaining = false;
            }

            return(workRemaining);
        }
Example #2
0
        /// <summary>
        /// Helper method for self-tuning how much time is allocated to the given handler.
        /// </summary>
        /// <param name="quantum">The current quantum allocation</param>
        /// <param name="idealDuration">The time in milliseconds we want to take</param>
        /// <param name="handler">The handler to call that does the work being throttled</param>
        /// <returns>Returns the new quantum to use next time that will more likely hit the ideal time</returns>
        private static int SelfThrottlingWorker(int quantum, int idealDuration, QuantizedWorkHandler handler)
        {
            PerfTimer timer = new PerfTimer();

            timer.Start();
            int count = handler(quantum);

            timer.Stop();
            long duration = timer.GetDuration();

            if (duration > 0 && count > 0)
            {
                long estimatedFullDuration = duration * (quantum / count);
                long newQuanta             = (quantum * idealDuration) / estimatedFullDuration;
                quantum = Math.Max(100, (int)Math.Min(newQuanta, int.MaxValue));
            }

            return(quantum);
        }
Example #3
0
        /// <summary>
        /// Helper method for self-tuning how much time is allocated to the given handler.
        /// </summary>
        /// <param name="quantum">The current quantum allocation</param>
        /// <param name="idealDuration">The time in milliseconds we want to take</param>
        /// <param name="handler">The handler to call that does the work being throttled</param>
        /// <returns>Returns the new quantum to use next time that will more likely hit the ideal time</returns>
        private static int SelfThrottlingWorker(int quantum, int idealDuration, QuantizedWorkHandler handler)
        {
            PerfTimer timer = new PerfTimer();
            timer.Start();
            int count = handler(quantum);

            timer.Stop();
            long duration = timer.GetDuration();

            if (duration > 0 && count > 0)
            {
                long estimatedFullDuration = duration * (quantum / count);
                long newQuanta = (quantum * idealDuration) / estimatedFullDuration;
                quantum = Math.Max(100, (int)Math.Min(newQuanta, int.MaxValue));
            }

            return quantum;
        }
Example #4
0
        /// <summary>
        /// Realizes and virtualizes items based on the current viewbox.
        /// </summary>
        /// <returns>An enumerator which allows this method to continue realization where it left off.</returns>
        private IEnumerator RealizeOverride()
        {
            IVisualFactory f = VisualFactory ?? this.defaultFactory;

            f.BeginRealize();
            IEnumerator <ISpatialItem> itemEnumerator = null;
            HashSet <ISpatialItem>     realizedItems  = new HashSet <ISpatialItem>();

            // RealizeItems
            if (this.Items != null)
            {
                IEnumerable <ISpatialItem> itemsToRealize = null;
                if (this.IsVirtualizing)
                {
                    // Only realize the items within our viewbox.
                    double scale   = Scale;
                    Rect   viewbox = ActualViewbox;

                    // Buffer the viewbox.
                    // This just seems to make things worse, especially when zoomed out a long way.
                    // A smarter algorithm would predict the direction we are moving and only prefetch those.
                    // viewbox.Inflate(viewbox.Width / 2, viewbox.Height / 2);

                    // Query the index for all items that intersect our viewbox.
                    // use ToList() because we can't leave the query to be lazy.
                    // by the time RealizeItems is called below the contents of the query
                    // may have mutated.
                    itemsToRealize = Items.GetItemsIntersecting(viewbox).ToList();
                }
                else
                {
                    // Get all items.
                    itemsToRealize = Items;
                }

                itemEnumerator = itemsToRealize.GetEnumerator();
                QuantizedWorkHandler realizeHandler = delegate(int realizationQuantum)
                {
                    return(this.RealizeItems(itemEnumerator, realizedItems, realizationQuantum));
                };

                while (this.SelfThrottlingWorker(ref this.realizationQuantum, realizeHandler))
                {
                    yield return(true);
                }

                // Raise VisualChildrenChanged only if new
                if (realizedItems.Count > 0)
                {
                    // Raise the VisualChildrenChanged event since all items are visible.
                    if (this.VisualChildrenChanged != null)
                    {
                        this.VisualChildrenChanged(this, EventArgs.Empty);
                    }
                }
            }

            // VirtualizeItems
            // Build a list of items to virtualize.
            IList <ISpatialItem> itemsToVirtualize = new List <ISpatialItem>(this.visualMap.Count);

            // Get any items that are no longer part of our result set.
            foreach (ISpatialItem item in this.visualMap.Keys)
            {
                if (!realizedItems.Contains(item))
                {
                    if (this.ShouldVirtualize(item))
                    {
                        itemsToVirtualize.Add(item);
                    }
                }
            }

            itemEnumerator = itemsToVirtualize.GetEnumerator();
            QuantizedWorkHandler virtualizingHandler = delegate(int virtualizationQuantum)
            {
                return(this.VirtualizeItems(itemEnumerator, virtualizationQuantum));
            };

            while (this.SelfThrottlingWorker(ref this.virtualizationQuantum, virtualizingHandler))
            {
                yield return(true);
            }

            f.EndRealize();
        }