Quando o programador não tem nada a fazer ou otimizar o código usando Linq.Expression

Acontece que não fui capaz de codificar ativamente por cinco anos. Portanto, toda chance de entrar no código e mexer com seus camaradas lá é percebida com alegria, como uma oportunidade de sacudir os velhos tempos e ter certeza de que ainda há "frutinhas nas nádegas" (também conhecido como um furador no traseiro). Sim, e farei uma ressalva já que o artigo é mais um tutorial, não da série "olha que legal eu consigo", mas da série "ah, que boa opção mostrar com um simples exemplo o uso de uma tecnologia que causa dificuldades para alguns colegas". É minha profunda convicção que tais soluções devem ser incluídas no arsenal de qualquer desenvolvedor C #.





Acabei de revisar o código, que inclui um processo de aproximação de várias etapas, no qual a obtenção da constante do coeficiente está ativamente envolvida (O coeficiente é selecionado para uma faixa de valores. vai da tabela IGalla CSF de acordo com a velocidade atual do corpo (a faixa de velocidades corresponde a um CSF específico, cerca de 300 elementos na tabela). 





O processo é multi-etapas, a operação de busca é realizada frequentemente, e os kids-developers foram ótimos, foram ainda mais longe do que a busca binária, implementaram o cálculo de uma chave inteira para uma gama de valores e obtendo um coeficiente para esta chave através de Dictionary



E desde a equipe Agile, e eu, feio, também SixSigma e Gosto muito de ver tudo em números - então os caras mostraram de forma convincente a eficácia da solução escolhida. Para 1 cálculo de 1000 pontos de aproximação, os custos são:





Pesquisa linear na tabela - 0,6 ms

Pesquisa linear com cadeia de retorno

if - 0,1 ms

Pesquisa por divisão ao meio - 0,08 ms Pesquisa por dicionário - 0,018 ms





Acertou minha mesa no momento em que o projeto engatinhava para o palco “e agora estamos fazendo os mesmos cálculos no microcontrolador”. Acontece que a transferência do dicionário não foi muito boa (sim, eles poderiam ter pensado com antecedência, mas eles enfrentaram microcontroladores pela primeira vez, então vamos perdoá-los por essa omissão). 





Graças à equipe, eles já contaram os números para “pensar”, e percebi que o ganho de “código limpo” versus busca na estrutura de dados é de 6 vezes (primeiras linhas). E salvando o dicionário contra a redução pela metade - um pouco mais de 4 vezes. 





“ ”, - -, data-driven , 20 . - .NET “ ”. if , Linq ? , . , , “” . 





- . . - - . - if, , - if, . 





if, , . - range (), , (value), (v) .   , , Linq - , if if.





If (v >= from && v < to) return value;
      
      



public Expression CreateSimpleIf(double from, double to, 
                      double value, 
                      Expression v, LabelTarget returnTarget)
{
    var returnStmt = Expression.Return(
      returnTarget, 
      Expression.Constant(value));
    var ifCondition = Expression.AndAlso(
        Expression.GreaterThanOrEqual(v, Expression.Constant(from)), 
        Expression.LessThan(v, Expression.Constant(to)));
    return Expression.IfThen(ifCondition, returnStmt);
}
      
      







. 1 2 , , -,   , . 





, . 









if (v >= mid.from && v < mid.to) 
   return mid.value 
if (v < mid.from)    
    return search in (0...mid-1) 
else    
    return search in (mid + 1...length - 1);
      
      



Span



/ / “ ”. 





public Expression CreateSpanExpression(Span<Coefficient> span, 
          Expression v, 
          LabelTarget returnTarget)
{
    if (span.Length == 1)
        return CreateSimpleIf(span[0].RangeFrom, 
                   span[0].RangeTo, 
                   span[0].Value, 
                   v, returnTarget);
    else if (span.Length == 2)
    {
        Expression[] ifs = new Expression[2];
        ifs[0] = CreateSimpleIf(span[0].RangeFrom, 
                   span[0].RangeTo, 
                   span[0].Value, 
                   v, returnTarget);
        ifs[1] = CreateSimpleIf(span[1].RangeFrom, 
                   span[1].RangeTo, 
                   span[1].Value, 
                   v, returnTarget);
        return Expression.Block(ifs);
    }
    else
    {
        int mid = span.Length / 2;
        Expression[] blocks = new Expression[2];
        blocks[0] = CreateSimpleIf(span[mid].RangeFrom, 
                       span[mid].RangeTo, 
                       span[mid].Value, 
                       v, returnTarget);

        var leftSide = 
          CreateSpanExpression(span.Slice(0, mid), 
                               v, returnTarget);
        var rightSide = 
          CreateSpanExpression(span.Slice(mid + 1, 
                               span.Length - mid - 1), 
                               v, returnTarget);

        Expression condition = 
          Expression.LessThan(v, 
                              Expression.Constant(span[mid].RangeFrom));
        blocks[1] = Expression.IfThenElse(condition, leftSide, rightSide);
        return Expression.Block(blocks);
     }
} 
      
      



- . , , lambda- . 





public Func<double, double> CreateBTReeExpression()	
{
    var value = Expression.Parameter(typeof(double), "value");
    var returnTarget = Expression.Label(typeof(double));

    var ifs = CreateSpanExpression(mCoefficients.ToArray(), 
                                   value, returnTarget);
    var body = Expression.Block(typeof(double), 
                 new Expression[] 
                 { 
                   ifs, 
                   Expression.Label(returnTarget, 
                     Expression.Constant(0.0))
                 });

    var expression = Expression.Lambda(typeof(Func<double, double>), 
                       body, 
                       new ParameterExpression[] { value });
    var functionDelegate = expression.Compile();
    return (Func<double, double>) functionDelegate;        
}
      
      







, , ? 0.012ms, 1.5 Dictionary



. . 





, , , “” - , , , “” . , - , .  





, , , “ IDE” , . 





, , , , - , , , , ( , ). “, ”.  





, – , , . silver bullet .





P.S.: , , . - , , , , , . , , , . .








All Articles