Производительность обоих обычно одинакова, поскольку деревья выражений внутренне просматриваются и генерируются как IL с использованием тех же базовых системных функций, которые вы использовали бы сами. Теоретически возможно испускать более эффективный IL, используя низкоуровневые функции, но я сомневаюсь, что будет какой-либо практически важный прирост производительности. Это будет зависеть от задачи, но я не пришел ни к какой практической оптимизации испускаемого IL по сравнению с тем, который испускается деревьями выражений.
Я настоятельно рекомендую приобрести инструмент под названием ILSpy для обратной компиляции сборок CLR. При этом вы можете посмотреть на код, фактически пересекающий деревья выражений и фактически испускающий IL.
Наконец, предостережение. Я использовал деревья выражений в синтаксическом анализаторе языка, где вызовы функций связаны с правилами грамматики, которые компилируются из файла во время выполнения. Скомпилировано является ключом здесь. Для многих проблем, с которыми я сталкивался, когда то, чего вы хотите достичь, известно во время компиляции, вы не получите большую производительность при генерации кода во время выполнения. Некоторые оптимизации CLR JIT также могут быть недоступны для динамического кода. Это всего лишь мнение из моей практики, и ваш домен будет другим, но если производительность критична, я бы лучше посмотрел на нативный код, высоко оптимизированные библиотеки. Некоторая часть работы, которую я проделал, была бы медленной, если не использовать LAPACK / MKL. Но это только тот совет, который не просили, поэтому возьмите его с крошкой соли.