Как ускорить типизированные сборки в 10gen официальном драйвере MongoDB C#?

Профилируя мое приложение, я обнаружил неприятный факт: типизированный сборщик Upadte<> (и Query<>) оценивает лямбда-выражения для каждого запроса, потребляя много ресурсов ЦП. Вы получите несколько процентов ЦП, переключившись с красивого современного типа UpdateBuilder<> на:

var u = Update<MyPerson>.Inc(e => e.Age, Age);

к старым добрым статическим строкам:

var u = Update.Inc("Age", Age);

Та же проблема с QueryBuilder<>, он также оценивает выражения для каждого запроса и тратит впустую ценные ресурсы процессора.

Официальная страница драйвера LINQ гласит:

Компилятор C# все равно переводит все запросы, написанные с использованием синтаксиса запросов, в лямбда-синтаксис, поэтому нет никакого преимущества в производительности или штрафа при выборе любого стиля.

Да, это правда, если вы выбираете между двумя синтаксисами LINQ. Но существует огромная разница в производительности между использованием и не использованием синтаксиса LINQ. Накладные расходы зависят от того, как часто ваш клиент выполняет запросы. В моем случае разница выше 30%!

Интересно, есть ли способ получить хороший типизированный синтаксис и производительность одновременно?

Простое кэширование результатов компоновщика не является ответом, поскольку нам, очевидно, необходимо передавать динамические параметры в каждый запрос. Нам нужно найти способ "предварительно скомпилировать" дорогостоящую часть процессора (в отношении вычисления лямбда-выражений), но сохранить динамические параметры (например, индексы массива).

1 ответ

Абзац, который вы цитировали:

Компилятор C# все равно переводит все запросы, написанные с использованием синтаксиса запросов, в лямбда-синтаксис, поэтому нет никакого преимущества в производительности или штрафа при выборе любого стиля.

Относится к двум синтаксисам, доступным для написания запросов LINQ.

var query =
    from e in collection.AsQueryable<Employee>()
    where e.FirstName == "John"
    select e;

или же

var query =
    collection.AsQueryable<Employee>()
    .Where(e => e.FirstName == "John");

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

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

Другие вопросы по тегам