2008-11-03 8 views
15

Po skompilowaniu Expression<T>, wynikowy kod jest niejawnie zapisywany w pamięci podręcznej przez framework? Zastanawiam się nad metodami statycznymi Regex, w których framework domyślnie kompiluje i buforuje ostatnie kilka wyrażeń regularnych.Po skompilowaniu wyrażenia <T> jest on domyślnie buforowany?

Jeśli skompilowane Expression<T> obiekty są nie buforowane, można polecić kilka najlepszych praktyk dla utrzymywania w czasie kompilacji w dół ani żadnych gotchas, które mogą powodować problemy, jeśli ręcznie buforują wyrażenia?

public MyResultType DoSomething(int arg1, int arg2) 
{ 
    var result = invokeHandler(
     (IDoSomethingHandler h) => h.DoSomething(arg1, arg2) 
    ); 
    return result; 
} 

private TResult invokeHandler<T, TResult>(Expression<Func<T, TResult>> action) 
    where T : class 
{ 
    // Here, I might want to check to see if action is already cached. 

    var compiledAction = action.Compile(); 
    var methodCallExpr = action as MethodCallExpression; 

    // Here, I might want to store methodCallExpr in a cache somewhere. 

    var handler = ServiceLocator.Current.GetInstance<T>(); 
    var result = compiledAction(handler); 

    return result; 
} 

W tym przykładzie, jestem nieco zaniepokojony, że gdybym buforować skompilowany wyrażenie, że użyje wartości arg1 i arg2 jak były w momencie wyrażenie został skompilowany, zamiast pobierania tych wartości z odpowiedniego miejsca w stosie (tj. zamiast uzyskiwania aktualnych wartości).

Odpowiedz

10

Nie; Nie wierzę, że tak jest; jeśli chcesz go zbuforować, musisz zachować odniesienie Delegate (zazwyczaj Func<...> lub Action<...>). Podobnie, jeśli chcesz uzyskać najlepszą wydajność, skompilowałbyś ją jako sparametryzowane wyrażenie, więc możesz wysyłać różne wartości podczas wywoływania.

W tym przypadku, ponowne sformułowanie pomoże:

public MyResultType DoSomething(int arg1, int arg2) 
{ 
    var result = invokeHandler(
     (IDoSomethingHandler h, int a1, int a2) => h.DoSomething(a1, a2), 
     arg1, arg2); 
    return result; 
} 

private TResult invokeHandler<T, TResult>(Expression<Func<T,int,int,TResult>> action, 
    int arg1, int arg2) 
    where T : class 
{ 
    // Here, I might want to check to see if action is already cached. 

    var compiledAction = action.Compile(); 
    var methodCallExpr = action as MethodCallExpression; 

    // Here, I might want to store methodCallExpr in a cache somewhere. 

    var handler = ServiceLocator.Current.GetInstance<T>(); 
    var result = compiledAction(handler, arg1, arg2); 

    return result; 
} 

to, aby parametry numery ekspresji i przekazać rzeczywiste te, których w czasie działania (a nie jest stałe w ekspresji).

+1

Cześć Mark, nigdy nie spotkałem się z tego rodzaju optymalizacją. Czy możesz doradzić, czy jest to naprawdę przydatne pod względem wydajności, buforowania prekompilowanych zapytań? –

Powiązane problemy