2017-08-04 83 views
0

我在我的应用程序上运行了一些性能分析,发现检查控制台输出编码需要将近两倍的时间来检查我的应用程序是否运行完整的性能迭代。为什么检查Console.OutputEncoding需要很长时间?

我通过检查:

Console.OutputEncoding.EncodingName != Encoding.UTF8.EncodingName 

这个检查需要80〜蜱(8000纳秒),我(生成控制台表)整个应用程序只需要50〜蜱(5000纳秒),而不该运行,并经历了数百个条件。

为什么检查输出编码需要很多时间?我可以加快速度吗?

+0

我不知道你是否可以将这个false等于一个linq表达式。你可以添加一些你的表达式检查的更多上下文吗? –

+1

@BenderBending它只是检查编码。如果控制台编码不等于UTF8,那么我将它设置为UTF8。因为我会添加一个间接级别,所以LINQ可能会变慢。 –

+0

投票过关的用户是否可以解释为什么您认为这太宽?范围似乎对我来说非常明确。 –

回答

1

如果我不得不冒险猜测这是因为你正在比较EncodingName,这会导致潜在的昂贵查找(以及后续的字符串比较)。是否有理由不直接比较编码?

!Console.OutputEncoding.Equals(Encoding.UTF8) 

本地测试它看起来快得多。

+0

这需要大约相同的时间,有趣的是,虽然用这种方式,它每次支票从65-100滴答跳转。 'EncodingName'检查一直挂起80 + = 2个滴答。 –

+0

@DouglasGaskell我不能在本地重现。对我来说,直接比较比'EncodingName'属性快得多。你怎么分析这个? – Kyle

+0

良好的通话,我的测试是有缺陷的,我无意中将'EncodingName'位留在'Encoding.UTF8'上。我正在使用秒表来记录经过的滴答。在发布版本中,需要3个刻度,而名称检查需要38个刻度。 –

2

OutputEncoding,吸气参考来源:https://referencesource.microsoft.com/#mscorlib/system/console.cs,594

public static Encoding OutputEncoding { 
    [System.Security.SecuritySafeCritical] // auto-generated 
    get { 

     Contract.Ensures(Contract.Result<Encoding>() != null); 

     if (null != _outputEncoding) 
      return _outputEncoding; 

     lock(InternalSyncObject) { 

      if (null != _outputEncoding) 
       return _outputEncoding; 

      uint cp = Win32Native.GetConsoleOutputCP(); 
      _outputEncoding = Encoding.GetEncoding((int) cp); 
      return _outputEncoding; 
     } 
    } 
    ... 

我注意到的第一件事是,它采取了锁,所以有一点开销已经存在。它也似乎被延迟实例化:第一次获得OutputEncoding时,它需要先执行PInvoke,然后再执行Encoding.GetEncoding(如果您看到,这不是一项简单的任务)。但是所有后续调用都会避免锁定并返回已经实例化的值。所以,如果你多次获得它,成本将被分摊到几乎没有任何东西。

如果你只是得到它一次......你真的需要优化的东西只需要8微秒?

+0

我得到它多次,我只在第一次测量后,以防止延迟加载。至于优化,我的图书馆是考虑到重度优化而构建的。通常我会说8微秒并不重要,但是当这是我的库实例化的两倍时间,收集数据,格式和输出时,我想优化它。 –

+0

看过之后,除非我模拟'uint cp = Win32Native.GetConsoleOutputCP();'调用,否则它看起来并没有任何解决方法,但我想可以在框架版本之间进行更改,因为它是内部版本。 –

相关问题