private async Task PushQueueAsync(IFdbTransaction tr, IDynamicKeySubspace queue, Slice taskId) { //TODO: use a high contention algo ? // - must support Push and Pop // - an empty queue must correspond to an empty subspace // get the current size of the queue var range = queue.ToRange(); var lastKey = await tr.Snapshot.GetKeyAsync(KeySelector.LastLessThan(range.End)).ConfigureAwait(false); int count = lastKey < range.Begin ? 0 : queue.DecodeFirst <int>(lastKey) + 1; // set the value tr.Set(queue.Encode(count, GetRandomId()), taskId); }
private static async Task BenchSerialWriteAsync(IFdbDatabase db, int N, CancellationToken ct) { // read a lot of small keys, one by one Console.WriteLine($"=== BenchSerialWrite(N={N:N0}) ==="); var location = db.Root.ByKey("hello"); var sw = Stopwatch.StartNew(); IFdbTransaction trans = null; IDynamicKeySubspace subspace = null; try { for (int i = 0; i < N; i++) { if (trans == null) { trans = await db.BeginTransactionAsync(ct); subspace = await location.Resolve(trans); } trans.Set(subspace.Encode(i), Slice.FromInt32(i)); if (trans.Size > 100 * 1024) { await trans.CommitAsync(); trans.Dispose(); trans = null; } } await trans.CommitAsync(); } finally { trans?.Dispose(); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:N3} sec to read {N:N0} items ({FormatTimeMicro(sw.Elapsed.TotalMilliseconds / N)}/read, {N/sw.Elapsed.TotalSeconds:N0} read/sec)"); Console.WriteLine(); }
private async Task <KeyValuePair <Slice, Slice> > FindRandomItem(IFdbTransaction tr, IDynamicKeySubspace ring) { var range = ring.ToRange(); // start from a random position around the ring var key = ring.Encode(GetRandomId()); // We want to find the next item in the clockwise direction. If we reach the end of the ring, we "wrap around" by starting again from the start // => So we do find_next(key <= x < MAX) and if that does not produce any result, we do a find_next(MIN <= x < key) // When the ring only contains a few items (or is empty), there is more than 50% change that we wont find anything in the first read. // To reduce the latency for this case, we will issue both range reads at the same time, and discard the second one if the first returned something. // This should reduce the latency in half when the ring is empty, or when it contains only items before the random key. var candidate = await tr.GetRange(key, range.End).FirstOrDefaultAsync(); if (!candidate.Key.IsPresent) { candidate = await tr.GetRange(range.Begin, key).FirstOrDefaultAsync(); } return(candidate); }