private void TimeToStartSomeWorkers(object info) { if (currentSecond == loadIntervalInSecs) { timer.Change(Timeout.Infinite, Timeout.Infinite); } lock (_lock) //nothing blocks inside this except the last second (or so we hope) { if (thatsIt) //timer may start a little more threads than necessary { return; } System.Threading.Thread.CurrentThread.Priority = ThreadPriority.Highest; //we obtained lock, so we have to be cpu-priviliged if (currentSecond == loadIntervalInSecs) //last second { thatsIt = true; WriteInfo(string.Format("{0} should be equal (more or less) to {1}. If it isn't it means your computer wasn't always able to fire given amount of threads per second.", (DateTime.Now - start).TotalSeconds, loadIntervalInSecs)); if (jobs.Count(f => f.Completed) != jobs.Count) { WriteInfo("Waiting (max one minute)..."); int waited = 0; while (waited < 60) { System.Threading.Thread.Sleep(1000); waited++; if (jobs.Count(f => f.Completed) == jobs.Count) { break; } } } WriteInfo(string.Format("{0}: Total threads created: {1}, actually completed before test ended: {2} ({3}%)", DateTime.Now, jobs.Count, jobs.Count(f => f.Completed), Math.Round(jobs.Count(f => f.Completed) * 100 / (double)jobs.Count))); //calc and output stats int failures = 0; double totalMillisecs = 0; Dictionary <string, int> failureReasons = new Dictionary <string, int>(); List <KeyValuePair <DateTime, string> > errorTimes = new List <KeyValuePair <DateTime, string> >(); foreach (ThreadJob job in jobs.Where(f => f.Completed)) { if (!job.TerminatedSuccesfully) { failures++; if (!failureReasons.Keys.Contains(job.FailureReason)) { failureReasons.Add(job.FailureReason, 1); } else { failureReasons[job.FailureReason]++; } errorTimes.Add(new KeyValuePair <DateTime, string>(job.FailureTime, job.FailureReason)); } else { totalMillisecs += job.ResponseTimeInMilliseconds; } } WriteInfo(string.Format("Total completed workers: {0}, of which failed {1} ({2}%), successful worker's avg time (sec) {3}, downloaded (after decompression): {4} Mb", jobs.Count(f => f.Completed), failures, jobs.Count(f => f.Completed) != 0 ? Math.Round(failures * 100 / (double)jobs.Count(f => f.Completed)) : 0, (jobs.Count(f => f.Completed) - failures) != 0 ? (double)((totalMillisecs / (double)(jobs.Count(f => f.Completed) - failures)) / (double)1000) : -1, Math.Round(jobs.Where(f => f.Completed).Sum(f => f.DownloadedBytes) / (double)1048576, 2))); Dictionary <string, int> timeDistribution = new Dictionary <string, int>(); timeDistribution.Add("[0; 10] sec", 0); timeDistribution.Add("[10; 30] sec", 0); timeDistribution.Add("[30; 60] sec", 0); timeDistribution.Add("[60; ...] sec", 0); foreach (ThreadJob job in jobs.Where(f => f.Completed)) { if (job.TerminatedSuccesfully) { int time = job.ResponseTimeInMilliseconds / 1000; if (time <= 10) { timeDistribution["[0; 10] sec"]++; } if (time > 10 && time <= 30) { timeDistribution["[10; 30] sec"]++; } if (time > 30 && time <= 60) { timeDistribution["[30; 60] sec"]++; } if (time > 60) { timeDistribution["[60; ...] sec"]++; } } } WriteInfo("Time distribution:"); foreach (string key in timeDistribution.Keys) { WriteInfo(key + ": " + timeDistribution[key] + " request(s)"); } if (failures != 0) { WriteInfo("\nBelow are common failure reasons:"); foreach (string failure in failureReasons.Keys.OrderByDescending(f => failureReasons[f])) { WriteInfo(string.Format("'{0}' happened {1} times", failure, failureReasons[failure])); } WriteInfo("Error map:"); foreach (var failureTime in errorTimes) { WriteInfo(failureTime.Key + ": " + failureTime.Value); } } thatsReallyIt = true; //main program can exit } else { if (ShowAllOutput) { WriteInfo(string.Format("{0}: second {1}, jobs that second {2}, active requests: {3}", DateTime.Now, currentSecond, loadMap[currentSecond], Engine.counter)); } for (int i = 0; i < loadMap[currentSecond]; i++) //how much work happened this second { ThreadJob job = new ThreadJob(string.Format("{0}.{1}", currentSecond, i), currentJob); jobs.Add(job); ThreadPool.QueueUserWorkItem(job.ThreadProc); currentJob++; } currentSecond++; } } System.Threading.Thread.CurrentThread.Priority = ThreadPriority.Normal; }
private void TimeToStartSomeWorkers(object info) { if (currentSecond == loadIntervalInSecs) timer.Change(Timeout.Infinite, Timeout.Infinite); lock (_lock) //nothing blocks inside this except the last second (or so we hope) { if (thatsIt) //timer may start a little more threads than necessary return; System.Threading.Thread.CurrentThread.Priority = ThreadPriority.Highest; //we obtained lock, so we have to be cpu-priviliged if (currentSecond == loadIntervalInSecs) //last second { thatsIt = true; WriteInfo(string.Format("{0} should be equal (more or less) to {1}. If it isn't it means your computer wasn't always able to fire given amount of threads per second.", (DateTime.Now - start).TotalSeconds, loadIntervalInSecs)); if (jobs.Count(f => f.Completed) != jobs.Count) { WriteInfo("Waiting (max one minute)..."); int waited = 0; while (waited < 60) { System.Threading.Thread.Sleep(1000); waited++; if (jobs.Count(f => f.Completed) == jobs.Count) break; } } WriteInfo(string.Format("{0}: Total threads created: {1}, actually completed before test ended: {2} ({3}%)", DateTime.Now, jobs.Count, jobs.Count(f => f.Completed), Math.Round(jobs.Count(f => f.Completed)*100 / (double)jobs.Count))); //calc and output stats int failures = 0; double totalMillisecs = 0; Dictionary<string, int> failureReasons = new Dictionary<string, int>(); List<KeyValuePair<DateTime, string>> errorTimes = new List<KeyValuePair<DateTime, string>>(); foreach (ThreadJob job in jobs.Where(f => f.Completed)) { if (!job.TerminatedSuccesfully) { failures++; if (!failureReasons.Keys.Contains(job.FailureReason)) failureReasons.Add(job.FailureReason, 1); else failureReasons[job.FailureReason]++; errorTimes.Add(new KeyValuePair<DateTime, string>(job.FailureTime, job.FailureReason)); } else { totalMillisecs += job.ResponseTimeInMilliseconds; } } WriteInfo(string.Format("Total completed workers: {0}, of which failed {1} ({2}%), successful worker's avg time (sec) {3}, downloaded (after decompression): {4} Mb", jobs.Count(f => f.Completed), failures, jobs.Count(f => f.Completed) != 0 ? Math.Round(failures*100 / (double)jobs.Count(f => f.Completed)) : 0, (jobs.Count(f => f.Completed) - failures) != 0 ? (double)((totalMillisecs / (double)(jobs.Count(f => f.Completed) - failures)) / (double)1000) : -1, Math.Round(jobs.Where(f => f.Completed).Sum(f => f.DownloadedBytes) / (double)1048576, 2))); Dictionary<string, int> timeDistribution = new Dictionary<string, int>(); timeDistribution.Add("[0; 10] sec", 0); timeDistribution.Add("[10; 30] sec", 0); timeDistribution.Add("[30; 60] sec", 0); timeDistribution.Add("[60; ...] sec", 0); foreach (ThreadJob job in jobs.Where(f => f.Completed)) { if (job.TerminatedSuccesfully) { int time = job.ResponseTimeInMilliseconds/1000; if (time <= 10) timeDistribution["[0; 10] sec"]++; if (time > 10 && time <= 30) timeDistribution["[10; 30] sec"]++; if (time > 30 && time <= 60) timeDistribution["[30; 60] sec"]++; if (time > 60) timeDistribution["[60; ...] sec"]++; } } WriteInfo("Time distribution:"); foreach (string key in timeDistribution.Keys) WriteInfo(key + ": " + timeDistribution[key] + " request(s)"); if (failures != 0) { WriteInfo("\nBelow are common failure reasons:"); foreach (string failure in failureReasons.Keys.OrderByDescending(f => failureReasons[f])) WriteInfo(string.Format("'{0}' happened {1} times", failure, failureReasons[failure])); WriteInfo("Error map:"); foreach (var failureTime in errorTimes) WriteInfo(failureTime.Key + ": " + failureTime.Value); } thatsReallyIt = true; //main program can exit } else { if(ShowAllOutput) WriteInfo(string.Format("{0}: second {1}, jobs that second {2}, active requests: {3}", DateTime.Now, currentSecond, loadMap[currentSecond], Engine.counter)); for (int i = 0; i < loadMap[currentSecond]; i++) //how much work happened this second { ThreadJob job = new ThreadJob(string.Format("{0}.{1}", currentSecond, i), currentJob); jobs.Add(job); ThreadPool.QueueUserWorkItem(job.ThreadProc); currentJob++; } currentSecond++; } } System.Threading.Thread.CurrentThread.Priority = ThreadPriority.Normal; }