如何使用DateTime.ToString提高代码的性能?

Mic*_*der 19 c# optimization formatting datetime

在我的二进制文本解码应用程序(.NET 2.0)中,我发现了这一行:

logEntryTime.ToString("dd.MM.yy HH:mm:ss:fff")
Run Code Online (Sandbox Code Playgroud)

占总处理时间的33%.有没有人对如何加快速度有任何想法?

编辑:此应用程序用于处理一些二进制日志,它目前需要15个小时才能运行.所以1/3将是5个小时.

编辑:我正在使用NProf进行分析.应用程序正在处理大约17 GB的二进制日志.

Jon*_*eet 16

遗憾的是,.NET没有一种"格式化程序"类型,它可以解析模式并记住它.

如果您总是使用相同的格式,您可能希望手工制作格式化程序来完成相同的操作.有点像:

public static string FormatDateTime(DateTime dt)
{
    char[] chars = new char[21];
    Write2Chars(chars, 0, dt.Day);
    chars[2] = '.';
    Write2Chars(chars, 3, dt.Month);
    chars[5] = '.';
    Write2Chars(chars, 6, dt.Year % 100);
    chars[8] = ' ';
    Write2Chars(chars, 9, dt.Hour);
    chars[11] = ' ';
    Write2Chars(chars, 12, dt.Minute);
    chars[14] = ' ';
    Write2Chars(chars, 15, dt.Second);
    chars[17] = ' ';
    Write2Chars(chars, 18, dt.Millisecond / 10);
    chars[20] = Digit(dt.Millisecond % 10);

    return new string(chars);
}

private static void Write2Chars(char[] chars, int offset, int value)
{
    chars[offset] = Digit(value / 10);
    chars[offset+1] = Digit(value % 10);
}

private static char Digit(int value)
{
    return (char) (value + '0');
}
Run Code Online (Sandbox Code Playgroud)

这非常难看,但它可能效率更高......当然,基准吧!

  • ...和傻瓜很少不同:) (9认同)

Mar*_*ell 9

你确定需要33%的时间吗?你怎么测量的?这对我来说听起来有点可疑......

这使得事情变得更快一些:

Basic: 2342ms
Custom: 1319ms
Run Code Online (Sandbox Code Playgroud)

或者,如果我们删除IO(Stream.Null):

Basic: 2275ms
Custom: 839ms
Run Code Online (Sandbox Code Playgroud)
using System.Diagnostics;
using System;
using System.IO;
static class Program
{
    static void Main()
    {
        DateTime when = DateTime.Now;
        const int LOOP = 1000000;

        Stopwatch basic = Stopwatch.StartNew();
        using (TextWriter tw = new StreamWriter("basic.txt"))
        {
            for (int i = 0; i < LOOP; i++)
            {
                tw.Write(when.ToString("dd.MM.yy HH:mm:ss:fff"));
            }
        }
        basic.Stop();
        Console.WriteLine("Basic: " + basic.ElapsedMilliseconds + "ms");

        char[] buffer = new char[100];
        Stopwatch custom = Stopwatch.StartNew();
        using (TextWriter tw = new StreamWriter("custom.txt"))
        {
            for (int i = 0; i < LOOP; i++)
            {
                WriteDateTime(tw, when, buffer);
            }
        }
        custom.Stop();
        Console.WriteLine("Custom: " + custom.ElapsedMilliseconds + "ms");
    }
    static void WriteDateTime(TextWriter output, DateTime when, char[] buffer)
    {
        buffer[2] = buffer[5] = '.';
        buffer[8] = ' ';
        buffer[11] = buffer[14] = buffer[17] = ':';
        Write2(buffer, when.Day, 0);
        Write2(buffer, when.Month, 3);
        Write2(buffer, when.Year % 100, 6);
        Write2(buffer, when.Hour, 9);
        Write2(buffer, when.Minute, 12);
        Write2(buffer, when.Second, 15);
        Write3(buffer, when.Millisecond, 18);
        output.Write(buffer, 0, 21);
    }
    static void Write2(char[] buffer, int value, int offset)
    {
        buffer[offset++] = (char)('0' + (value / 10));
        buffer[offset] = (char)('0' + (value % 10));
    }
    static void Write3(char[] buffer, int value, int offset)
    {
        buffer[offset++] = (char)('0' + (value / 100));
        buffer[offset++] = (char)('0' + ((value / 10) % 10));
        buffer[offset] = (char)('0' + (value % 10));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我并不完全不相信它 - 当我做一些日志测试时,我发现格式化和解析日期和时间主导了CPU访问.不可否认,除了记录之外,它几乎没有做任何事...... (3认同)