【ConcurrentDictionary】并发测试

前言

参考博文:

https://www.cnblogs.com/xiaomowang/p/12400440.html

测试代码

        [HttpGet]
        public async Task<MessageModel<string>> UseConDic(int index, string key, string value)
        {
            var r = await _utilBLL.UseConDic(index, key, value);

            return new MessageModel<string>(true, "Success") { Data = r };
        }
    public interface IUtilBLL
    {
        Task<string> UseConDic(int index, string key, string value);
    }
    public class UtilBLL : IUtilBLL
    {
        private static readonly ConcurrentDictionary<string, string> pairs = new ConcurrentDictionary<string, string>();

        public async Task<string> UseConDic(int index, string key, string value)
        {
            var pId = System.Diagnostics.Process.GetCurrentProcess().Id;

            int count = pairs.Count;

            var val = pairs.GetOrAdd(key, value);

            return $"pId:{pId},执行前:{count}个,执行后:{pairs.Count}个。val:{val}";
        }
    }
        /// <summary>
        /// 将接口导入到SqlServer
        /// </summary>
        /// <returns></returns>
        static async Task TestAddConDicLogs()
        {
            Console.WriteLine($"{DateTime.Now}开始执行");
            SqlSugarScope sqlSugarScope = new SqlSugarScope(new ConnectionConfig()
            {
                DbType = SqlSugar.DbType.SqlServer,
                ConnectionString = "server=.;database=ConTest;uid=sa;pwd=123456;",
                IsAutoCloseConnection = true,
            });

            string filePath = @"D:\Logs\2021-11-30\warn.txt";

            List<ConDicLogs> lst = new List<ConDicLogs>();

            var fileContent = File.ReadAllLines(filePath, Encoding.UTF8);
            for (int i = 0; i < fileContent.Length; i++)
            {
                string str = fileContent[i];

                if (str.Contains("Util.UseConDic") == false)
                    continue;

                ConDicLogs conDicLogs = new ConDicLogs();

                {
                    string p = str[str.IndexOf("参数:")..];
                    string para = p[p.IndexOf("")..p.IndexOf("")];
                    para = para.Replace("", "");
                    para = para.Replace("query:", "");
                    para = para.Replace(".", "");
                    para = para.Replace("", "");

                    string[] s1 = para.Split("&");

                    conDicLogs.p_index = s1[0];
                    conDicLogs.p_key = s1[1];
                    conDicLogs.p_value = s1[2];

                    conDicLogs.p_index = conDicLogs.p_index.Replace("index=", "");
                    conDicLogs.p_key = conDicLogs.p_key.Replace("key=", "");
                    conDicLogs.p_value = conDicLogs.p_value.Replace("value=", "");
                }

                {
                    string p = str[str.IndexOf("Data")..];
                    string para = p[p.IndexOf("pId")..p.IndexOf("}")];
                    para = para.Replace("\"", "");
                    para = para.Replace("}", "");

                    conDicLogs.r_pId = para[para.IndexOf("pId:")..para.IndexOf("", para.IndexOf("pId:"))];
                    conDicLogs.r_ExecBefore = para[para.IndexOf("执行前:")..para.IndexOf("", para.IndexOf("执行前:"))];
                    conDicLogs.r_ExecAfter = para[para.IndexOf("执行后:")..para.IndexOf("", para.IndexOf("执行后:"))];
                    conDicLogs.r_val = para[para.IndexOf("val:")..];

                    conDicLogs.r_pId = conDicLogs.r_pId.Replace("pId:", "");
                    conDicLogs.r_ExecBefore = conDicLogs.r_ExecBefore.Replace("执行前:", "");
                    conDicLogs.r_ExecAfter = conDicLogs.r_ExecAfter.Replace("执行后:", "");
                    conDicLogs.r_val = conDicLogs.r_val.Replace("val:", "");
                }

                Console.WriteLine($"第{i}个");

                lst.Add(conDicLogs);
            }
            Console.WriteLine("加载导入数据的集合完成");

            var r = sqlSugarScope.Insertable(lst).ExecuteCommand();

            Console.WriteLine($"{DateTime.Now}结束执行");
        }
/*创建接口日志表*/
CREATE TABLE [dbo].[ConDicLogs](
    [p_index] [varchar](10) NULL,
    [p_key] [varchar](10) NULL,
    [p_value] [varchar](10) NULL,
    [r_pId] [varchar](10) NULL,
    [r_ExecBefore] [varchar](10) NULL,
    [r_ExecAfter] [varchar](10) NULL,
    [r_val] [varchar](10) NULL
) ON [PRIMARY]
GO

/*
select count(1)
from ConDicLogs
where r_pId='31356'

select count(1)
from ConDicLogs
where r_val='18836'

select *
from ConDicLogs
where r_pId='31356' and r_ExecBefore=0
*/

测试工具

使用Jmeter进行并发测试

1.线程属性

 2.HTTP请求信息

IIS信息

最大工作进程数调整为:3

测试结果

Jmeter结果

1000*50=50000个样本

 NLog日志

总共49998条日志,与Jmeter样本对比,少了2条日志,未找到原因

其中有效日志,49992条记录,存在6条无效的日志记录

 IIS进程

Process进程Id分别为:

进程1=>31356

进程2=>2632

进程3=>10152

请求结果分析

1.pId:31356

记录数:14899条,执行前0个:2条,最终结果:18836,最终结果记录数:14899

2.pId:2632

记录数:15834条,执行前0个:2条,最终结果:26475,最终结果记录数:15834

3.pId:10152

记录数:19259条,执行前0个:3条,最终结果:14205,最终结果记录数:19259

 总结

并发时,测试ConcurrentDictionary的写入值正常,虽然有极限情况下写之前的字典元素个数为0,但是最终写到字典之后返回的结果都是同一个

原文地址:https://www.cnblogs.com/masonblog/p/15624494.html