我的扩展方法能够改进吗?BlockBlobClient GetBlockById dotnet

huangapple go评论51阅读模式
英文:

My extension method can get better? BlockBlobClient GetBlockById dotnet

问题

我已经为BlockBlobClient创建了一个扩展方法,用于根据块ID获取特定块,并且我想知道是否可以调整此代码片段以提高性能或其他方面的优化。

public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks.ToList();
    
    var currentBlock = blockList.FirstOrDefault(a => a.Name == blockId);

    if (currentBlock.Name == null)
    {
        throw new InvalidOperationException($"Could not find BlockId {blockId}");
    }
    
    var length = currentBlock.SizeLong;
    var index = blockList.FindIndex(a => a.Name == blockId);

    var offset = 0L;
    for (var i = 0; i < index; i++)
    {
        offset += blockList[i].SizeLong;
    }

    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
英文:

I've made an extension method for the BlockBlobClient, to get a specific block by block id, and I want to know if this code snippet can be tweaked to increase performance/other things

public static async Task&lt;T&gt; GetBlockByIdAsync&lt;T&gt;(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
	var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
	var blockList = blockListResponse.Value.CommittedBlocks.ToList();
			
	var currentBlock = blockList.FirstOrDefault(a =&gt; a.Name == blockId);

	if (currentBlock.Name == null)
	{
		throw new InvalidOperationException($&quot;Could not find BlockId {blockId}&quot;);
	}
			
	var length = currentBlock.SizeLong;
	var index = blockList.FindIndex(a =&gt; a.Name == blockId);

	var offset = 0L;
	for (var i = 0; i &lt; index; i++)
	{
		offset += blockList[i].SizeLong;
	}

	var options = new BlobDownloadOptions()
	{
		Range = new HttpRange(offset, length)
	};

	var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

	return JsonSerializer.Deserialize&lt;T&gt;(blockInfo.Value.Content);
}

答案1

得分: 2

以下是代码部分的翻译:

  1. blockList.FirstOrDefault(a => a.Name == blockId)

    • 用第一个满足条件的元素,其Name等于blockId的元素。
  2. blockList.FindIndex(a => a.Name == blockId)

    • 找到第一个满足条件的元素索引,其Name等于blockId的元素。
  3. for (var i = 0; i < index; i++)

    • 使用循环,从0遍历到index。

这是你提供的代码的翻译:

public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks.ToList();

    var length = 0L;
    var offset = 0L;

    // 遍历所有块,直到找到所需的块。
    foreach (var block in blockList){
        if (block.Name == blockId){
            length = block.SizeLong;
            break;
        }

        // 如果尚未找到所需的块,则更新偏移量。
        offset += block.SizeLong;
    }

    // 检查是否找到了所需的块。
    if (length == 0)
    {
        throw new InvalidOperationException($"无法找到块标识 {blockId}");
    }
            
    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}

“CAVEAT”部分表示注意事项,提醒可能存在代码错误但思路正确。在“UPDATE”部分中,作者提到可能进一步提高效率的方法。

英文:

The only thing that really stands out is the multiple iteration (3 times) of blockList.

  1. blockList.FirstOrDefault(a =&gt; a.Name == blockId)
  2. blockList.FindIndex(a =&gt; a.Name == blockId)
  3. for (var i = 0; i &lt; index; i++)

You can do this with a single iteration, something like this.

public static async Task&lt;T&gt; GetBlockByIdAsync&lt;T&gt;(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks.ToList();

    var length = 0L;
    var offset = 0L;

    // iterate over all blocks until we find the block we want.
    foreach (var block in blockList){
        if (block.Name == blockId){
            length = block.SizeLong;
            break;
        }

        // We haven&#39;t found the block we want yet so update the offset.
        offset += block.SizeLong;
    }

    // Check if we found the block we were looking for.
    if (length == 0)
    {
        throw new InvalidOperationException($&quot;Could not find BlockId {blockId}&quot;);
    }
            
    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize&lt;T&gt;(blockInfo.Value.Content);
}

CAVEAT I haven't run this code locally or even tried to compile it so there may be errors but the idea is sound.

UPDATE There was an iteration that I missed: blockListResponse.Value.CommittedBlocks.ToList();

Granted, calling to list prevents any repeated calls to CommittedBlocks but this could be even more efficient.

Assuming blockListResponse.Value.CommittedBlocks returns IEnumerable<T>` you could even remove this...

public static async Task&lt;T&gt; GetBlockByIdAsync&lt;T&gt;(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
    var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
    var blockList = blockListResponse.Value.CommittedBlocks;

    var length = 0L;
    var offset = 0L;

    // iterate over all blocks until we find the block we want.
    var blockListEnumerator = blockList.GetEnumerator();
    while (blockListEnumerator.MoveNext())
    {
        var block = blockListEnumerator.Current as BlobBlock;

        if (block.Name == blockId){
            length = block.SizeLong;
            break;
        }

        // We haven&#39;t found the block we want yet so update the offset.
        offset += block.SizeLong;
    }

    // Check if we found the block we were looking for.
    if (length == 0)
    {
        throw new InvalidOperationException($&quot;Could not find BlockId {blockId}&quot;);
    }
            
    var options = new BlobDownloadOptions()
    {
        Range = new HttpRange(offset, length)
    };

    var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);

    return JsonSerializer.Deserialize&lt;T&gt;(blockInfo.Value.Content);
}

huangapple
  • 本文由 发表于 2023年3月7日 18:57:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75661095.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定