Здравствуйте, Ночной Смотрящий, Вы писали:
EP>>Если для mapping'а генерируется байткод (который может быть настолько быстрым, насколько позволяет платформа) и используется скомпилированный запрос — то откуда вообще взяться overhead'у?
НС>Построить запрос это дорого, в некоторых провайдерах — очень дорого. linq2db поэтому построение запроса кеширует. К сожалению, компилятор шарпа генерирует код, который строит дерево при каждом исполнении метода, т.е. дерево каждый раз разное. Из-за этого, чтобы сравнить запросы, приходится обходить это дерево и вычислять хеш. Это тоже довольно быстро, но уже не мгновенно.
Это понятно, но если использовать Compiled Query, то есть без обхода дерева — то получается что совсем не будет overhead'а? Здорово
EP>>Этот AST по идее должен лежать в памяти достаточно компактно, и соответственно должен обходится быстро.
НС>Так и есть.
EP>>, то можно попробовать сделать свой обход через unsafe Но нужно знать внутреннюю структуру, либо тогда делать reverse engineering
НС>unsafe не спасет. Единственное в чем он дает существенный выигрышь на практике — отключение проверок границ массивов. Но в Expression Tree массивов не сказать чтобы много.
Там наверняка какой-нибудь visitor на виртуальных функциях, и скорей всего обход узлов в памяти не последовательный, что медленно.
Если сделать допущение, что у одного и того же запроса узлы в памяти располагаются последовательно, то можно обходить узлы по порядку — как они лежат в памяти. Плюс надо будет "нормализировать" указатели-дуги, чтобы они не зависели от начального адреса. Плюс отказ от виртуальных функций в пользу хардкорного инлайнинга и jump table. Думаю всё это даст прирост скорости в несколько раз, а то и на порядок (порядки — если супер-оптимистично).
Но это конечно жуткий low-level hack, требующий кучи тестов и version-specific кода.