C# 性能字符串检查

C# 性能字符串检查,c#,C#,我的C应用程序中有此功能: public static string SafeTrim(object str) { if ( str == null || str == DBNull.Value ) return string.Empty; else return str.ToString().Trim(); } 它工作正常,但在我的导入实用程序中,它在处理数十万条记录时被调用了数百万次。ANTS profiler指出,这个函数会消耗大量的CPU周期,

我的C应用程序中有此功能:

public static string SafeTrim(object str) 
{
    if ( str == null || str == DBNull.Value )
      return string.Empty;
    else
      return str.ToString().Trim();
}
它工作正常,但在我的导入实用程序中,它在处理数十万条记录时被调用了数百万次。ANTS profiler指出,这个函数会消耗大量的CPU周期,因为它被频繁调用

编辑:我忘了提一下SafeTrim在 我的应用程序用于数据行/数据列值。例子: SafeTrimdt.Rows[0][id]-通常包含 值,并且它通常包含边空间 这需要加以调整

它可以以任何方式进行优化吗

编辑:我将尝试这些不同的方法,在负载下,和 明天回来报道。谢谢大家


在我看来,几个简单的重载可能很有用:

public static string SafeTrim(object str)
{
    return str is string x ? SafeTrim(x) : String.Empty;
}

public static string SafeTrim(string str)
{
    return str?.Trim() ?? string.Empty;
}
我不明白如果对象str是其他类型,那么返回值应该是什么,所以我没有把它放进去

以下是我的测试代码:

void Main()
{
    var rnd = new Random();
    var strings = Enumerable.Range(0, 1000000).Select(x => x.ToString() + (rnd.Next(2) == 0 ? " " : "")).ToArray();

    var results = new [] { new { source = 0, elapsed = TimeSpan.Zero } }.Take(0).ToList();

    for (int i = 0; i < 100; i++)
    {

        var sw = Stopwatch.StartNew();
        var trimmed0 = strings.Select(x => SafeTrim0(x)).ToArray();
        sw.Stop();
        results.Add(new { source = 0, elapsed = sw.Elapsed });

        sw = Stopwatch.StartNew();
        var trimmed1 = strings.Select(x => SafeTrim1(x)).ToArray();
        sw.Stop();
        results.Add(new { source = 1, elapsed = sw.Elapsed });      
    }

    results.GroupBy(x => x.source, x => x.elapsed.TotalMilliseconds).Select(x => new { x.Key, Average = x.Average() }).Dump();
}

public static string SafeTrim1(string str)
{
    return str?.Trim() ?? string.Empty;
}

public static string SafeTrim0(object str) 
{
    if ( str == null || str == DBNull.Value )
      return string.Empty;
    else
      return str.ToString().Trim();
}
SafeTrim0和SafeTrim1之间的平均运行长度分别为155.8 ms和147.7 ms。

使用ReferenceEquals,可以减少运算符重载导致的一些嵌套函数调用

公共静态字符串SafeTrimobject str { ifReferenceEqualsstr,null | | referenceequalstr,DBNull.Value//DBNull.Value为单例 { 返回字符串。空; } 返回str.ToString.Trim; }
这可能很有用:如果要修剪字符串值,为什么要使用parameter对象?这个方法是如何调用的,传递给它的是什么?我首先要问自己是否真的需要经常调用这个方法。也许,也仅仅是也许,您可以通过以类型感知的方式处理记录字段来消除对该方法的大量调用,例如,对于包含数字的记录字段,您不需要将该方法称为DBNull;有趣的是,您可以从IDataReader的第一条记录中获得IsDbNull/GetFieldType,然后以惊人的速度继续前进。如果速度是一个问题,不要懒惰。你可以应用[MethodImplOptions.AggressiveInline]属性。适用于x64,但不适用于x86。这将阻止探查器抱怨它,因为它无法再看到该方法。然而,你的程序是否真的更快还是很值得怀疑的。不仅仅是因为内联它会使它变慢,这个程序的执行时间应该完全由I/O控制。检索数据的成本,探查器通常不会显示这一点。使代码速度提高两倍并不能使I/O速度提高两倍,如果您看到一些百分比的改进,或者看到一个非字符串的情况,您将是幸运的。这与实际情况完全不同。请将行:string result=str视为string?.Trim??无效的如果在参数中传递的值DBNull,它将自动转换为null,因为它不是字符串。要进一步提高性能,可以通过重新检查第一个和最后一个不是分隔字符串的字符来避免重新创建已修剪的字符串值。我尝试了你的,每100000000次运行一次。速度没有明显差别。我试过你的和我的,每次跑100000000次。我的车快了2秒-@HerrimanCoder-是否要共享测试和度量代码?我将看看是否可以将其组合在一起。您也应该向测试中添加一些DBNull.value。
void Main()
{
    var rnd = new Random();
    var strings = Enumerable.Range(0, 1000000).Select(x => x.ToString() + (rnd.Next(2) == 0 ? " " : "")).ToArray();

    var results = new [] { new { source = 0, elapsed = TimeSpan.Zero } }.Take(0).ToList();

    for (int i = 0; i < 100; i++)
    {

        var sw = Stopwatch.StartNew();
        var trimmed0 = strings.Select(x => SafeTrim0(x)).ToArray();
        sw.Stop();
        results.Add(new { source = 0, elapsed = sw.Elapsed });

        sw = Stopwatch.StartNew();
        var trimmed1 = strings.Select(x => SafeTrim1(x)).ToArray();
        sw.Stop();
        results.Add(new { source = 1, elapsed = sw.Elapsed });      
    }

    results.GroupBy(x => x.source, x => x.elapsed.TotalMilliseconds).Select(x => new { x.Key, Average = x.Average() }).Dump();
}

public static string SafeTrim1(string str)
{
    return str?.Trim() ?? string.Empty;
}

public static string SafeTrim0(object str) 
{
    if ( str == null || str == DBNull.Value )
      return string.Empty;
    else
      return str.ToString().Trim();
}