0

I have a program that calls a method with the linq aggregate a lot. The purpose is to find the closest value in the list. It currently does it on a List but I need to move the data the double holds into a struct or class. But when I do the program takes almost twice as long to run.

I wrote a sample program below to help illustrate what is going on.

I haven't been programming long so I am sure there is something I am not doing right. Can someone help me understand why its so much slower and is there a way to speed it up? Maybe I shouldn't use linq for this?

    static class Program
    {
        private static readonly List<double> _list = new List<double>();
        private static readonly List<ClassFoo> _classFooList = new List<ClassFoo>();
        private static readonly List<StructFoo> _structFooList = new List<StructFoo>();

        static void Main()
        {
            double _searchVal = 1000.5;
            double _searchCount = 300000;
            
            ClassFoo searchClassFoo = new ClassFoo(_searchVal);
            StructFoo searchStructFoo = new StructFoo(_searchVal);

            for (int i = 0; i < 2000; i++)
            {
                _list.Add(i);
                _classFooList.Add(new ClassFoo(i));
                _structFooList.Add(new StructFoo(i));
            }

            Stopwatch watch;
            Console.WriteLine("double...");
            watch = Stopwatch.StartNew();
            for (int i = 0; i < _searchCount; i++)
            {
                double closest = _list.Aggregate((x, y) => Math.Abs(x - _searchVal) < Math.Abs(y - _searchVal) ? x : y);
            }
            watch.Stop();
            Console.WriteLine(watch.ElapsedMilliseconds);

            Console.WriteLine();
            Console.WriteLine("Struct...");
            watch = Stopwatch.StartNew();
            for (int i = 0; i < _searchCount; i++)
            {
                StructFoo closest = _structFooList.Aggregate((x, y) => Math.Abs(x.Value - searchStructFoo.Value) < Math.Abs(y.Value - searchStructFoo.Value) ? x : y);
            }
            watch.Stop();
            Console.WriteLine(watch.ElapsedMilliseconds);

            Console.WriteLine();
            Console.WriteLine("Class...");
            watch = Stopwatch.StartNew();
            for (int i = 0; i < _searchCount; i++)
            {
                ClassFoo closest = _classFooList.Aggregate((x, y) => Math.Abs(x.Value - searchClassFoo.Value) < Math.Abs(y.Value - searchClassFoo.Value) ? x : y);
            }
            watch.Stop();
            Console.WriteLine(watch.ElapsedMilliseconds);
        }
    }

    readonly struct StructFoo
    {
        public StructFoo(double value) => Value = value;

        public double Value { get; }

        //There will be more properties but not needed for this example.
    }

    class ClassFoo
    {
        public ClassFoo(double value) => Value = value;

        public double Value { get; }

        //There will be more properties but not needed for this example.
    }

Here are my results:

double...
6340

Struct...
11249

Class...
11806
Press any key to continue . . .
  • I can't reproduce the behaviour: `double = 5200; struct = 5500; class = 5700` on *release* build (.Net 5, IA 64). The figures are *slightly different* but I can't see twofold difference. – Dmitry Bychenko Nov 01 '21 at 17:56
  • I am not able to reproduce the same results using BenchmarkDotNet. For me, structs and primitives are the fastest, being 20-25% faster than classes. This seems like a value/reference type divide. – Sweeper Nov 01 '21 at 17:56
  • Oh wow I didn't realize there would be a difference in comparison from debug build and release build. I figured there might be a diff but not in comparison. You guys are correct, when I switch to release build I get `double = 4425; struct = 4402; class = 5432.` I don't know why this happens but I guess its not really a problem then. Thanks. – Corey11820 Nov 01 '21 at 18:15
  • https://stackoverflow.com/questions/4043821/performance-differences-between-debug-and-release-builds – Alexei Levenkov Nov 01 '21 at 18:44

0 Answers0