小编Hau*_*aus的帖子

避免C#虚拟呼叫的开销

我有一些经过大量优化的数学函数需要1-2 nanoseconds完成.这些功能每秒被称为数亿次,因此尽管性能已经非常出色,但呼叫开销仍是一个问题.

为了保持程序的可维护性,提供这些方法的类继承了一个IMathFunction接口,以便其他对象可以直接存储特定的数学函数并在需要时使用它.

public interface IMathFunction
{
  double Calculate(double input);
  double Derivate(double input);
}

public SomeObject
{
  // Note: There are cases where this is mutable
  private readonly IMathFunction mathFunction_; 

  public double SomeWork(double input, double step)
  {
    var f = mathFunction_.Calculate(input);
    var dv = mathFunction_.Derivate(input);
    return f - (dv * step);
  }
}
Run Code Online (Sandbox Code Playgroud)

由于消费代码使用它,这种接口与直接呼叫相比造成了巨大的开销.一个直接调用需要1-2ns,而虚拟接口调用需要8-9ns.显然,接口的存在及其随后的虚拟呼叫转换是这种情况的瓶颈.

如果可能的话,我想保留可维护性和性能.有没有办法在实例化对象时将虚函数解析为直接调用,以便所有后续调用都能够避免开销?我认为这将涉及用IL创建委托,但我不知道从哪里开始.

c# virtual-functions micro-optimization

36
推荐指数
2
解决办法
1673
查看次数

属性比字段慢

似乎我遇到的每个帖子都达成了相同的共识:仅返回字段的属性由JIT内联,并且具有与字段几乎相同的性能.

但是,我目前的情况似乎并非如此.我的程序进行密集计算,访问许多属性,这些属性只是自动获取器和私有设置器.但是,在这种特殊情况下,我只是复制一个对象.

在启用优化的情况下在发布模式下分析代码会导致get对属性函数的许多调用.Copy()总呼叫总计约5.6ms.

属性基准

但是,当属性转换为字段时,函数运行速度比使用属性快6倍:

在此输入图像描述

与使用字段相比,比较两个属性的相等性似乎会产生更多的性能损失.这是类IEquatable实现的基准,使用相同的代码,但使用字段交换属性.

在此输入图像描述

如果JIT应该通过内联来优化属性,为什么会出现?我想保留属性,因为它们的访问控制方面非常方便,但如果它们这么慢,我会坚持使用字段.

编辑:似乎受此问题影响的一些(但不是全部)案例正在使用在接口中声明的属性.在这些情况下没有使用其他多态性,但在这些情况下,删除接口会将性能差异带入预期的水平.

编辑2:如前面的编辑​​所述,似乎问题的一部分是由于接口虚拟调用.经过更多调查后,似乎在CLR中运行基准测试正确地内联属性,但JetBrains dotTrace没有,即使选中"启用内联"也是如此.

c# jit field properties

14
推荐指数
1
解决办法
164
查看次数

.NET Core CLR 一半的时间都在等待 ntdll.dll

我正在使用 dotTrace 分析一个高度并行的项目,并注意到 CLR 花费了近 50% 的时间来等待ntdll.dll. 我很难弄清楚将其归因于什么。

dotTrace 时间线

有没有办法可以确定是什么导致 CLR 花费如此多的时间来调用内核?我已经将这个项目开发为尽可能低分配,并且与运行时间相比,垃圾收集的使用可以忽略不计。我能想到的唯一原因是内存延迟或 CPU 缓存未命中,因为一些 CPU 密集型计算利用随机内存访问。

.net c# performance profiling

7
推荐指数
0
解决办法
1208
查看次数

编写性能与数组 foreach 相当的 IEnumerator

要添加foreach对自定义集合的支持,您需要实现IEnumerable. 阵列,但是,是特殊的,因为它们基本上是编译成一个范围为基础的循环,这是很多比使用一个IEnumerable更快。一个简单的基准测试证实:

                number of elements: 20,000,000
                            byte[]:  6.860ms
       byte[] as IEnumerable<byte>: 89.444ms
CustomCollection.IEnumerator<byte>: 89.667ms
Run Code Online (Sandbox Code Playgroud)

基准:

private byte[] byteArray = new byte[20000000];
private CustomCollection<byte> collection = new CustomCollection<T>( 20000000 );

