2009-07-24 29 views
17

Trong nhị phân của tôi để nhắn tin cho ứng dụng giải mã (.NET 2.0) tôi thấy rằng dòng:Làm cách nào để cải thiện hiệu suất của mã bằng DateTime.ToString?

logEntryTime.ToString("dd.MM.yy HH:mm:ss:fff") 

mất 33% tổng thời gian xử lý. Có ai có bất kỳ ý tưởng về làm thế nào để làm cho nó nhanh hơn?

EDIT: Ứng dụng này được sử dụng để xử lý một số nhật ký nhị phân và hiện mất 15 giờ để chạy. Vì vậy 1/3 số này sẽ là 5 giờ.

EDIT: Tôi đang sử dụng NProf để định cấu hình. Ứng dụng đang xử lý khoảng 17 GB ký tự nhị phân.

+4

33% trong số những gì? 33% thời gian xử lý 2ms có thể thậm chí không đáng để tái cấu trúc. –

+0

Ngoài ra, bạn đã sử dụng công cụ nào để xác định 33%? Các công cụ khác nhau đôi khi đo lường những thứ khác nhau một cách tinh tế, vì vậy nó đáng để biết ... – Stobor

+2

Làm cách nào để bạn thêm chuỗi kết quả vào đầu ra của mình? Stringbuilder? –

Trả lời

13

Thật không may là .NET không có loại "định dạng" có thể phân tích mẫu và ghi nhớ.

Nếu bạn luôn sử dụng cùng một định dạng, bạn có thể muốn tạo thủ công một trình định dạng để thực hiện chính xác điều đó. Một cái gì đó dọc theo dòng:

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'); 
} 

Điều này khá xấu xí, nhưng có lẽ nó hiệu quả hơn rất nhiều ... đánh giá nó, tất nhiên!

+0

lol; Tôi nghĩ rằng chúng tôi đã làm việc trên một số mã rất giống nhau! –

+1

@Marc tâm trí tuyệt vời nghĩ như nhau !! – inspite

+8

... và fools hiếm khi khác nhau :) –

9

Bạn có chắc chắn mất 33% thời gian không? Làm thế nào bạn đo được điều đó? Nghe có vẻ hơn một chút nghi ngờ đối với tôi ...

này làm cho mọi thứ một chút chút nhanh hơn:

Basic: 2342ms 
Custom: 1319ms 

Hoặc nếu chúng ta cắt ra IO (Stream.Null):

Basic: 2275ms 
Custom: 839ms 

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)); 
    } 
} 
+2

Tôi không hoàn toàn không tin nổi - khi tôi thực hiện một số kiểm tra nhật ký, tôi thấy rằng việc định dạng và phân tích ngày tháng và thời gian đã thống trị truy cập CPU. Phải thừa nhận rằng nó đã làm hầu như không có gì ngoài việc đăng nhập ... –

+0

microbenchmark của bạn là IO bị ràng buộc, nếu bạn muốn đo chu kỳ CPU, bạn có thể bỏ qua văn bản vào một tập tin. –

+1

Có, nhưng OP đang ghi vào một tập tin, do đó, nó là một chút nhân tạo để bỏ qua điều này ... nhưng thực sự, bằng cách sử dụng Stream.Null sẽ hiển thị nhiều sự khác biệt. –

0

Bạn có biết mỗi bản ghi lớn trong nhị phân và văn bản không nhật ký sẽ là gì? Nếu vậy bạn có thể chia nhỏ quá trình xử lý tệp nhật ký trên một số luồng để sử dụng tốt hơn máy tính đa lõi/bộ vi xử lý. Nếu bạn không nhớ kết quả là trong các tập tin riêng biệt nó sẽ là một ý tưởng tốt để có một đĩa cứng cho mỗi lõi theo cách đó bạn sẽ giảm số lượng người đứng đầu đĩa phải di chuyển.

1

Đây không phải là một câu trả lời của riêng mình, mà đúng hơn là một addedum để trả lời execellent Jon Skeet, cung cấp một biến thể cho "s" định dạng (ISO):

/// <summary> 
    ///  Implements a fast method to write a DateTime value to string, in the ISO "s" format. 
    /// </summary> 
    /// <param name="dateTime">The date time.</param> 
    /// <returns></returns> 
    /// <devdoc> 
    ///  This implementation exists just for performance reasons, it is semantically identical to 
    ///  <code> 
    /// text = value.HasValue ? value.Value.ToString("s") : string.Empty; 
    /// </code> 
    ///  However, it runs about 3 times as fast. (Measured using the VS2015 performace profiler) 
    /// </devdoc> 
    public static string ToIsoStringFast(DateTime? dateTime) { 
     if (!dateTime.HasValue) { 
      return string.Empty; 
     } 
     DateTime dt = dateTime.Value; 
     char[] chars = new char[19]; 
     Write4Chars(chars, 0, dt.Year); 
     chars[4] = '-'; 
     Write2Chars(chars, 5, dt.Month); 
     chars[7] = '-'; 
     Write2Chars(chars, 8, dt.Day); 
     chars[10] = 'T'; 
     Write2Chars(chars, 11, dt.Hour); 
     chars[13] = ':'; 
     Write2Chars(chars, 14, dt.Minute); 
     chars[16] = ':'; 
     Write2Chars(chars, 17, dt.Second); 
     return new string(chars); 
    } 

Với serializer 4 chữ số như :

private static void Write4Chars(char[] chars, int offset, int value) { 
     chars[offset] = Digit(value/1000); 
     chars[offset + 1] = Digit(value/100 % 10); 
     chars[offset + 2] = Digit(value/10 % 10); 
     chars[offset + 3] = Digit(value % 10); 
    } 

Điều này chạy nhanh gấp 3 lần. (Được đo bằng hồ sơ hiệu suất VS2015)

Các vấn đề liên quan