private static String BuildPerformanceMeasurementConfigurationString(bool enabled                  = true,
                                                                             float simulationDuration      = 100.0f,
                                                                             int logCount                  = 1,
                                                                             int histogramBins             = 16,
                                                                             bool recordRealizationCpuTime = true,
                                                                             bool recordSolverStepTicks    = true,
                                                                             bool recordSolverSteps        = true,
                                                                             bool recordReactionFirings    = true,
                                                                             PerformanceMeasurementConfigurationParameters.LoggingFileFormat logFileFormat = PerformanceMeasurementConfigurationParameters.LoggingFileFormat.JSON,
                                                                             string logFilenamePrefix = "perflog",
                                                                             bool compressOutput      = false)
        {
            var stringBuilder = new StringBuilder();

            // Double literal '{' in format string since single '{' delimits an argument.
            stringBuilder.AppendFormat("{{\"duration\":{0},\"perf\":{{", simulationDuration);
            stringBuilder.AppendFormat("\"Enabled\":{0},", enabled.ToString(CultureInfo.InvariantCulture).ToLower());
            stringBuilder.AppendFormat("\"LogCount\":{0},", logCount);
            stringBuilder.AppendFormat("\"HistogramBins\":{0},", histogramBins);
            stringBuilder.AppendFormat("\"RecordRealizationCpuTime\":{0},", recordRealizationCpuTime.ToString(CultureInfo.InvariantCulture).ToLower());
            stringBuilder.AppendFormat("\"RecordSolverStepTicks\":{0},", recordSolverStepTicks.ToString(CultureInfo.InvariantCulture).ToLower());
            stringBuilder.AppendFormat("\"RecordSolverSteps\":{0},", recordSolverSteps.ToString(CultureInfo.InvariantCulture).ToLower());
            stringBuilder.AppendFormat("\"RecordReactionFirings\":{0},", recordReactionFirings.ToString(CultureInfo.InvariantCulture).ToLower());
            stringBuilder.AppendFormat("\"LogFileFormat\":\"{0}\",", logFileFormat);
            stringBuilder.AppendFormat("\"LogFilenamePrefix\":\"{0}\",", logFilenamePrefix.Replace(@"\", @"\\"));
            stringBuilder.AppendFormat("\"CompressOutput\":{0}", compressOutput.ToString(CultureInfo.InvariantCulture).ToLower());
            stringBuilder.Append("}}");
            return(stringBuilder.ToString());
        }
        public void PerfMeasurementConfigParamsCtorFromConfig()
        {
            const int logCount      = 42;
            const int histogramBins = 20;
            const PerformanceMeasurementConfigurationParameters.LoggingFileFormat logFileFormat = PerformanceMeasurementConfigurationParameters.LoggingFileFormat.CSV;
            const string logFilenamePrefix = "logfile";
            var          configString      = BuildPerformanceMeasurementConfigurationString(enabled: true,
                                                                                            simulationDuration: TestDuration,
                                                                                            logCount: logCount,
                                                                                            histogramBins: histogramBins,
                                                                                            recordRealizationCpuTime: false,
                                                                                            recordSolverStepTicks: false,
                                                                                            recordSolverSteps: false,
                                                                                            recordReactionFirings: false,
                                                                                            logFileFormat: logFileFormat,
                                                                                            logFilenamePrefix: logFilenamePrefix,
                                                                                            compressOutput: true);
            var config       = Configuration.ConfigurationFromString(configString);
            var configParams = new PerformanceMeasurementConfigurationParameters(config, TestDuration);

            Assert.IsTrue(configParams.Enabled);
            Assert.AreEqual(TestDuration, configParams.SimulationDuration);
            Assert.AreEqual(logCount, configParams.LogCount);
            Assert.AreEqual(histogramBins, configParams.HistogramBins);
            Assert.IsFalse(configParams.RecordRealizationCpuTime);
            Assert.IsFalse(configParams.RecordSolverStepTicks);
            Assert.IsFalse(configParams.RecordSolverSteps);
            Assert.IsFalse(configParams.RecordReactionFirings);
            Assert.AreEqual(logFileFormat, configParams.LogFileFormat);
            Assert.AreEqual(logFilenamePrefix, configParams.LogFilenamePrefix);
            Assert.IsTrue(configParams.CompressOutput);
            Assert.AreEqual(logFilenamePrefix + ".csv.gz", configParams.WorkingFilename);
        }
/*
 *      [Test]
 *      public void PerfLogging()
 *      {
 *          var configuration = BuildPerformanceMeasurementConfiguration();
 *          var perf = new PerformanceMeasurements(VersionInfo.Version, VersionInfo.Description, configuration);
 *          const int realizationCount = 16;
 *
 *          perf.StartMeasurement();
 *          for (int realization = 0; realization < realizationCount; realization++)
 *          {
 *              perf.StartRealization();
 *              for (int step = 0; step < perf.FrameCount; step++)
 *              {
 *                  // Log 3/4 of the way through each interval so there is one step and one reaction
 *                  // per logging bin.
 *                  Thread.Sleep(10);
 *                  float tau = Math.Min((step+0.75f)*perf.SimulationDuration/perf.FrameCount, perf.SimulationDuration);
 *                  // Console.WriteLine("LogStep(1, {0})", tau);
 *                  perf.LogStep(1, tau);
 * //                     Assert.GreaterOrEqual(perf.SolverSteps[step].Sum(), 0, "SolverSteps should be >= 0.");
 * //                     Assert.GreaterOrEqual(perf.ReactionFirings[step].Sum(), 0, "ReactionFirings should be > 0.");
 * //                     Assert.Greater(perf.StepTicks[step].Sum(), 0, "StepTimes should be > 0.");
 *              }
 *              perf.EndRealization();
 * //                 Assert.Greater(perf.RealizationTimes.SampleCount, 0, "RealizationTimes should be > 0.");
 *          }
 *          perf.EndMeasurement();
 *
 * //             Assert.Greater(perf.TotalTimeTicks, 0.0f, "TotalTime should be > 0.");
 * //             Assert.GreaterOrEqual(perf.TotalTimeTicks, perf.RealizationTimes.Sum());
 *
 *          WriteMeasurementsToConsole(perf);
 *      }
 */

/*
 *      private static void WriteMeasurementsToConsole(PerformanceMeasurements perf)
 *      {
 *          Console.WriteLine();
 *          Console.Write("SolverSteps: ");
 *          foreach (var vector in perf.SolverSteps)
 *              foreach (var count in vector)
 *              {
 *                  Console.Write("{0} ", count);
 *              }
 *
 *          Console.WriteLine();
 *          Console.Write("ReactionFirings: ");
 *          foreach (var vector in perf.ReactionFirings)
 *              foreach (var count in vector)
 *              {
 *                  Console.Write("{0} ", count);
 *              }
 *
 *          Console.WriteLine();
 *          Console.Write("StepTimes: ");
 *          foreach (var vector in perf.StepTicks)
 *              foreach (var count in vector)
 *              {
 *                  Console.Write("{0} ", count);
 *              }
 *
 *          Console.WriteLine();
 *          Console.Write("RealizationTimes: ");
 *          foreach (var count in perf.RealizationTimes)
 *          {
 *              Console.Write("{0} ", count);
 *          }
 *
 *          Console.WriteLine();
 *          Console.WriteLine("Tick frequency: {0}", perf.TickFrequency);
 *      }
 */

/*
 *      [Test]
 *      public void PerfLoggingToo()
 *      {
 *          var configuration = BuildPerformanceMeasurementConfiguration();
 *          var perf = GeneratePerformanceMeasurements(configuration);
 *
 *          Assert.Greater(perf.TotalTimeTicks, 0.0f, "TotalTime should be > 0.");
 *
 *          Assert.GreaterOrEqual(perf.TotalTimeTicks, perf.RealizationTimes[0]);
 *          Assert.GreaterOrEqual(perf.RealizationTimes[0], perf.StepTicks[0].Sum());
 *          Assert.AreEqual(16, perf.SolverSteps[0].Sum());
 *          Assert.AreEqual(816, perf.ReactionFirings[0].Sum());
 *
 *          WriteMeasurementsToConsole(perf);
 *      }
 */

        private static PerformanceMeasurementConfigurationParameters BuildPerformanceMeasurementConfiguration(bool enabled = true, int logCount = 16, int histogramBins = 16, PerformanceMeasurementConfigurationParameters.LoggingFileFormat logFileFormat = PerformanceMeasurementConfigurationParameters.LoggingFileFormat.JSON, String logFilenamePrefix = "perflog", bool compressOutput = false, float duration = 48.0f)
        {
            var configString = BuildPerformanceMeasurementConfigurationString(enabled: enabled, logCount: logCount, histogramBins: histogramBins, logFileFormat: logFileFormat, logFilenamePrefix: logFilenamePrefix, compressOutput: compressOutput);
            var config       = Configuration.ConfigurationFromString(configString);
            var perfConfig   = new PerformanceMeasurementConfigurationParameters(config, duration);

            return(perfConfig);
        }