C# 性能-函数调用与事件、操作与委托

C# 性能-函数调用与事件、操作与委托,c#,performance,events,dependency-injection,delegates,C#,Performance,Events,Dependency Injection,Delegates,目前我正在使用Microsoft Sync Framework同步数据库。我需要收集Microsoft Sync Framework插入/更新/删除的每条记录的信息,并对这些信息进行处理 同步速度每分钟可超过50000条记录。因此,这意味着我的附加代码必须非常轻量级,否则将对性能造成巨大的损失 Microsoft Sync Framework为每条记录引发一个SyncProgress事件。我订阅的代码如下: // Assembly1 SyncProvider.SyncProgress += On

目前我正在使用Microsoft Sync Framework同步数据库。我需要收集Microsoft Sync Framework插入/更新/删除的每条记录的信息,并对这些信息进行处理

同步速度每分钟可超过50000条记录。因此,这意味着我的附加代码必须非常轻量级,否则将对性能造成巨大的损失

Microsoft Sync Framework为每条记录引发一个
SyncProgress
事件。我订阅的代码如下:

// Assembly1
SyncProvider.SyncProgress += OnSyncProgress;
// ....
private void OnSyncProgress(object sender, DbSyncProgressEventArgs e)
{
    switch (args.Stage)
    {
        case DbSyncStage.ApplyingInserts:
            // MethodCall/Delegate/Action<>/EventHandler<> => HandleInsertedRecordInformation 
            // Do something with inserted record info
            break;
        case DbSyncStage.ApplyingUpdates:
            // MethodCall/Delegate/Action<>/EventHandler<> => HandleUpdatedRecordInformation  
            // Do something with updated record info
            break;
        case DbSyncStage.ApplyingDeletes:
            // MethodCall/Delegate/Action<>/EventHandler<> => HandleDeletedRecordInformation
            // Do something with deleted record info
            break;
    }
}
Assembly2
引用了
Assembly1
。因此,
Assembly1
不知道需要处理收集的信息的
SyncInformation
类的存在。因此,我有以下选项来触发此代码:

  • 使用事件并在
    Assembly2

    1.1. EventHandler
    1.2. 行动
    1.3. 代表
  • 使用依赖项注入:
    公共类Assembly2.SyncInformation:Assembly1.ISyncInformation
  • 其他的
  • 我知道性能取决于:

    • OnSyncProgress
      • 开关
      • 使用方法调用、委托、操作或事件处理程序
    • 同步信息类的实现
    我目前不关心
    SyncInformation
    类的实现。我主要关注
    OnSyncProgress
    方法以及如何调用
    SyncInformation
    方法

    因此,我的问题是:

    • 什么是最有效的方法?
    • 什么是最有效的方法?
    • 有没有比在同步进程中使用开关更好的方法?
    同步速度每分钟可超过50000条记录。因此,这意味着我的附加代码必须非常轻量级,否则将对性能造成巨大的损失

    不,不会的

    50k/minute不是一个很大数量的方法调用,除非每个记录需要进行数千次这样的调用。这带有过早优化的味道。如果我们故意忽略编写糟糕的代码和每次调用从头开始的反射,调用方法的绝对最慢的方法是通过非类型化委托
    DynamicInvoke
    ,在我的机器上可以在42ms内完成50k次调用。任何其他内容(在类或接口上键入的委托
    Invoke
    、直接
    callvirt
    、动态
    、静态
    call
    等)都是不可测量的(例如:对于50k调用,它实际上是0毫秒)


    在我看来,你最好使用一个剖析器来了解什么才是真正重要的。它几乎肯定是“正在做”的代码,而不是管道系统。

    谢谢你的回答。”50k/分钟并不是方法调用的一个重要数字“我同意,但我看到订阅
    SyncProvider.SyncProgress
    事件和不订阅事件之间的性能差异。SyncProgress上的
    OnSyncProgress
    唯一要做的事情是(当前)1:每10.000条记录添加日志行2:增加计数器
    DictionaryTableStats[tablename]。记录删除+
    。我看到时差还有其他原因吗?7.000.000/46分钟对7.000.000/53分钟?罚款20K/分钟(基于测试机器而非生产机器的次数。生产平均50K/分钟;测试平均150K/分钟)@hwcverwe为了子孙后代,我想在这里提出一点。您说OnSyncProgress正在添加到日志中,但没有说明成本。对于低延迟应用程序(不是说您的应用程序是,但重点是值得了解的),减少日志事件会有所帮助。如果必须进行日志记录,则可以从二进制日志记录中获益(避免解析文本)。要读取日志,您需要创建一个“日志读取器”应用程序(可能非常简单)。这一点是在大约6个月前我参加的Java for electronic trading活动(Gil Tene,CTO Azul Systems)上提出来的。这一原则适用于C#。
    // Assembly2
    public class SyncInformation
    {
        public void HandleInsertedRecordInformation(...) {...}
        public void HandleUpdatedRecordInformation(...) {...}
        public void HandleInsertedRecordInformation(...) {...}
    }