Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET queue ElementAt performance

Tags:

c#

.net

queue

I'm having a hard time with parts of my code:

    private void UpdateOutputBuffer()
    {
        T[] OutputField = new T[DisplayedLength];

        int temp = 0;
        int Count = HistoryQueue.Count;
        int Sample = 0;

        //Then fill the useful part with samples from the queue
        for (temp = DisplayStart; temp != DisplayStart + DisplayedLength && temp < Count; temp++)
        {
            OutputField[Sample++] = HistoryQueue.ElementAt(Count - temp - 1);
        }

        DisplayedHistory = OutputField;
    }

It takes most of the time in the program. The number of elements in HistoryQueue is 200k+. Could this be because the queue in .NET is implemented internally as a linked list?

What would be a better way of going about this? Basically, the class should act like a FIFO that starts dropping elements at ~500k samples and I could pick DisplayedLength elements and put them into OutputField. I was thinking of writing my own Queue that would use a circular buffer.

The code worked fine for count lower values. DisplayedLength is 500.

Thank you,

David

like image 257
daqq Avatar asked Jan 10 '11 09:01

daqq


People also ask

What is ElementAt C#?

ElementAt() is a System. Linq method in C# that is used to get and display element at a particular index. The following is our string array − string[] arr = { "One", "Two", "Three", "Four", "Five" }; Now to get an element at index 0, use the ElementAt() method − arr.ElementAt(0); The following is the complete code −

Are stacks more efficient than lists?

Stacks are less flexible than lists, but are easier to implement, and more efficient (for those operations they can do).

Is queue faster than list C#?

Queue is significantly faster than List , where memory accesses are 1 vs. n for List in this use case. I have a similar use case but I have hundreds of values and I will use Queue because it is an order of magnitude faster.


2 Answers

Queue does not have an ElementAt method. I'm guessing you are getting this via Linq, and that it is simply doing a forced iteration over n elements until it gets to the desired index. This is obviously going to slow down as the collection gets bigger. If ElementAt represents a common access pattern, then pick a data structure that can be accessed via index e.g. an Array.

like image 146
Tim Lloyd Avatar answered Sep 23 '22 00:09

Tim Lloyd


Yes, the linked-list-ness is almost certainly the problem. There's a reason why Queue<T> doesn't implement IList<T> :) (Having said that, I believe Stack<T> is implemented using an array, and that still doesn't implement IList<T>. It could provide efficient random access, but it doesn't.)

I can't easily tell which portion of the queue you're trying to display, but I strongly suspect that you could simplify the method and make it more efficient using something like:

T[] outputField = HistoryQueue.Skip(...) /* adjust to suit requirements... */
                              .Take(DisplayedLength)
                              .Reverse()
                              .ToArray();

That's still going to have to skip over a huge number of items individually, but at least it will only have to do it once.

Have you thought of using a LinkedList<T> directly? That would make it a lot easier to read items from the end of the list really easily.

Building your own bounded queue using a circular buffer wouldn't be hard, of course, and may well be the better solution in the long run.

like image 20
Jon Skeet Avatar answered Sep 22 '22 00:09

Jon Skeet