.net core中你的MD5用对了吗?

本文的项目环境为 .net 6.0 (.net 5.0 以上都支持)
在 .net 中获取字符串的 MD5 相信是非常容易的事情吧, 但是随便在网上搜一搜发现流传的版本还不少呢,比如:

  1. StringBuilder 版本(应该算是官方版本了,使用的人最多,我发现在 ABP 中也是使用的这个)

  2. BitConverter 版本

  3. StringConcat 版本 (字符串拼接,用的人很少,估计都知道性能不好)

但是它们是否是最佳实现? 我们来测试一下

StringBuilder 版本

C# 复制代码
public static string Md5_StringBuilder(string input)
{
    using var md5 = MD5.Create();
    var inputBytes = Encoding.UTF8.GetBytes(input);
    var hashBytes = md5.ComputeHash(inputBytes);
    var sb = new StringBuilder();
    foreach (var hashByte in hashBytes)
    {
        sb.Append(hashByte.ToString("X2"));
    }
    return sb.ToString();
}

BitConverter 版本

C# 复制代码
public static string Md5_BitConverter(string input)
{
    using var md5 = MD5.Create();
    var inputBytes = Encoding.UTF8.GetBytes(input);
    var hashBytes = md5.ComputeHash(inputBytes);
    return BitConverter.ToString(hashBytes).Replace("-", "");
}

StringConcat 版本

C# 复制代码
public static string Md5_StringConcat(string input)
{
    using var md5 = MD5.Create();
    var inputBytes = Encoding.UTF8.GetBytes(input);
    var hashBytes = md5.ComputeHash(inputBytes);
    var output = string.Empty;
    foreach (var hashByte in hashBytes)
    {
        output += hashByte.ToString("X2");
    }
    return output;
}

性能对比

先上我测试得到的数据(本机配置: 4 核 8 线程, 测试结果可能不一致)

看结果,的确是字符串拼接性能最差,但是 StringBuilder 好像也不是很高效啊,那个什么 Static 是啥玩意,怎么性能这么好,相对于 StringBuilder, 单线程性能提高了 3 倍, 多线性提高了 5 倍???

没错,这就是我要说的, 从 .net 5.0 开始提供了 2 个非常高效的方法

  • Convert.ToHexString
  • MD5.HashData

Convert.ToHexString 实例版本

C# 复制代码
public static string MD5_HexConvert_Instance(string input)
{
    using var md5 = MD5.Create();
    var inputBytes = Encoding.UTF8.GetBytes(input);
    var hashBytes = md5.ComputeHash(inputBytes);
    return Convert.ToHexString(hashBytes);
}

MD5.HashData 静态版本(强烈建议)

C# 复制代码
public static string MD5_HexConvert_Static(string input)
{
    var inputBytes = Encoding.UTF8.GetBytes(input);
    var hashBytes = MD5.HashData(inputBytes);
    return Convert.ToHexString(hashBytes);
}

总结

  • 强烈建议 使用 MD5.HashData + Convert.ToHexString, 代码性能最高,也最简洁,只有 3 行

  • 一定不要 忘记释放 MD5,我看网上很多在使用实例版本 MD5.Create() 后都没有 Dispose, 这会导致 内存泄漏!!!

最后放上我的完整的测试代码

C# 复制代码
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics;

namespace ConsoleTest;

class Program
{
    public static string Md5_StringBuilder(string input)
    {
        using var md5 = MD5.Create();
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = md5.ComputeHash(inputBytes);
        var sb = new StringBuilder();
        foreach (var hashByte in hashBytes)
        {
            sb.Append(hashByte.ToString("X2"));
        }
        return sb.ToString();
    }

    public static string Md5_StringConcat(string input)
    {
        using var md5 = MD5.Create();
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = md5.ComputeHash(inputBytes);
        var output = string.Empty;
        foreach (var hashByte in hashBytes)
        {
            output += hashByte.ToString("X2");
        }
        return output;
    }

    public static string Md5_BitConverter(string input)
    {
        using var md5 = MD5.Create();
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = md5.ComputeHash(inputBytes);
        return BitConverter.ToString(hashBytes).Replace("-", "");
    }

    public static string MD5_HexConvert_Instance(string input)
    {
        using var md5 = MD5.Create();
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = md5.ComputeHash(inputBytes);
        return Convert.ToHexString(hashBytes);
    }

    public static string MD5_HexConvert_Static(string input)
    {
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = MD5.HashData(inputBytes);
        return Convert.ToHexString(hashBytes);
    }

    private const int LOOPCOUNT = 100_0000;
    private static void CalcTime(Func<string, string> func, bool parallel = true)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();

        if (parallel)
        {
            Parallel.For(0, LOOPCOUNT, i =>
            {
                func("123456");
            });
        }
        else
        {
            for (int i = 0; i < LOOPCOUNT; i++)
            {
                func("123456");
            }
        }

        stopwatch.Stop();
        Console.WriteLine($"{func.Method.Name,32}: {stopwatch.ElapsedMilliseconds,4}ms");
    }

    static void Main()
    {
        Test();

        Console.ReadKey();
    }

    private static void Test()
    {
        var functions = new List<Func<string, string>>
        {
            Md5_StringConcat,
            Md5_StringBuilder,
            Md5_BitConverter,
            MD5_HexConvert_Instance,
            MD5_HexConvert_Static,
        };

        foreach (var func in functions)
        {
            Console.WriteLine($"{func.Method.Name,32}: {func("123456")}");
        }

        Console.WriteLine($"\n单线程 {LOOPCOUNT} 次用时统计:");
        foreach (var func in functions)
        {
            CalcTime(func, false);
        }


        Console.WriteLine($"\n多线程 {LOOPCOUNT} 次用时统计:");
        foreach (var func in functions)
        {
            CalcTime(func, true);
        }
    }
}
相关推荐
代码拾光2 天前
面试官:如果某个业务量突然提升100倍QPS你会怎么做?
.net core·架构设计
WikeSoft3 天前
1.net core 工作流WorkFlow流程(介绍)
.net·.net core·workflow·流程引擎
hez20104 天前
用 .NET NativeAOT 构建完全 distroless 的静态链接应用
c#·.net·aot·.net core·native
EdisonZhou9 天前
使用MCP C# SDK开发MCP Server + Client
llm·aigc·asp.net core·.net core
黑贝是条狗13 天前
对.net 的改变
.net core
小吴同学·18 天前
NET6 WebApi第5讲:中间件(源码理解,俄罗斯套娃怎么来的?);Web 服务器 (Nginx / IIS / Kestrel)、WSL、SSL/TSL
中间件·c#·.net·.netcore·.net core
坐望云起19 天前
ASP.NET Web的 Razor Pages应用,配置热重载,解决.NET Core MVC 页面在更改后不刷新
前端·后端·asp.net·mvc·.net core·razor pages
代码拾光1 个月前
.NET Core 中如何实现缓存的预热?
.net core
EdisonZhou1 个月前
基于Microsoft.Extensions.AI核心库实现RAG应用
llm·aigc·.net core
时光追逐者1 个月前
一个开源且免费的 .NET CMS 和应用程序框架
开源·c#·.net·cms·.net core