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
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 −
Stacks are less flexible than lists, but are easier to implement, and more efficient (for those operations they can do).
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.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With