3

我需要将格式为“HHmmss”的字符串快速转换为 DateTime 或整数。我已经测试过这样的代码:

Console.WriteLine("decoding " + text);
long microseconds = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
Console.WriteLine("start time " + microseconds);
field = DateTime.ParseExact(text, "HHmmss", null);
microseconds = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
Console.WriteLine("finish time " + microseconds);

输出是

解码 172400
开始时间 121
完成时间 244

解码 172400
开始时间 236
完成时间 383

解码 172400
开始时间 116
完成时间 416

解码 172400
开始时间 235
完成时间 421

解码 172359
开始时间 149
完成时间 323

所以平均大约150微秒。有很多时间,我正在编写 HFT 软件,而最好的 HFT 平均有 10 微秒的“tick-to-trade”时间(这包括一切!)。我知道使用 c# 这是不可能的,但是我仍然认为即使使用 c# 150 微秒也太多了。

现在我想使用另一种算法,但是我不知道如何从文本中“提取”整数:

field = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, /*extract hour, min, sec from text*/)

你有什么建议,最快的方法是什么?请不要问我为什么关心性能,而只是建议如何更快地做到这一点。

结果:

使用DateTime.ParseExact(text, "HHmmss", null)大约 6-8 个刻度

使用TimeSpan ts = TimeSpan.ParseExact(text, "hhmmss", null);大约 3-4 个刻度

使用int hour = 10 * text[0] + text[1] - 11 * '0';... 大约 0 滴答声

如果使用循环进行测量,则实际上远小于 0 滴答声。实际上发现上一个版本比其他版本快 100 倍。

代码:

    long startMicroseconds = sw.ElapsedTicks /*/ (Stopwatch.Frequency / (1000L * 1000L))*/;

    //TimeSpan ts = TimeSpan.ParseExact(text, "hhmmss", null);

    //int hour = 10 * text[0] + text[1] - 11 * '0';
    //int minute = 10 * text[2] + text[3] - 11 * '0';
    //int second = 10 * text[4] + text[5] - 11 * '0';

    field = DateTime.ParseExact(text, "HHmmss", null);

    long finishMicroseconds = sw.ElapsedTicks /*/ (Stopwatch.Frequency / (1000L * 1000L))*/;
    Console.WriteLine("elappsed " + (finishMicroseconds - startMicroseconds));
4

3 回答 3

9

这种方法不使用任何字符串子字符串或解析方法。它只使用索引和简单的算术:

int hour   = (s[0] - '0') * 10 + s[1] - '0';
int minute = (s[2] - '0') * 10 + s[3] - '0';
int second = (s[4] - '0') * 10 + s[5] - '0';

下一个版本可能会更快,因为已经对计算进行了部分评估以帮助编译器。因此,阅读和理解会稍微困难一些:

int hour   = s[0] * 10 + s[1] - '0' * 11;
int minute = s[2] * 10 + s[3] - '0' * 11;
int second = s[4] * 10 + s[5] - '0' * 11;

对于踢,您可能还想看看这是否更快,尽管我怀疑此代码将与以前的版本相同:

int hour   = s[0] * 10 + s[1] - 528;
int minute = s[2] * 10 + s[3] - 528;
int second = s[4] * 10 + s[5] - 528;
于 2012-11-07T13:38:54.913 回答
3

如果您真的想要性能而不是可读性,您可以直接使用原始字符:

hour   = 10*s[0] + s[1] - 11*'0';
minute = 10*s[2] + s[3] - 11*'0';
second = 10*s[4] + s[5] - 11*'0';

顺便提一句。DateTime.Now速度很慢,因为它需要将当前时间转换为本地时区。你应该DateTime.UtcNow改用。在我的补偿上花费 9ns DateTime.UtcNowDateTime.Now花费 900ns。

你也应该DateTime.UtcNow只取一次,否则你会得到一个竞争条件。

于 2012-11-07T13:39:14.953 回答
2

这真的太慢了​​吗?

TimeSpan ts = TimeSpan.ParseExact("172406", "hhmmss", null);
int hh = ts.Hours;
int mm = ts.Minutes;
int ss = ts.Seconds;

至少很容易理解。

于 2012-11-07T13:38:01.793 回答