public async Task RunTests() { if (Parallelism < 1) { Parallelism = 1; } if (NumberOfQueryResultsPrimary < 1) { NumberOfQueryResultsPrimary = 1; } if (NumberOfQueryResultsSecondary < 1) { NumberOfQueryResultsSecondary = 1; } PrimaryClient = DbHelper.PrimaryClient; if (DbHelper.Clients.Length == 1) { // If there is only one client available, use also as secondary SecondaryClient = PrimaryClient; } else { // Make sure we don't take the primary client SecondaryClient = DbHelper.Clients.Where(c => c != PrimaryClient).Last(); } WritesPrimary = await RunCreateTest("WritesPrimary", PrimaryClient, NumberOfWritesPrimary); WritesSecondary = await RunCreateTest("WritesSecondary", SecondaryClient, NumberOfWritesSecondary); QueryPrimary = await RunTest("QueryPrimary", async() => playersPrimary = await DbHelper.Query <Player>(PrimaryClient, $"TOP {NumberOfQueryResultsPrimary}", null, Player.CollectionId), NumberOfQueryResultsPrimary); QuerySecondary = await RunTest("QuerySecondary", async() => playersSecondary = await DbHelper.Query <Player>(SecondaryClient, $"TOP {NumberOfQueryResultsSecondary}", null, Player.CollectionId), NumberOfQueryResultsSecondary); RandomReadsPrimary = await RunRandomReadTest("RandomReadsPrimary", PrimaryClient, NumberOfRandomReadsPrimary, playersPrimary); RandomReadsSecondary = await RunRandomReadTest("RandomReadsSecondary", SecondaryClient, NumberOfRandomReadsSecondary, playersSecondary); UpsertsPrimary = await RunUpsertTest("UpsertsPrimary", PrimaryClient, NumberOfUpsertsPrimary, playersPrimary); UpsertsSecondary = await RunUpsertTest("UpsertsSecondary", SecondaryClient, NumberOfUpsertsSecondary, playersSecondary); }
private async Task <Results> RunCreateTest(string testName, DbClientInfo client, int count) { var stopWatch = Stopwatch.StartNew(); var prevRequestCharge = DbHelper.RequestCharge; counter = 0; var tasks = Enumerable.Range(0, Parallelism).Select(i => Task.Run(Create)).ToArray(); await Task.WhenAll(tasks); var results = new Results { ElapsedMilliseconds = stopWatch.ElapsedMilliseconds, RUCost = DbHelper.RequestCharge - prevRequestCharge, Name = testName, NumberOfOperations = count }; return(results); async Task Create() { try { while (true) { var i = System.Threading.Interlocked.Increment(ref counter); if (i > count) { return; } var player = Player.New(); player.ClientName = client.Name; await DbHelper.Create(player, Player.CollectionId); } } catch (DocumentClientException ex) { // If we get any DocumentClientException (for instance a RequestRateTooLargeException) - quit this task // Maybe should notify the user? } } }
public static async Task <T[]> Query <T>(DbClientInfo client, string top, string filter, string collectionId) where T : IDocument { var uri = UriFactory.CreateDocumentCollectionUri(DatabaseId, collectionId); if (!string.IsNullOrEmpty(filter)) { filter = "WHERE " + filter; } else { filter = filter ?? ""; } top = top ?? ""; var sql = new SqlQuerySpec($"SELECT {top} * FROM {collectionId} AS c {filter}"); var query = client.DocumentClient.CreateDocumentQuery <T>(uri, sql, new FeedOptions { EnableCrossPartitionQuery = true }).AsDocumentQuery(); var results = new List <T>(); while (query.HasMoreResults) { var items = await query.ExecuteNextAsync <T>(); results.AddRange(items.AsEnumerable()); RequestCharge += items.RequestCharge; } foreach (var item in results) { item.ClientName = client.Name; } return(results.ToArray()); }
static DbHelper() { // Init basic settings DatabaseId = ConfigurationManager.AppSettings["DatabaseId"]; InitialThroughput = int.Parse(ConfigurationManager.AppSettings["InitialThroughput"]); MaxConnectionLimit = int.Parse(ConfigurationManager.AppSettings["MaxConnectionLimit"]); ConsistencyLevel = (ConsistencyLevel)Enum.Parse(typeof(ConsistencyLevel), ConfigurationManager.AppSettings["ConsistencyLevel"]); var endpointUrls = ConfigurationManager.AppSettings["EndpointURLs"].Split(delimiter, StringSplitOptions.RemoveEmptyEntries); var authKeys = ConfigurationManager.AppSettings["AuthKeys"].Split(delimiter, StringSplitOptions.RemoveEmptyEntries); if (endpointUrls.Length != authKeys.Length || endpointUrls.Length == 0) { throw new Exception("Invalid configuration of EndpointURLs and AuthKeys"); } // Server specific settings ServerName = Environment.GetEnvironmentVariable("APPSETTING_WEBSITE_SITE_NAME") ?? "local"; // The name of the app service ServerSuffix = ServerName.Contains("-") ? $"-{ServerName.Split('-')[1]}" : ""; // Will be -eastus, -westeu or similar PreferredLocations = (ConfigurationManager.AppSettings["PreferredLocations" + ServerSuffix] ?? "").Split(delimiter, StringSplitOptions.RemoveEmptyEntries); // Create connection poliy (same for all endpoints/clients) var connectionPolicy = new ConnectionPolicy { ConnectionMode = (ConnectionMode)Enum.Parse(typeof(ConnectionMode), ConfigurationManager.AppSettings["ConnectionMode"]), ConnectionProtocol = (Protocol)Enum.Parse(typeof(Protocol), ConfigurationManager.AppSettings["ConnectionProtocol"]), EnableEndpointDiscovery = true, MaxConnectionLimit = MaxConnectionLimit, RetryOptions = new RetryOptions { MaxRetryAttemptsOnThrottledRequests = 10, MaxRetryWaitTimeInSeconds = 30 } }; foreach (var location in PreferredLocations) { connectionPolicy.PreferredLocations.Add(location); } // Create clients Clients = new DbClientInfo[endpointUrls.Length]; for (var i = 0; i < Clients.Length; i++) { var client = new DbClientInfo(); client.Name = new Uri(endpointUrls[i]).Host.Split('.').First(); client.DocumentClient = new DocumentClient(new Uri(endpointUrls[i]), authKeys[i], connectionPolicy, ConsistencyLevel); client.DocumentClient.OpenAsync(); // Preload routing tables client.IsPrimaryClient = ServerSuffix.Length != 0 && endpointUrls[i].Contains(ServerSuffix); Clients[i] = client; } // Detect primary client if (Clients.Where(c => c.IsPrimaryClient).Count() >= 1) { PrimaryClient = Clients.Where(c => c.IsPrimaryClient).First(); } else { PrimaryClient = Clients.First(); } ResetRequestCharge(); }