本文整理汇总了C#中Slice.Memoize方法的典型用法代码示例。如果您正苦于以下问题:C# Slice.Memoize方法的具体用法?C# Slice.Memoize怎么用?C# Slice.Memoize使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Slice
的用法示例。
在下文中一共展示了Slice.Memoize方法的2个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: EstimateCountAsync
/// <summary>Estimate the number of keys in the specified range.</summary>
/// <param name="db">Database used for the operation</param>
/// <param name="beginInclusive">Key defining the beginning of the range</param>
/// <param name="endExclusive">Key defining the end of the range</param>
/// <param name="onProgress">Optional callback called everytime the count is updated. The first argument is the current count, and the second argument is the last key that was found.</param>
/// <param name="cancellationToken">Token used to cancel the operation</param>
/// <returns>Number of keys k such that <paramref name="beginInclusive"/> <= k > <paramref name="endExclusive"/></returns>
/// <remarks>If the range contains a large of number keys, the operation may need more than one transaction to complete, meaning that the number will not be transactionally accurate.</remarks>
public static async Task<long> EstimateCountAsync([NotNull] IFdbDatabase db, Slice beginInclusive, Slice endExclusive, IProgress<FdbTuple<long, Slice>> onProgress, CancellationToken cancellationToken)
{
const int INIT_WINDOW_SIZE = 1 << 8; // start at 256 //1024
const int MAX_WINDOW_SIZE = 1 << 13; // never use more than 4096
const int MIN_WINDOW_SIZE = 64; // use range reads when the windows size is smaller than 64
if (db == null) throw new ArgumentNullException("db");
if (endExclusive < beginInclusive) throw new ArgumentException("The end key cannot be less than the begin key", "endExclusive");
cancellationToken.ThrowIfCancellationRequested();
// To count the number of items in the range, we will scan it using a key selector with an offset equal to our window size
// > if the returned key is still inside the range, we add the window size to the counter, and start again from the current key
// > if the returned key is outside the range, we reduce the size of the window, and start again from the previous key
// > if the returned key is exactly equal to the end of range, OR if the window size was 1, then we stop
// Since we don't know in advance if the range contains 1 key or 1 Billion keys, choosing a good value for the window size is critical:
// > if it is too small and the range is very large, we will need too many sequential reads and the network latency will quickly add up
// > if it is too large and the range is small, we will spend too many times halving the window size until we get the correct value
// A few optimizations are possible:
// > we could start with a small window size, and then double its size on every full segment (up to a maximum)
// > for the last segment, we don't need to wait for a GetKey to complete before issuing the next, so we could split the segment into 4 (or more), do the GetKeyAsync() in parallel, detect the quarter that cross the boundary, and iterate again until the size is small
// > once the window size is small enough, we can switch to using GetRange to read the last segment in one shot, instead of iterating with window size 16, 8, 4, 2 and 1 (the wost case being 2^N - 1 items remaning)
// note: we make a copy of the keys because the operation could take a long time and the key's could prevent a potentially large underlying buffer from being GCed
var cursor = beginInclusive.Memoize();
var end = endExclusive.Memoize();
using (var tr = db.BeginReadOnlyTransaction(cancellationToken))
{
#if TRACE_COUNTING
tr.Annotate("Estimating number of keys in range {0}", FdbKeyRange.Create(beginInclusive, endExclusive));
#endif
tr.SetOption(FdbTransactionOption.ReadYourWritesDisable);
// start looking for the first key in the range
cursor = await tr.Snapshot.GetKeyAsync(FdbKeySelector.FirstGreaterOrEqual(cursor)).ConfigureAwait(false);
if (cursor >= end)
{ // the range is empty !
return 0;
}
// we already have seen one key, so add it to the count
#if TRACE_COUNTING
int iter = 1;
#endif
long counter = 1;
// start with a medium-sized window
int windowSize = INIT_WINDOW_SIZE;
bool last = false;
while (cursor < end)
{
Contract.Assert(windowSize > 0);
var selector = FdbKeySelector.FirstGreaterOrEqual(cursor) + windowSize;
Slice next = Slice.Nil;
FdbException error = null;
try
{
next = await tr.Snapshot.GetKeyAsync(selector).ConfigureAwait(false);
#if TRACE_COUNTING
++iter;
#endif
}
catch (FdbException e)
{
error = e;
}
if (error != null)
{
// => from this point, the count returned will not be transactionally accurate
if (error.Code == FdbError.PastVersion)
{ // the transaction used up its time window
tr.Reset();
}
else
{ // check to see if we can continue...
await tr.OnErrorAsync(error.Code).ConfigureAwait(false);
}
// retry
tr.SetOption(FdbTransactionOption.ReadYourWritesDisable);
continue;
}
//BUGBUG: GetKey(...) always truncate the result to \xFF if the selected key would be past the end,
// so we need to fall back immediately to the binary search and/or get_range if next == \xFF
if (next > end)
//.........这里部分代码省略.........
示例2: Intern
/// <summary>Copy a slice into the buffer, with optional alignement, and return a new identical slice.</summary>
/// <param name="data">Data to copy in the buffer</param>
/// <param name="aligned">If true, align the index of first byte of the slice with a multiple of 8 bytes</param>
/// <returns>Slice that is the equivalent of <paramref name="data"/>, backed by the buffer.</returns>
public Slice Intern(Slice data, bool aligned = false)
{
if (data.Count == 0)
{
// transform into the corresponding Slice.Nil / Slice.Empty singleton
return data.Memoize();
}
SliceHelpers.EnsureSliceIsValid(ref data);
// allocate the slice
var slice = Allocate(data.Count, aligned);
SliceHelpers.CopyBytesUnsafe(slice.Array, slice.Offset, data.Array, data.Offset, data.Count);
return slice;
}