C# BenchmarkDotNet

Install-Package BenchmarkDotNet;

 

 

 

 

 

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApp32
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<PropertyAccessBenchmarks>();
        }
    }

    public class PropertyAccessBenchmarks
    {
        private List<Book> booksList;
        private PropertyInfo[] props;
        private List<Func<Book, object>> getters;

        [GlobalSetup]
        public void Setup()
        {
            booksList = new List<Book>();
            int idx = 0;
            for (int i = 0; i<1000000; i++)
            {
                ++idx;
                booksList.Add(new Book()
                {
                    Id=idx,
                    Name=$"Name_{idx}",
                    Author=$"Author_{idx}",
                    Abstract=$"Abstract_{idx}",
                    Chapter=$"Chapter_{idx}",
                    Title=$"Title_{idx}",
                    Topic=$"Topic_{idx}",
                    Summary=$"Summary_{idx}",
                    ISBN=$"ISBN_{idx}_{Guid.NewGuid().ToString("N")}"
                });
            }

            props=typeof(Book).GetProperties();
            getters=CreateGetters<Book>();
        }

        [Benchmark]
        public int ReflectionAccess()
        {
            int checkSum = 0;
            foreach(var bk in booksList)
            {
                foreach(var prop in props)
                {
                    var val=prop.GetValue(bk);
                    checkSum+=val?.ToString()?.Length??0;
                }
            }
            return checkSum;
        }

        [Benchmark]
        public int ExpressionAccess()
        {
            int checkSum = 0;
            foreach(var bk in booksList)
            {
                foreach(var get in getters)
                {
                    var val = get(bk);
                    checkSum+=val?.ToString()?.Length??0;
                }
            }
            return checkSum;
        }

        private static List<Func<T, object>> CreateGetters<T>()
        { 
            var getters=new List<Func<T, object>>();
            foreach(var prop in typeof(T).GetProperties())
            {
                var param = Expression.Parameter(typeof(T), "x");
                var body = Expression.Convert(
                    Expression.Property(param, prop),
                    typeof(object));

                var lambda=Expression.Lambda<Func<T,object>>(body, param);
                getters.Add(lambda.Compile());
            }
            return getters;
        }
    }

    public class Book
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Abstract { get; set; }
        public string Author { get; set; }
        public string Chapter { get; set; }
        public string Title { get; set; }
        public string Topic { get; set; }
        public string Summary { get; set; }
        public string ISBN { get; set; }
    }
}

 

 

 

image

 

 

 

BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.4946/24H2/2024Update/HudsonValley)
Unknown processor
.NET SDK 9.0.302
  [Host]     : .NET 8.0.18 (8.0.1825.31117), X64 RyuJIT AVX2 [AttachedDebugger]
  DefaultJob : .NET 8.0.18 (8.0.1825.31117), X64 RyuJIT AVX2
MethodMeanErrorStdDev
ReflectionAccess 79.73 ms 1.021 ms 0.905 ms
ExpressionAccess 53.41 ms 0.489 ms 0.434 ms

 


 

 

using System.Diagnostics;
using System.Linq.Expressions;
using System.Text;

namespace ConsoleApp31
{
    internal class Program
    {
        static StringBuilder timeBuilder= new StringBuilder();  
        static void Main(string[] args)
        {
            var booksList = InitBooksList();
            TestTimeViaReflection(booksList);
            TestTimeViaExpression(booksList);
            Console.WriteLine(timeBuilder.ToString());
        }

        static void TestTimeViaReflection(List<Book> booksList)
        {
            Stopwatch watch = Stopwatch.StartNew();

            var props = typeof(Book).GetProperties();

            StringBuilder builder = new StringBuilder(256);
            foreach (var bk in booksList)
            {
                builder.Clear();
                foreach (var prop in props)
                {
                    builder.AppendLine($"{prop.GetValue(bk)?.ToString()??""}");
                }
                //Console.WriteLine(builder.ToString());
            }

            watch.Stop();
            Console.WriteLine($"In refection cost: {watch.Elapsed.TotalSeconds} seconds");
            timeBuilder.AppendLine($"In refection cost: {watch.Elapsed.TotalSeconds} seconds");
        }

        private static void TestTimeViaExpression(List<Book> booksList)
        {
            Stopwatch watch = Stopwatch.StartNew();
            // Cache property getters for Book
            var getters = CreateGetters<Book>();

            StringBuilder builder = new StringBuilder(256);

            foreach (var bk in booksList)
            {
                builder.Clear();
                foreach (var get in getters)
                {
                    builder.AppendLine(get(bk)?.ToString() ?? "");
                }

                // Writing all 1M will kill performance → just sample
                //Console.WriteLine(builder.ToString());
            }

            watch.Stop();
            Console.WriteLine($"In Expression cost {watch.Elapsed.TotalSeconds} seconds");
            timeBuilder.AppendLine($"In Expression cost :{watch.Elapsed.TotalSeconds} seconds");
        }

        static Func<T, object>[] CreateGetters<T>()
        {
            return typeof(T).GetProperties()
                .Select(p =>
                {
                    var param = Expression.Parameter(typeof(T), "x");
                    var property = Expression.Property(param, p);
                    var convert = Expression.Convert(property, typeof(object));
                    return Expression.Lambda<Func<T, object>>(convert, param).Compile();
                })
                .ToArray();
        }

        static List<Book> InitBooksList()
        {
            List<Book> booksList = new List<Book>();
            int idx = 0;
            for (int i = 0; i<1000000; i++)
            {
                ++idx;
                booksList.Add(new Book()
                {
                    Id=idx,
                    Name=$"Name_{idx}",
                    Author=$"Author_{idx}",
                    Abstract=$"Abstract_{idx}",
                    Chapter=$"Chapter_{idx}",
                    Title=$"Title_{idx}",
                    Topic=$"Topic_{idx}",
                    Summary=$"Summary_{idx}",
                    ISBN=$"ISBN_{idx}_{Guid.NewGuid().ToString("N")}"
                });
            }
            return booksList;
        }
    }

    public class Book
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Abstract { get; set; }
        public string Author { get; set; }
        public string Chapter { get; set; }
        public string Title { get; set; }
        public string Topic { get; set; }
        public string Summary { get; set; }
        public string ISBN { get; set; }
    }
}

 

 

image

 

posted @ 2025-09-05 17:41  FredGrit  阅读(11)  评论(0)    收藏  举报