Почему AsQueryable так медленно работает с Linq? - PullRequest
2 голосов
/ 14 октября 2011

Я столкнулся с довольно глупой проблемой производительности в моем коде. После небольшого исследования я обнаружил, что метод AsQueryable, который я использовал для приведения своего общего списка, замедляет код до 8000 раз. Итак, вопрос в том, почему это? Вот пример

class Program
{
    static void Main(string[] args)
    {
        var c = new ContainerTest();
        c.FillList();

        var s = Environment.TickCount;
        for (int i = 0; i < 10000; ++i)
        {
            c.TestLinq(true);
        }
        var e = Environment.TickCount;
        Console.WriteLine("TestLinq AsQueryable - {0}", e - s);

        s = Environment.TickCount;
        for (int i = 0; i < 10000; ++i)
        {
            c.TestLinq(false);
        }
        e = Environment.TickCount;
        Console.WriteLine("TestLinq as List - {0}", e - s);

        Console.WriteLine("Press enter to finish");
        Console.ReadLine();
    }
}

class ContainerTest
{
    private readonly List<int> _list = new List<int>();
    private IQueryable<int> _q; 

    public void FillList()
    {
        _list.Clear();
        for (int i = 0; i < 10; ++i)
        {
            _list.Add(i);
        }
        _q = _list.AsQueryable();
    }

    public Tuple<int, int> TestLinq(bool useAsQ)
    {
        var upperBorder = useAsQ ? _q.FirstOrDefault(i => i > 7) : _list.FirstOrDefault(i => i > 7);
        var lowerBorder = useAsQ ? _q.TakeWhile(i => i < 7).LastOrDefault() : _list.TakeWhile(i => i < 7).LastOrDefault();            

        return new Tuple<int, int>(upperBorder, lowerBorder);
    }
}

UPD Как я понимаю, я должен как можно больше избегать метода AsQueryable (если он не находится в строке наследования контейнера), потому что я получу немедленно проблема производительности

"и избегай болота в те часы тьмы, когда превозносятся силы зла"

Ответы [ 2 ]

0 голосов
/ 17 октября 2011

Поскольку AsQueryable возвращает IQueryable, который имеет совершенно другой набор методов расширения для стандартных операторов запросов LINQ, чем тот, который предназначен для таких вещей, как List.

Queryable коллекцииподразумевается наличие резервного хранилища СУБД или чего-то подобного, и вы создаете другое, более сложное дерево выражений кода при вызове IQueryable.FirstOrDefault() в отличие от List<>.FirstOrDefault().

0 голосов
/ 14 октября 2011

хотя бы используйте LINQ с List *

ручная реализация всегда будет быстрее, чем LINQ

EDIT

вы знаете, что оба теста не 'дает тот же результат

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...