在域级结构中使用 Int64 代替 DateTime / TimeSpan 是否合理?

问题描述 投票:0回答:1

我的解决方案域项目 (.NET Framework) 中有以下简单结构:

public struct Candlestick
{
    public DateTime OpenTime;
    public DateTime CloseTime;
    public double Open;
    public double High;
    public double Low;
    public double Close;
    public double Volume;
}

在我的业务逻辑中,我有许多方法可以在大烛台结构列表中执行基于时间的搜索。例如:

public static int IndexOfFirst(this IReadOnlyList<Candlestick> data, DateTime from)
{
    if (data == null)
        throw new ArgumentNullException(nameof(data));

    int count = data.Count;
    if (count == 0) return -1;

    int fromIdx = 0;
    while (data[fromIdx].OpenTime < from)
    {
        if (++fromIdx == count)
        {
            return -1;
        }
    }

    return fromIdx;
}

在 Candlestick 结构中使用 long (

Int64
) 类型作为时间变量通常是个好主意,以便逻辑层可以使用此结构更快地运行吗?此外,我的意思是将相应的类保留在应用程序级别(视图模型层中的 CandlestickVM),并使用
DateTime
.

类型的时间变量

为了检验我使用

Int64
的想法,我在 dotnetfiddle.net 上运行了一个简单的性能测试:

DateTime a = new DateTime(2023, 01, 01);
DateTime b = new DateTime(2023, 02, 01);

TimeSpan incr = new TimeSpan(1);
DateTime now = a;
Stopwatch sw = Stopwatch.StartNew();
while (now < b)
{
    now += incr;
}
sw.Stop();
Console.WriteLine($"It took {sw.Elapsed} to run the Date & Time test.");

long incr2 = incr.Ticks;
long now2 = a.Ticks;
long bticks = b.Ticks;
sw.Restart();
while (now2 < bticks)
{
    now2 += incr2;
}
sw.Stop();
Console.WriteLine($"It took {sw.Elapsed} to run the long test.");

结果如下:

It took 00:00:04.8027716 to run the Date & Time test.
It took 00:00:00.9261338 to run the long test.
c# .net performance optimization domain-driven-design
1个回答
0
投票

您的代码仅使用

DateTime
进行比较,而您的基准测试则进行加法。我使用 BenchmarkDtonet 做了一个简单的基准测试,仅进行了比较,这里是代码和结果:

[SimpleJob(RuntimeMoniker.Net70)]    
[RPlotExporter]
public class LongXDateTime
{
    [Params(1_000_000)]
    private int N;
    private DateTime[] Da;
    private DateTime[] Db;
    private long[] La;
    private long[] Lb;

    [GlobalSetup]
    public void Setup()
    {
        Da = new DateTime[N];
        Db = new DateTime[N];
        La = new long[N];
        Lb = new long[N];
        for (int i = 0; i < N; i++)
        {
            La[i] = Random.Shared.NextInt64(DateTime.MinValue.Ticks, DateTime.MaxValue.Ticks);
            Lb[i] = Random.Shared.NextInt64(DateTime.MinValue.Ticks, DateTime.MaxValue.Ticks);
            Da[i] = new DateTime(La[i]);
            Db[i] = new DateTime(Lb[i]);
        }
    }

    [Benchmark]
    public bool[] LongMethod()
    {
        bool[] result = new bool[La.Length];
        for(int i = 0; i < La.Length; i++)
        {
            result[i] = La[i] < Lb[i];
        }
        return result;
    }
    [Benchmark]
    public bool[] DateTimeMethod()
    {
        bool[] result = new bool[Da.Length];
        for (int i = 0; i < Da.Length; i++)
        {
            result[i] = Da[i] < Db[i];
        }
        return result;
    }
}

结果:

|         Method |          N |     Mean |     Error |    StdDev |
|--------------- |----------- |---------:|----------:|----------:|
|     LongMethod |    1000000 | 1.460 ms | 0.0253 ms | 0.0370 ms |
| DateTimeMethod |    1000000 | 1.467 ms | 0.0292 ms | 0.0380 ms |

所以切换到长:

  1. 可能与应用程序性能无关
  2. 可读性较差
  3. 不太安全,因为你失去了类型安全

此外,推荐阅读 Erik Lippert 关于性能的博客

© www.soinside.com 2019 - 2024. All rights reserved.