Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 内存收集速度慢,每秒约500个请求_Performance_Linq_Asp.net Core - Fatal编程技术网

Performance 内存收集速度慢,每秒约500个请求

Performance 内存收集速度慢,每秒约500个请求,performance,linq,asp.net-core,Performance,Linq,Asp.net Core,我有asp.net Core 3.1 API,每秒约500个请求。 我在一个纯基于内存的集合中进行分页。 该藏品约70万至100万件。 我只使用LINQ“Where”、“OrderBy”、“Take”和“Skip”,这是最简单的分页方法。 假设我的班级是这样的 public class Item { public int Id { get; set; } public string Name { get; set; } public DateTime AgeUtc { g

我有asp.net Core 3.1 API,每秒约500个请求。 我在一个纯基于内存的集合中进行分页。 该藏品约70万至100万件。 我只使用LINQ“Where”、“OrderBy”、“Take”和“Skip”,这是最简单的分页方法。 假设我的班级是这样的

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime AgeUtc { get; set; }
}
private IEnumerable PopulateItems(int?水印,UiParameters resourceParameters)
{
i数不清的项目;
if(水印.HasValue)
{
//验证水印是否小于列表中的第一个水印
var firstKeyValye=MemoryCacheService.Instance.PartitionedReadOnlyItems.First().Key;
if(水印k.Key>=startKey和&k.Key s.Value)
.SelectMany(p=>p.AsEnumerable());
items=PatientLocationsPage
.Where(p=>p.Id>cursor)
.Take(resourceParameters.PageSize);
退货项目;
}
items=MemoryCacheService.Instance.ReadOnlyItems
.Skip((resourceParameters.PageNumber-1)*resourceParameters.PageSize)
.Take(resourceParameters.PageSize);
退货项目;
}

这不是Sql查询,而是内存集合中的查询

哦,孩子。这是行不通的,你在一个有一百万个元素的数据库中进行线性搜索,每秒500次


您需要在集合的顶部实现某种索引,甚至像记录集合中每50个id的索引这样简单,这样您就不必每次都从一开始就使用
。其中(x=>x.id>watermark)
。如果它是按
Id
排序的,即使是二进制搜索也比您现在所做的要好。

您不会解释如何创建
ReadOnlyItems
,但是如果您可以使用
SortedList
,则可以大大加快您的方法

使用
Item.Id
作为键,将您的
项添加到排序列表中

在我对一百万个Id为4:1的
Id
随机
项进行的测试中,
SortedList
的测试时间约为0.02-0.04毫秒,而第一次查找的测试时间约为1.2-4毫秒(或快100倍),后续查找的测试时间约为0.001毫秒,而后续查找的测试时间约为3.5毫秒(或快400倍)

然后,您可以执行以下操作:

private IEnumerable<ItemDto> PopulateItems(int? watermark, UiParameters uiParameters) {
    IEnumerable<ItemDto> items;

    if (watermark.HasValue) {
        var firstIndex = MemoryCacheService.Instance.ReadOnlyItems.IndexOfKey(watermark.Value) + 1;

        items = MemoryCacheService.Instance.ReadOnlyItems.Values
                .Skip(firstIndex + (uiParameters.PageNumber - 1) * uiParameters.PageSize)
                .Take(uiParameters.PageSize);
    }
    else
        items = MemoryCacheService.Instance.ReadOnlyItems.Values
            .Skip((uiParameters.PageNumber - 1) * uiParameters.PageSize)
            .Take(uiParameters.PageSize);

    return items;
}

您尚未显示在表上构建的任何索引。另外,
Take
/
Skip
如果没有
OrderBy
,SQL查询没有顺序。这不是SQL查询,它在内存集合中
MemoryCacheService.Instance.ReadOnlyItems的类型是什么List@NetMage另外,在执行分区解决方案时,我使用ImmutableSortedDictionary,Id是键。。我在“where”语句中使用了它,您不应该将它拆分为更小的列表,因为这将需要为枚举数分配很多资源。您要做的是将指针列表(作为索引,而不是实际指针)存储到现有的大型列表中。不过,理想的情况是,既然您意识到这有多么困难,就应该使用一个已经制作好的内存SQL数据库。例如,Entity Framework对内存中的Sqlite数据库具有一流的支持,您将立即看到它的好处!请你指出我读过的任何资料。我还在关于实体框架的问题中添加了一个“编辑”?请阅读微软的文档
ReadOnlyItems
将使用
IHostedService
每天使用计时器从SQL数据库中填充。在赋值操作过程中,锁定(_syncObj){ReadOnlyItems=newDbItems}
。。。首次请求470709、470710、470711…471708中的ID示例(这是第1/749页…每页1000个项目)。最后一页,我将返回
时间戳:1222686
,这也是本页最后一项中的相同Id。我希望这能回答您的问题。@bunjeeb似乎可以轻松地转换为
SortedList
,但我添加了一个扩展方法,以防。。。
private IEnumerable<ItemDto> PopulateItems(int? watermark, UiParameters uiParameters) {
    IEnumerable<ItemDto> items;

    if (watermark.HasValue) {
        var firstIndex = MemoryCacheService.Instance.ReadOnlyItems.IndexOfKey(watermark.Value) + 1;

        items = MemoryCacheService.Instance.ReadOnlyItems.Values
                .Skip(firstIndex + (uiParameters.PageNumber - 1) * uiParameters.PageSize)
                .Take(uiParameters.PageSize);
    }
    else
        items = MemoryCacheService.Instance.ReadOnlyItems.Values
            .Skip((uiParameters.PageNumber - 1) * uiParameters.PageSize)
            .Take(uiParameters.PageSize);

    return items;
}
public static SortedList<TKey, TValue> ToSortedList<T, TKey, TValue>(this IEnumerable<T> items, Func<T, TKey> keyFn, Func<T, TValue> valueFn) {
    var ans = new SortedList<TKey, TValue>();
    foreach (var item in items)
        ans.Add(keyFn(item), valueFn(item));
    return ans;
}