SortedSet / SortedList с лучшей производительностью LINQ?

предположим, у нас есть отсортированная коллекция, такая как объект sortedset или SortedList С много элементов (10M+). Много запросов происходит, поэтому производительность имеет значение. Из сравнений времени выполнения у меня сложилось впечатление, что LINQ to Objects не использует сортировку, поэтому не использует потенциальный прирост производительности.

первый пример - подсчет элементов в диапазоне:

        var mySortedSet1 = new SortedSet<int>();
        // populate ...
        int rangeCount = (from n in mySortedSet1
                          where ((n >= 1000000000) && (n <= 2000000000))
                          select n).Count();

не совсем уверен, что LINQ Объекты здесь внутренне, в худшем случае это проверка каждого отдельного элемента, который был бы O(n). Это можно сделать намного быстрее, воспользовавшись сортировкой с бинарным поиском нижней и верхней границы в O (log n).

второй пример-SelectMany над списком наборов:

        var myListOfSortedSets = new List<SortedSet<int>>();
        // populate...

        var q = myListOfSortedSets.SelectMany(s => s).OrderBy(s => s);
        foreach (var n in q)
        {
            Console.WriteLine(n);
        }

Если LINQ to SQL объекты должны были воспользоваться сортировкой, это могло эффективно объединить все отсортированные наборы в один большой отсортированный список в O(n). Этот.Заказатьпо на результат может быть проигнорирован, поскольку список уже отсортирован.

вместо этого SelectMany объединяет все отсортированные наборы в один большой (теперь несортированный) список, который потребует другой сортировки O(N log n). Это можно легко проверить, удалив .Порядок и соблюдение порядка, в котором элементы записываются на консоль.

мой вопрос: есть ли уже альтернативная, более эффективная реализация LINQ to SortedSet/SortedList out там?

i4o выглядит очень интересно, но, похоже, требуются вторичные коллекции индексов для повышения производительности запросов в исходной коллекции. Я просто хочу, чтобы запросы в моих отсортированных коллекциях выполнялись быстрее, используя сортировку.

1 ответов


проблема для LINQ заключается в том, что он не может знать, что отсортированный набор упорядочен точно так же, как ожидает запрос. Поскольку любая упорядоченная коллекция может быть создана с помощью IComparer / IComparable / Comparison<T>, нет, зная, что > 500000 на самом деле имеет смысл. Возможно, у вас есть пользовательский метод на компараторе, который сначала сортирует по нечетному/четному, а затем по номеру. В этом случае порядок будет полностью испорчен, и во всех случаях требуется O(n).

Итак, чтобы быть в безопасности, LINQ нужно будет перебирать все элементы в коллекции, даже если она каким-то образом отсортирована. Значение по умолчанию .Where реализация не содержит оптимизации для упорядоченных коллекций.

возможно, удастся создать оптимизированную версию, которая будет учитывать существующий порядок при итерации, но это будет очень сложно сделать и заставить ее работать во всех случаях.

вы можете создать Between метод, который использует GetViewBetween метод SortedSet для возврата новый предзаказ коллекции. Или добавит стандарт .Where как обычно для любого не-предварительно отсортированного набора.

Linq-to-SQL и Entity Framework используют, если IQueryable и фактически переведет ваш запрос Linq на SQL и позволит серверу обрабатывать индексацию, сортировку, фильтрацию и т. д.