[Benchmark]
public void enumerateByteArray()
{
  var counter = 0;
  foreach( var item in byteArray )
     counter += item;
}

[Benchmark]
public void enumerateByteArrayAsIEnumerable()
{
  var counter = 0;
  var casted = (IEnumerable<byte>) byteArray;
  foreach( var item in casted )
     counter += item;
}

[Benchmark]
public …
Run Code Online (Sandbox Code Playgroud)

c# ienumerable roslyn

5
推荐指数
1
解决办法
589
查看次数

大型数据集上的 System.Numerics.Vector&lt;T&gt;

我试图通过利用System.Numerics在数组上执行 SIMD 操作来提高 .NET Core 库的性能float[]System.Numerics现在有点时髦,我很难看出它有什么好处。我知道,为了看到 SIMD 的性能提升,必须通过大量计算进行摊销,但考虑到它目前的实现方式,我不知道如何实现这一点。

Vector<float>需要 8 个float值 - 不多也不少。如果我想对一组小于 8 的值执行 SIMD 运算,我必须将这些值复制到一个新数组,并用零填充余数。如果该组值大于 8,我需要复制这些值,用零填充以确保其长度与 8 的倍数对齐,然后循环它们。长度要求是有道理的,但适应这一点似乎是抵消任何性能增益的好方法。

我编写了一个测试包装类来处理填充和对齐:

public readonly struct VectorWrapper<T>
  where T : unmanaged
{

  #region Data Members

  public readonly int Length;
  private readonly T[] data_;

  #endregion

  #region Constructor

  public VectorWrapper( T[] data )
  {
    Length = data.Length;

    var stepSize = Vector<T>.Count;
    var bufferedLength = data.Length - ( data.Length % stepSize ) + stepSize;

    data_ = …
Run Code Online (Sandbox Code Playgroud)

.net c# simd .net-core system.numerics

5
推荐指数
1
解决办法
1415
查看次数

表格行上的 CSS 框阴影未正确显示

当鼠标悬停在表格行上时,我在表格行上添加了一个轻微的框阴影,以便它更加明显。它按预期工作,但是当我添加交替行颜色时,它停止正确显示。

这是问题的 JSFiddle。

<div class="search-table">
<table>
  <tbody>
    <tr>
      <td>A1</td>
      <td>A2</td>
    </tr>
    <tr class="alt">
      <td>B1</td>
      <td>B2</td>
    </tr>
    <tr>
      <td>C1</td>
      <td>C2</td>
    </tr>
    <tr class="alt">
      <td>C1</td>
      <td>C2</td>
    </tr>
  </tbody>
</table>
</div>
<style>
.search-table {
    display: block;
    background-color: #535353;
    font: normal 12px/150% Arial, Helvetica, sans-serif;
    overflow: hidden;
    border: 1px solid #8C8C8C;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
}

.search-table a {
    color: #424242;
}

.search-table table {
    border-collapse: collapse;
    text-align: left;
    width: 100%;
    background-color: #ffffff;
}

.search-table table td, .search-table table th {
    padding: …
Run Code Online (Sandbox Code Playgroud)

css box-shadow

3
推荐指数
1
解决办法
2314
查看次数

SQL Server:查找丢失 ID 的有效方法

我正在使用 SQL Server 来存储数千万条记录。我需要能够查询其表以查找 Id 列中存在间隙的缺失行,因为应该没有间隙。

我目前正在使用我在 StackOverflow 上找到的解决方案:

CREATE PROCEDURE [dbo].[find_missing_ids]
    @Table NVARCHAR(128)
AS
BEGIN
    DECLARE @query NVARCHAR(MAX)
    SET @query = 'WITH Missing (missnum, maxid) '
+ N'AS '
+ N'('
+ N' SELECT 1 AS missnum, (select max(Id) from ' + @Table + ') '
+ N'    UNION ALL '
+ N'    SELECT missnum + 1, maxid FROM Missing '
+ N'    WHERE missnum < maxid '
+ N') '
+ N'SELECT missnum '
+ N'FROM Missing ' …
Run Code Online (Sandbox Code Playgroud)

t-sql sql-server

1
推荐指数
1
解决办法
1486
查看次数