Beispiel #1
0
        public static void IoTest(GenericPerformanceTestRequest request)
        {
            DiskPerformanceResult result;

            using (var tester = AbstractDiskPerformanceTester.ForRequest(request, Console.WriteLine))
            {
                tester.DescribeTestParameters();
                tester.TestDiskIO();
                result = tester.Result;
            }

            var hasReads  = request.OperationType == OperationType.Read || request.OperationType == OperationType.Mix;
            var hasWrites = request.OperationType == OperationType.Write || request.OperationType == OperationType.Mix;

            if (hasReads)
            {
                var sb = new StringBuilder();
                sb.AppendLine(string.Format("Total read: {0}", SizeHelper.Humane(result.TotalRead)));
                sb.AppendLine(string.Format("Average read: {0}/s", SizeHelper.Humane(result.TotalRead / request.TimeToRunInSeconds)));
                sb.AppendLine("Read latency");
                sb.AppendLine(string.Format("\tMin:   {0:#,#.##;;0}", result.ReadLatency.Min));
                sb.AppendLine(string.Format("\tMean:  {0:#,#.##;;0}", result.ReadLatency.Mean));
                sb.AppendLine(string.Format("\tMax:   {0:#,#.##;;0}", result.ReadLatency.Max));
                sb.AppendLine(string.Format("\tStdev: {0:#,#.##;;0}", result.ReadLatency.Stdev));

                sb.AppendLine("Read latency percentiles");
                foreach (var percentile in result.ReadLatency.Percentiles)
                {
                    sb.AppendLine(string.Format("\t{0}: {1:#,#.##;;0}", percentile.Key, percentile.Value));
                }

                sb.AppendLine();
                Console.WriteLine(sb.ToString());
            }
            if (hasWrites)
            {
                var sb = new StringBuilder();
                sb.AppendLine(string.Format("Total write: {0}", SizeHelper.Humane(result.TotalWrite)));
                sb.AppendLine(string.Format("Average write: {0}/s", SizeHelper.Humane(result.TotalWrite / request.TimeToRunInSeconds)));
                sb.AppendLine("Write latency");
                sb.AppendLine(string.Format("\tMin:   {0:#,#.##;;0}", result.WriteLatency.Min));
                sb.AppendLine(string.Format("\tMean:  {0:#,#.##;;0}", result.WriteLatency.Mean));
                sb.AppendLine(string.Format("\tMax:   {0:#,#.##;;0}", result.WriteLatency.Max));
                sb.AppendLine(string.Format("\tStdev: {0:#,#.##;;0}", result.WriteLatency.Stdev));

                sb.AppendLine("Write latency percentiles");
                foreach (var percentile in result.WriteLatency.Percentiles)
                {
                    sb.AppendLine(string.Format("\t{0}: {1:#,#.##;;0}", percentile.Key, percentile.Value));
                }

                sb.AppendLine();
                Console.WriteLine(sb.ToString());
            }
        }
Beispiel #2
0
        public void TestRandomRead()
        {
            var performanceRequest = new GenericPerformanceTestRequest
            {
                FileSize           = (long)128 * 1024,
                OperationType      = OperationType.Read,
                Path               = Path.GetTempPath(),
                Sequential         = false,
                ThreadCount        = 4,
                TimeToRunInSeconds = 5,
                ChunkSize          = 4 * 1024
            };

            var tester = AbstractDiskPerformanceTester.ForRequest(performanceRequest, s => { });

            tester.TestDiskIO();
            var result = tester.Result;

            Assert.Equal(0, result.TotalWrite);
            Assert.True(result.TotalRead > 0);
        }
