Introduction

I’ve been implementing numerical libraries in .NET and have come to some conclusions about iteration performance. My classes have to hold a large amount of data and be able to iterate through that data as quickly as possible. In order to compare various methods, I created a simple class called Data that encapsulates an array of doubles.

Method #1: Enumeration

Data implements IEnumerable. It contains GetEnumerator which returns its own DataEnumerator, an inner class.

Conclusions

To test the different methods, I allocated 1,000,000 doubles into an array and indexed over all of them. I repeated this 1,000 times to minimize randomness. Here are the results...

Enumeration is always slow. That’s not surprising as I’m using a general data structure to hold the doubles. The three operator/property methods differed very slightly. These are probably all optimized similarly. Using pointer math to traverse over the raw data was significantly faster. This is probably due to the fact that there’s no bounds checking. In summary, if you have large amounts of data and performance is critical, consider using managed C++.

Acknowledgements

Thanks to Mark Vulfson of ProWorks for tips on using Flipper Graph Control. Also, to my colleagues Ken Baldwin and Steve Sneller at CenterSpace Software.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Trevor has held demanding development positions for a variety of firms using C++, Java, .NET, and other technologies, including Rogue Wave Software, CleverSet, and ProWorks. He is coauthor of The Elements of Java Style , The Elements of C++ Style, and The Elements of C# Style, published by Cambridge University Press. He has also served on a course advisory board of the University of Washington. His teams have won the JavaWorld "GUI Product of the Year" and XML Magazine "Product of the Year" awards. Trevor holds a BSc in Computer Science from the University of British Columbia and a BA in Economics from the University of Western Ontario.

Comments and Discussions

Hi there, You seem to be very up on the subject, and the enumeration thing frankly scares me because I've inherited a project that uses ALOT of enumerations. They are the most OO friendly way of doing things IMHO, but it seems what you've descovered is that it's over 3 times more expensive time wise to use them!

Do you know of any standard structures (Queues, Stacks, etc) that have been implemented to support the IEnumerable interface in a lighter weight way that means enumeration is not quite so expensive in C#?

I haven't tried it, but looking through the code in this article, I'm 99% sure that the slowness of enumerations is because of the boxing/unboxing of doubles to objects. Try replacing the doubles with an object reference type and you should see very different results.

Anyway, point is, I'm guessing "a project that uses ALOT of enumerations" probably isn't using them with value types like double, but with reference types (classes). Queues and Stacks in the System.Collections namespace should be very fast with reference types. Finally, even if you are using value types (ints/doubles/... anything derived from System.ValueType), I'd be very careful before you go out and start ripping code out because "it's using enumerations and they're slow." If you don't absolutely need the performance it's always better to use more easily understandable, maintainable OO designs than a less-elegant method just because it's a little faster. Remember, templates will likely be in the next major version of C#, and then all your value types can use fast enumerators too.

Btw, if you don't have a solid understanding of it, I'd go on to MSDN (probably some good articles here at CP too, I haven't looked) and read about boxing/unboxing in .NET. It happens very transparently, but it's a good thing to understand, especially if you're performance-conscious.

....

Just read some of the other comments on the article, they more or less cover what I was saying. See the "Enumeration performance" thread.