Domanda

Quando viene compilata un'espressione < T > , il codice risultante viene implicitamente memorizzato nella cache dal framework? Sto pensando secondo i metodi statici Regex in cui il framework compila e memorizza in modo implicito gli ultimi regex.

Se gli oggetti compilati Expression < T > non sono non memorizzati nella cache, puoi consigliare alcune best practice per ridurre i tempi di compilazione o eventuali gotcha che potrebbero causare problemi se memorizzare manualmente un'espressione nella cache?

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;
}

In questo esempio, sono leggermente preoccupato che se memorizzo nella cache l'espressione compilata, che utilizzerà i valori di arg1 e arg2 come erano al momento l'espressione è stata compilata, anziché recuperare quei valori dalla posizione appropriata nello stack (ovvero anziché ottenere i valori correnti).

È stato utile?

Soluzione

No; Non credo che lo sia; se vuoi che sia memorizzato nella cache, devi tenere il riferimento Delegate (in genere Func < ... > o Action < ... > ). Allo stesso modo, se si desidera ottenere le migliori prestazioni, è necessario compilarlo come un'espressione parametrizzata, in modo da poter inviare valori diversi quando viene richiamato.

In questo caso, la riformulazione aiuterebbe:

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;
}

vale a dire. imposta i parametri numerici dell'espressione e passa quelli effettivi al momento dell'esecuzione (anziché essere costanti nell'espressione).

Altri suggerimenti

Le espansioni Lambda non vengono memorizzate automaticamente nella cache. Per questo dovrai implementare i tuoi algoritmi di memorizzazione nella cache / memoizzazione. Controlla la relativa domanda StackOverflow:

Is è possibile memorizzare nella cache un valore valutato in un'espressione lambda?

È importante notare che le espressioni lambda sono valutate in modo pigro in C #.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top