日期:2014-05-18  浏览次数:20909 次

大并发量下的线程数据问题
今天在做性能测试时为了方便知道哪个过程用了多长时间,所以在代码里写了处理时间记录。以提交业务时的时间为开始点,每一个处理过程获取系统时间减开始时间,记录开始时间到处理完当前过程用了多少ms。
然后跑1W个业务过程,每秒上20个,当同时运行过程数达到2K多个时,时间记录出了问题,一个过程完成的每个段的总ms数应是增加的,结果出现了ms数小于前一个处理段ms数的问题。(1000用户并发时没有问题)
400用户并发时的正常过程如下:
加载xml:0 获取信息:0 保存XML:0 评分完成:46 保存XML:46 保存错误数据:187 保存信息到库:187
加载xml:15 获取信息:15 保存XML:15 评分完成:62 保存XML:62 保存错误数据:203 保存信息到库:203

1W用户到达2000并发时会出以如下错误:
加载xml:0 获取信息:0 保存XML:578 评分完成:718 保存XML:0 保存错误数据:828 保存信息到库:828
加载xml:0 获取信息:31 保存XML:703 评分完成:968 保存XML:140 保存错误数据:984 保存信息到库:984
加载xml:0 获取信息:0 保存XML:796 评分完成:921 保存XML:109 保存错误数据:15 保存信息到库:15
加载xml:15 获取信息:15 保存XML:687 评分完成:812 保存XML:15 保存错误数据:15 保存信息到库:15
加载xml:0 获取信息:0 保存XML:343 评分完成:375 保存XML:609 保存错误数据:484 保存信息到库:484


原来担心StringBuilder的线程安全问题,所以把timeInfo由StringBuilder改成了string。
代码基本过程如下:
C# code

using System;

class class1
{
    static StringBuilder infoAll = new StringBuilder();

    private void Page_Load()
    {
        //如果要保存,将信息保存到文件中
        if (Request.QueryString["save"] == "1")
        {
            System.IO.StreamWriter sw = new StreamWriter("c:\\logs\\test\\examcount.txt", true);
            sw.WriteLine(timeInfoAll.ToString());
            sw.Close();
            infoAll = new StringBuilder();
            return;
        }

        //初始化
        DateTime dtS = DateTime.Now;
        TimeSpan ts = new TimeSpan();
        string timeInfo = "";

        //过程1

        ts = DateTime.Now - dtS;
        timeInfo += ";加载xml:" + ts.Milliseconds;

        //过程2

        ts = DateTime.Now - dtS;
        timeInfo += "; 从库获取信息:" + ts.Milliseconds;

        //过程3


        ts = DateTime.Now - dtS;
        timeInfo += "; 保存XML:" + ts.Milliseconds;

        if(1=1)//分支条件
            Pro1(dtS, timeInfo, ts);
        else
            Pro1A(dtS, timeInfo, ts);

    }

    private void Pro1(DateTime dtS, string timeInfo, TimeSpan ts)
    {
        //过程
        Pro2(dtS, timeInfo, ts);
    }

    private void Pro1A(DateTime dtS, string timeInfo, TimeSpan ts)
    {
        //过程
        Pro2(dtS, timeInfo,ts);
    }

    private void Pro2(DateTime dtS, string timeInfo, TimeSpan ts)
    {
        ts = DateTime.Now - dtS;
        timeInfo += "; 数据处理完成:" + ts.Milliseconds;

        //过程4


        ts = DateTime.Now - dtS;
        timeInfo += "; 保存XML:" + ts.Milliseconds;

        //过程5

        ts = DateTime.Now - dtS;
        timeInfo += "; 保存错误数据:" + ts.Milliseconds;

        //过程6

        ts = DateTime.Now - dtS;
        timeInfo += "; 保存信息到库:" + ts.Milliseconds + "\r\n";

        infoAll.Append(timeInfo);
    }
}



------解决方案--------------------
个人认为你的日志记录,不是一个用户使用的结果,比如用户A执行了过程一并记录了时间,马上要执行过程2,但是还没有记录时间,这是用户B进入页面并执行过程,这时会写入日志吧,但这个值和用户A的值就不一样了
------解决方案--------------------
孩,用TotalMilliseconds 。
Milliseconds只是指这个时间持续中的毫秒分量。
1000个没问题是因为都不超过1秒,所有怎么减都没错。
超过1秒,你知道的。