У меня есть метод хеширования, операции которого зависят от ввода в функцию. Профилирование программы показало, что слишком много времени тратится на оценку этого метода хеширования. Я хочу попробовать изменить его в дерево выражений, чтобы проверки внутреннего цикла можно было выполнить один раз. Надеюсь, это будет быстрее, но я все равно узнаю о деревьях выражений.
Вот упрощенная версия функции (я отменил несколько очевидных оптимизаций для примера и убрал любую проверку ввода):
Private Function Checksum(ByVal inputValues As IEnumerable(Of UInt32),
ByVal declarations As IEnumerable(Of String),
ByVal statements As IEnumerable(Of String)) As UInt32
Dim variables = New Dictionary(Of Char, UInt32)
For Each declaration In declarations
'parse declaration (eg. "X=52")'
variables(declaration(0)) = UInt32.Parse(declaration.Substring(2))
Next declaration
For Each value In inputValues
'"I"nput'
variables("I"c) = value
For Each statement In statements
'parse statement (eg. "X=Y+Z")'
Dim varResult = statement(0)
Dim valueLeft = variables(statement(2))
Dim operand = statement(3)
Dim valueRight = variables(statement(4))
'execute statement'
Dim valueResult As UInt32
Select Case operand
Case "+"c : valueResult = valueLeft + valueRight
Case "-"c : valueResult = valueLeft - valueRight
Case "*"c : valueResult = valueLeft * valueRight
Case "&"c : valueResult = valueLeft And valueRight
Case "|"c : valueResult = valueLeft Or valueRight
Case "^"c : valueResult = valueLeft Xor valueRight
End Select
variables(varResult) = valueResult
Next statement
Next value
'"O"utput'
Return variables("O"c)
End Function
Я хочу создать функцию, которая принимает объявления и операторы и выводит специализированное дерево выражений, представляющее функцию, которая принимает IEnumerable из UInt32 и возвращает UInt32.
Follow-Up:
Мне удалось, и ускорение было смешным (на порядок). Главные вещи, которые мне пришлось узнать, где:
- Используйте Expression.Lambda и Expression.Compile, чтобы получить делегата, которого вы действительно можете использовать.
- У метода фабрики Expression.Block есть параметр 'variable', который вы (по сути) используете для объявления локальных объектов. Аналогично, Expression.lambda имеет «параметры».
- Если вы вызываете Expression.Parameter дважды, вы имеете дело с двумя разными переменными (даже если их имя одинаковое)! Сохраните результат для последующего использования. То же самое для этикеток и т. Д.
- Результатом выражения BlockExpression является последнее выражение в блоке.