The second part of the path to Lambda masters

Source: Internet
Author: User
Tags benchmark
Impact of closures

To show the impact of the closure, let's look at the example below.

 VaR Buttons = New Button [ 10  ];  For ( VaR I = 0 ; I <buttons. length; I ++ ){  VaR Button = New  Button (); button. Text = (I + 1 ) + " . Button-click for index!  "  ; Button. onclick + = (S, e) => {MessageBox. Show (I. tostring () ;}; buttons [I] = Button ;}  //  What will happen if we click the button? 

 

This is a strange question. I often ask my students in my JavaScript courses. 95% of students said. Obviously, the button 0 shows 0, the button 1 shows 1, and so on. Less than 5% of students will understand after learning the closure. 10 is displayed for all buttons.

The value of the local variable I has changed. And is equal to buttons. length. That is, 10. It's easy to avoid this strange situation. As shown in the following figure.

VaRButton =NewButton ();VaRIndex =I; button. Text= (I +1) +". Button-click for index!"; Button. onclick+ = (S, e) =>{MessageBox. Show (index. tostring () ;}; buttons [I]= Button;

 

The problem is solved, but the index variable is a value type, so a copy of "global" I is retained.

The last topic is something called the expression tree. It cooperates with Lambda expressions. In addition, he will make some wonderful things happen in the HTML Extension Method in ASP. net mvc. The key issue is: how to find the target function

1. What is the name of the variable passed in?
2. What is the subject of the method?
3. What types are used in the function body?

Expression solves these problems. It allows us to mine the generated Expression Tree. We can also execute the functions that are passed to func and action delegates, and parse lambda expressions at runtime.

Let's take a look at how to use the expression type example.

 
Expression <func <mymodel,Int> Expr = model =>Model. myproperty;VaRMember = expr. BodyAsMemberexpression;VaRPropertyname = memberexpression. member. Name;//When member! = Execution when null...

 

This is the simplest use of expression. The rules are also quite straightforward. Construct an expression-type object. The compiler generates some metadata for the generated interpretation tree. This interpretation tree contains all relevant information, such as parameters and method bodies.

The method body contains a complete interpretation tree, which we can access. Just like a complete statement. You can also specify the return value and type. Of course, the return value can be null. In most cases. We are very interested in expressions. This is very similar to the expression-type method in ASP. net mvc-the name of the parameter to be used can be obtained, and the benefit is obvious. No name spelling errors will occur. This will not cause any compilation errors.

Note: WhenProgramThe caller is only interested in the name of the called attribute. There is a simpler and more elegant solution, that is, the parameter feature callermembername can get the name of the call method/attribute. The field is automatically filled by the compiler. Therefore, if we only want to know the name and do not want to know more information, we only need to writeCodeThat's all. You can call the whatsmyname () method to return the method name.

 
StringWhatsmyname ([callermembername]StringCallingname =Null){ReturnCallingname ;}

 

Performance of lambda expressions

There is a big question: How fast is a Lambda expression? Okay. First, we expect them to be as fast as our general functions. In the next section. The msil code of Lambda is not very different from that of a common function.

One of the most interesting discussions is that if a Lambda expression produces a closure, it will be as fast as using a global variable method. This creates an interesting question. Is it related to the number of local variables in a region?

Let's look at the test code. With four different indicators, we can see the differences between common methods and Lambda methods.

 Using System;  Using  System. Collections. Generic;  Using  System. diagnostics;  Namespace  Lambdatests {  Class  Standardbenchmark: benchmark {  Const   Int Length = 100000  ;  Static   Double [];  Static   Double  [] B;  Static   Void  Init (){  VaR R = New  Random (); = New   Double  [Length]; B = New   Double [Length];  For ( VaR I = 0 ; I <length; I ++ ) {A [I] = R. nextdouble (); B [I] = R. nextdouble ();}}  Static   Long  Lambdabenchmark () {func < Double > Perform = () =>{  VaR Sum = 0.0  ;  For ( VaR I = 0 ; I <length; I ++ ) Sum + = A [I] * B [I];  Return  SUM ;};  VaR Iterations = New  Double [ 100  ];  VaR Timing = New  Stopwatch (); timing. Start ();  For ( VaR J = 0 ; J <iterations. length; j ++ ) Iterations [J] = Perform (); timing. Stop (); console. writeline (  " Time for Lambda-benchmark: \ t {0} MS  "  , Timing. elapsedmilliseconds );  Return  Timing. elapsedmilliseconds ;}  Static   Long  Normalbenchmark (){  VaR Iterations = New   Double [ 100  ];  VaR Timing =New  Stopwatch (); timing. Start ();  For ( VaR J = 0 ; J <iterations. length; j ++ ) Iterations [J] = Normalperform (); timing. Stop (); console. writeline (  "  Time for normal-benchmark: \ t {0} MS  "  , Timing. elapsedmilliseconds );  Return Timing. elapsedmilliseconds ;}  Static   Double  Normalperform (){  VaR Sum = 0.0  ;  For ( VaR I = 0 ; I <length; I ++ ) Sum + = A [I] * B [I];  Return Sum ;}}} 

 

We can use lambda expressions to write better code. In the end, I did not. It is to prevent impact on the final result. Therefore, essentially. There are three methods in the above Code
One is lambda testing, the other is normal testing, and the other is the method called in normal testing. The fourth method is actually our Lambda expression. It has been created in the first method. The calculation process is very simple. We randomly take numbers to prevent the compiler from doing any optimization. Finally, we are very interested in the differences between common methods and Lambda methods.

If we run this test program. We will find that Lambda expressions are not always worse than normal methods. We are surprised that sometimes even lambda expressions are faster. However, in the case of closures, it is incorrect. This means that in most cases, we can use lambda expressions without hesitation. When using closures, there will be a little performance loss, but fortunately, the next section will explain several causes of performance loss.
The following table lists the test output results.

Test Lambda [MS] Normal [MS]
0 45 +-1 46 +-1
1 44 +-1 46 +-2
2 49 +-3 45 +-2
3 48 +-2 45 +-2

Is the result of the above table. We can see that the general method is basically the same as the lambda expression limit. When lambda expressions are used, there is not much performance loss.

The secrets behind Chapter 3-msil

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.