Beispiel #3
0
        public void TestCanCancelPerformanceTest()
        {
            var cts = new CancellationTokenSource();

            cts.CancelAfter(TimeSpan.FromSeconds(5));

            var performanceRequest = new GenericPerformanceTestRequest
            {
                FileSize           = (long)128 * 1024,
                OperationType      = OperationType.Mix,
                Path               = Path.GetTempPath(),
                Sequential         = false,
                ThreadCount        = 4,
                TimeToRunInSeconds = 30,
                ChunkSize          = 4 * 1024
            };

            var tester = AbstractDiskPerformanceTester.ForRequest(performanceRequest, s => { }, cts.Token);

            Assert.Throws <OperationCanceledException>(() => tester.TestDiskIO());
        }
Beispiel #4
0
        private static void InteractiveRun(string[] args)
        {
            var ioTestRequest = new GenericPerformanceTestRequest();

            string backupLocation            = null;
            string restoreLocation           = null;
            string restoreDatabaseName       = null;
            string restoreFilesystemName     = null;
            bool   restoreDisableReplication = false;
            bool   defrag = false;
            var    requiresRestoreAction = new HashSet <string>();
            bool   isRestoreAction       = false;
            var    requiresIoTestAction  = new HashSet <string>();
            bool   isIoTestAction        = false;
            Action actionToTake          = null;
            bool   launchBrowser         = false;
            bool   noLog = false;
            var    ravenConfiguration  = new RavenConfiguration();
            bool   waitForRestore      = true;
            int?   restoreStartTimeout = 15;

            var optionSet = new OptionSet();

            optionSet.Add("set={==}", OptionCategory.None, "The configuration {0:option} to set to the specified {1:value}", (key, value) =>
            {
                ravenConfiguration.Settings[key] = value;
                ravenConfiguration.Initialize();
            });
            optionSet.Add("nolog", OptionCategory.General, "Don't use the default log", s => noLog = true);
            optionSet.Add("config=", OptionCategory.General, "The config {0:file} to use", ravenConfiguration.LoadFrom);
            optionSet.Add("install", OptionCategory.Service, "Installs the RavenDB service", key => actionToTake = () => AdminRequired(InstallAndStart));
            optionSet.Add("allow-blank-password-use", OptionCategory.Other, "Allow to log on by using a Windows account that has a blank password", key => actionToTake = () => AdminRequired(() => SetLimitBlankPasswordUseRegValue(0)));
            optionSet.Add("deny-blank-password-use", OptionCategory.Other, "Deny to log on by using a Windows account that has a blank password", key => actionToTake   = () => AdminRequired(() => SetLimitBlankPasswordUseRegValue(1)));
            optionSet.Add("service-name=", OptionCategory.Service, "The {0:service name} to use when installing or uninstalling the service, default to RavenDB", name => ProjectInstaller.SERVICE_NAME = name);
            optionSet.Add("uninstall", OptionCategory.Service, "Uninstalls the RavenDB service", key => actionToTake = () => AdminRequired(EnsureStoppedAndUninstall));
            optionSet.Add("start", OptionCategory.Service, "Starts the RavenDB service", key => actionToTake         = () => AdminRequired(StartService));
            optionSet.Add("restart", OptionCategory.Service, "Restarts the RavenDB service", key => actionToTake     = () => AdminRequired(RestartService));
            optionSet.Add("stop", OptionCategory.Service, "Stops the RavenDB service", key => actionToTake           = () => AdminRequired(StopService));
            optionSet.Add("ram", OptionCategory.General, "Run RavenDB in RAM only", key =>
            {
                ravenConfiguration.Settings[Constants.RunInMemory] = "true";
                ravenConfiguration.RunInMemory = true;
                ravenConfiguration.Initialize();
                actionToTake = () => RunInDebugMode(AnonymousUserAccessMode.Admin, ravenConfiguration, launchBrowser, noLog);
            });
            optionSet.Add("debug", OptionCategory.General, "Run RavenDB in debug mode", key => actionToTake = () => RunInDebugMode(null, ravenConfiguration, launchBrowser, noLog));
            optionSet.Add("browser|launchbrowser", OptionCategory.General, "After the server starts, launches the browser", key => launchBrowser = true);
            optionSet.Add("help", OptionCategory.Help, "Help about the command line interface", key =>
            {
                actionToTake = () => PrintUsage(optionSet);
            });
            optionSet.Add("config-help", OptionCategory.Help, "Help about configuration databaseOptions", key =>
            {
                actionToTake = () => PrintConfig(ravenConfiguration.GetConfigOptionsDocs());
            });
            optionSet.Add("restore", OptionCategory.RestoreDatabase, "[Obsolete] Use --restore-system-database or --restore-database", key =>
            {
                actionToTake = () =>
                {
                    throw new OptionException("This method is obsolete, use --restore-system-database or --restore-database", "restore");
                };
                isRestoreAction = true;
            });
            optionSet.Add("restore-system-database", OptionCategory.RestoreDatabase, "Restores a SYSTEM database from backup.", key =>
            {
                actionToTake = () =>
                {
                    if (backupLocation == null || restoreLocation == null)
                    {
                        throw new OptionException("When using --restore-system-database, --restore-source and --restore-destination must be specified", "restore-system-database");
                    }
                    RunSystemDatabaseRestoreOperation(backupLocation, restoreLocation, defrag);
                };
                isRestoreAction = true;
            });
            optionSet.Add("restore-database=", OptionCategory.RestoreDatabase, "Starts a restore operation from a backup on a REMOTE server found under specified {0:url}.", url =>
            {
                actionToTake = () =>
                {
                    if (backupLocation == null)
                    {
                        throw new OptionException("When using --restore-database, --restore-source must be specified", "restore-database");
                    }

                    Uri uri;
                    if (Uri.TryCreate(url, UriKind.Absolute, out uri) == false)
                    {
                        throw new OptionException("Specified destination server url is not valid", "restore-database");
                    }

                    RunRemoteDatabaseRestoreOperation(backupLocation, restoreLocation, restoreDatabaseName, defrag, restoreDisableReplication, uri, waitForRestore, restoreStartTimeout);
                    Environment.Exit(0);
                };
                isRestoreAction = true;
            });
            optionSet.Add("restore-filesystem=", OptionCategory.RestoreFileSystem, "Starts a restore operation from a backup on a REMOTE server found under specified {0:url}.", url =>
            {
                actionToTake = () =>
                {
                    if (backupLocation == null)
                    {
                        throw new OptionException("When using --restore-filesystem, --restore-source must be specified", "restore-filesystem");
                    }

                    Uri uri;
                    if (Uri.TryCreate(url, UriKind.Absolute, out uri) == false)
                    {
                        throw new OptionException("Specified destination server url is not valid", "restore-database");
                    }

                    RunRemoteFilesystemRestoreOperation(backupLocation, restoreLocation, restoreFilesystemName, defrag, uri, waitForRestore, restoreStartTimeout);
                    Environment.Exit(0);
                };
                isRestoreAction = true;
            });
            optionSet.Add("restore-disable-replication", OptionCategory.RestoreDatabase, "Disables replication destinations in newly restored database", value =>
            {
                restoreDisableReplication = true;
                requiresRestoreAction.Add("restore-disable-replication");
            });
            optionSet.Add("restore-no-wait", OptionCategory.RestoreDatabase | OptionCategory.RestoreFileSystem, "Return immediately without waiting for a restore to complete", value =>
            {
                waitForRestore = false;
                requiresRestoreAction.Add("restore-no-wait");
            });
            optionSet.Add("restore-start-timeout=", OptionCategory.RestoreDatabase | OptionCategory.RestoreFileSystem, "The maximum {0:timeout} in seconds to wait for another restore to complete. Default: 15 seconds.", value =>
            {
                int timeout;
                if (int.TryParse(value, out timeout) == false)
                {
                    throw new OptionException("Specified restore start timeout is not valid", "restore-start-timeout");
                }
                restoreStartTimeout = timeout;
                requiresRestoreAction.Add("restore-start-timeout");
            });
            optionSet.Add("restore-defrag", OptionCategory.RestoreDatabase | OptionCategory.RestoreFileSystem, "Applicable only during restore, execute defrag after the restore is completed", key =>
            {
                defrag = true;
                requiresRestoreAction.Add("restore-defrag");
            });
            optionSet.Add("restore-destination=", OptionCategory.RestoreDatabase | OptionCategory.RestoreFileSystem, "The {0:path} of the new database. If not specified it will be located in default data directory", value =>
            {
                restoreLocation = value;
                requiresRestoreAction.Add("restore-destination");
            });
            optionSet.Add("restore-source=", OptionCategory.RestoreDatabase | OptionCategory.RestoreFileSystem, "The {0:path} of the backup", value =>
            {
                backupLocation = value;
                requiresRestoreAction.Add("restore-source");
            });
            optionSet.Add("restore-database-name=", OptionCategory.RestoreDatabase, "The {0:name} of the new database. If not specified, it will be extracted from backup. Only applicable during REMOTE restore", value =>
            {
                restoreDatabaseName = value;
                requiresRestoreAction.Add("restore-database-name");
            });
            optionSet.Add("restore-filesystem-name", OptionCategory.RestoreFileSystem, "The {0:name} of the new filesystem. If not specified, it will be extracted from backup.", value =>
            {
                restoreFilesystemName = value;
                requiresRestoreAction.Add("restore-filesystem-name");
            });
            optionSet.Add("io-test=", OptionCategory.IOTest, "Performs disk io test using {0:dir} as temporary dir path", path =>
            {
                ioTestRequest.Path = path;
                actionToTake       = () => IoTest(ioTestRequest);
                isIoTestAction     = true;
            });
            optionSet.Add("io-test-file-size=", OptionCategory.IOTest, "The {0:size} of test file for io test in MB (default: 1024MB)", value =>
            {
                int fileSize;
                if (int.TryParse(value, out fileSize) == false)
                {
                    throw new OptionException("Specified test file size is not valid", "io-test-file-size");
                }
                ioTestRequest.FileSize = fileSize * 1024 * 1024;
                requiresIoTestAction.Add("io-test-file-size");
            });
            optionSet.Add("io-test-threads=", OptionCategory.IOTest, "The {0:number} of threads to use during test", value =>
            {
                int threads;
                if (int.TryParse(value, out threads) == false)
                {
                    throw new OptionException("Specified amount of threads is not valid", "io-test-threads");
                }
                ioTestRequest.ThreadCount = threads;
                requiresIoTestAction.Add("io-test-threads");
            });
            optionSet.Add("io-test-time=", OptionCategory.IOTest, "The {0:number} of seconds to run the test (default: 30)", value =>
            {
                int testTime;
                if (int.TryParse(value, out testTime) == false)
                {
                    throw new OptionException("Specified test time is not valid", "io-test-time");
                }
                ioTestRequest.TimeToRunInSeconds = testTime;
                requiresIoTestAction.Add("io-test-time");
            });
            optionSet.Add("io-test-seed=", OptionCategory.IOTest, "The {0:seed} for random generator", value =>
            {
                int seed;
                if (int.TryParse(value, out seed) == false)
                {
                    throw new OptionException("Specified random seed is not valid", "io-test-seed");
                }
                ioTestRequest.RandomSeed = seed;
                requiresIoTestAction.Add("io-test-seed");
            });
            optionSet.Add("io-test-mode=", OptionCategory.IOTest, "The operation {0:mode} (read,write,mix) (default: write)", value =>
            {
                OperationType opType;
                if (Enum.TryParse(value, true, out opType) == false)
                {
                    throw new OptionException("Specified test mode is not valid", "io-test-mode");
                }
                ioTestRequest.OperationType = opType;
                requiresIoTestAction.Add("io-test-mode");
            });
            optionSet.Add("io-test-chunk-size=", OptionCategory.IOTest, "The {0:value} for chunk size in KB (default: 4 KB)", value =>
            {
                int chunkSize;
                if (int.TryParse(value, out chunkSize) == false)
                {
                    throw new OptionException("Specified test chunk size is not valid", "io-test-chunk-size");
                }
                ioTestRequest.ChunkSize = chunkSize * 1024;
                requiresIoTestAction.Add("io-test-chunk-size");
            });
            optionSet.Add("io-test-sequential", OptionCategory.IOTest, "Perform sequential read/write (default: random)", value =>
            {
                ioTestRequest.Sequential = true;
                requiresIoTestAction.Add("io-test-sequential");
            });
            optionSet.Add("io-test-buffering-type", OptionCategory.IOTest, "Buffering type (None,Read, ReadAndWrite) (default: None)", value =>
            {
                BufferingType bufferingType;
                if (Enum.TryParse(value, true, out bufferingType) == false)
                {
                    throw new OptionException("Specified buffering type is not valid", "io-test-buffering-type");
                }
                ioTestRequest.BufferingType = bufferingType;
                requiresIoTestAction.Add("io-test-buffering-type");
            });
            optionSet.Add("encrypt-self-config", OptionCategory.Encryption, "Encrypt the RavenDB configuration file", file =>
            {
                actionToTake = () => ProtectConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            });
            optionSet.Add("encrypt-config=", OptionCategory.Encryption, "Encrypt the specified {0:configuration file}", file =>
            {
                actionToTake = () => ProtectConfiguration(file);
            });
            optionSet.Add("decrypt-self-config", OptionCategory.Encryption, "Decrypt the RavenDB configuration file", file =>
            {
                actionToTake = () => UnprotectConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            });
            optionSet.Add("decrypt-config=", OptionCategory.Encryption, "Decrypt the specified {0:configuration file}", file =>
            {
                actionToTake = () => UnprotectConfiguration(file);
            });
            optionSet.Add("installSSL={==}", OptionCategory.SSL, "Bind X509 certificate specified in {0:option} with optional password from {1:option} with 'Raven/Port'.", (sslCertificateFile, sslCertificatePassword) =>
            {
                actionToTake = () => InstallSsl(sslCertificateFile, sslCertificatePassword, ravenConfiguration);
            });
            optionSet.Add("uninstallSSL={==}", OptionCategory.SSL, "Unbind X509 certificate specified in {0:option} with optional password from {2:option} from 'Raven/Port'.", (sslCertificateFile, sslCertificatePassword) =>
            {
                actionToTake = () => UninstallSsl(sslCertificateFile, sslCertificatePassword, ravenConfiguration);
            });
            optionSet.Add("update-version=", OptionCategory.Update, "Updates the specified {0:databaseName} to newest version", dbName =>
            {
                actionToTake = () => UpdateVersion(dbName);
            });

            try
            {
                if (args.Length == 0)                 // we default to executing in debug mode
                {
                    args = new[] { "--debug" }
                }
                ;

                optionSet.Parse(args);
            }
            catch (Exception e)
            {
                ConsoleWriteLineWithColor(ConsoleColor.Red, e.Message);
                PrintUsage(optionSet);
                ConsoleWriteLineWithColor(ConsoleColor.Red, e.Message);
                Environment.Exit(-1);
                return;
            }

            if (!isRestoreAction && requiresRestoreAction.Any())
            {
                var joinedActions = string.Join(", ", requiresRestoreAction);
                throw new OptionException(string.Format("When using {0}, --restore-source must be specified", joinedActions), joinedActions);
            }

            if (!isIoTestAction && requiresIoTestAction.Any())
            {
                var joinedActions = string.Join(", ", requiresRestoreAction);
                throw new OptionException(string.Format("When using {0}, --io-test must be specified", joinedActions), joinedActions);
            }

            if (actionToTake == null)
            {
                actionToTake = () => RunInDebugMode(null, ravenConfiguration, launchBrowser, noLog);
            }

            actionToTake();
        }