Console.WriteLine slow

后端 未结 9 1575
天涯浪人
天涯浪人 2020-11-29 07:35

I run through millions of records and sometimes I have to debug using Console.WriteLine to see what is going on.

However, Console.WriteLine

9条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-29 07:59

    Here is a 7 times faster implementation that bulk-writes to the Console, with a 10 msec delay. The downside is that you must remember to call Console2.Flush() at the end of the program, otherwise you may lose some output.

    public static class Console2
    {
        private static readonly StringBuilder _sb = new StringBuilder();
        private static volatile CancellationTokenSource _cts;
        private static int _count;
    
        public static void Write(string value)
        {
            lock (_sb) _sb.Append(value);
            ScheduleFlush();
        }
        public static void Write(string format, params object[] args)
        {
            lock (_sb) _sb.AppendFormat(format, args);
            ScheduleFlush();
        }
        public static void WriteLine(string value)
            => Write(value + Environment.NewLine);
    
        public static void WriteLine(string format, params object[] args)
            => Write(format + Environment.NewLine, args);
    
        public static void WriteLine()
            => WriteLine("");
    
        private static void ScheduleFlush()
        {
            _cts?.Cancel();
            var count = Interlocked.Increment(ref _count);
            if (count % 100 == 0) // periodically flush without cancellation
            {
                var fireAndForget = Task.Run(Flush);
            }
            else
            {
                _cts = new CancellationTokenSource();
                var token = _cts.Token;
                var fireAndForget = Task.Run(async () =>
                {
                    await Task.Delay(10, token);
                    Flush();
                }, token);
            }
        }
    
        public static void Flush()
        {
            _cts?.Cancel();
            string text;
            lock (_sb)
            {
                if (_sb.Length == 0) return;
                text = _sb.ToString();
                _sb.Clear();
            }
            Console.Write(text);
        }
    }
    

    Usage example:

    for (int i = 1; i <= 1000; i++)
    {
        Console2.WriteLine($"{DateTime.Now:HH:mm:ss.fff} > Line {i}");
    }
    Console2.Flush();
    

    Output:

    06:27:22.882 > Line 1
    06:27:22.882 > Line 2
    ...
    06:27:22.893 > Line 999
    06:27:22.893 > Line 1000

提交回复
热议问题