NoInlining Question?

NoInlining Question?

Old forum URL: forums.lhotka.net/forums/t/1121.aspx


RangerGuy posted on Tuesday, September 05, 2006

Not really sure what this is for. If I understand correct it just says if it's a small a method just JIT when it's called instead of  when it's compiled.

Is there any benifets to no inlining.. I noticed that the snippets put this attribute on my get and set methods of my properties.

I don't have my book here today so I could not look for an explanation and what I found on google was quite complex :(

[System.Runtime.CompilerServices.MethodImplSystem.Runtime.CompilerServices.MethodImplOptions.NoInlining)]

RockfordLhotka replied on Tuesday, September 05, 2006

The primary benefit to using the noinlining attribute is that your code will work. Smile [:)]

Inlining is a compiler optimization feature, where the compiler can avoid the overhead of making a method call, if the target method's code is simple enough to just copy it in-line with the calling code. It is a very simple and powerful performance optimization, and is one that compilers have been doing for a very long time.

Essentially, you have some code, A, that is calling a method, B. Making that call requires putting stuff on the stack, transferring control to B and handling the stack when the call is complete. Not a lot of overhead, but overhead still (especially inside a loop structure). What inlining does, is merges the code from B directly into A, so A doesn't actually call B at all, it just includes B's code.

That's all good stuff! However, if you are using CanReadProperty(), CanWriteProperty() or PropertyHasChanged() without specifying the property name with a string literal, CSLA .NET uses the stack trace to find the property name. That works fine, unless the property was inlined (properties are just methods after all), in which case "A" would be returned instead of "B". Since the property name is "B", this will cause your app to run incorrectly (not crash - just not work right).

So either use the noinlining attribute, or supply the property name as a string literal to those methods - either way works, but you must do one or the other.

owensig replied on Tuesday, November 28, 2006

In my opinion, the parameterless versions should be dropped in the next version (as well as any references to the System.Diagnostics namespace). 

figuerres replied on Tuesday, September 05, 2006

I do not recall the exact detail but sometimes when a compiler inlines code it can break it.

sometimes when I used to do C stuff in DOS it might make a function crash or return the wrong results.

generally inline makes the code a tad larger in your .exe image but faster by not having to do as many

push, call, pop cycles at the assembly level.

but in a few cases you need that code to be a "real function" and not cut down to a segment of code.

 

RangerGuy replied on Tuesday, September 05, 2006

Cool! It makes sense now. Thanks for the explanation. Now I have optimized properties :)

public string Phone
{
 get
 {
  CanReadProperty(true);
  return _Phone;

 }
 
 set
 {

  CanWriteProperty(true);
  if (_Phone != value)
  {

   _Phone = value;
   PropertyHasChanged("Phone");

  }
 }

}

RockfordLhotka replied on Tuesday, September 05, 2006

Not with that code!!!

Your calls to CanReadProperty() and CanWriteProperty() also must explicitly pass a string literal property name or you are in trouble!!

RangerGuy replied on Tuesday, September 05, 2006

oh my bad! Sorry about that.... I was leaving them until I do my security but it's better to change them now so I don't forget.

Thanks Rocky!

REVISED PROPERTY

public string Phone
{
  get
     {
       CanReadProperty("Phone");
       return _Phone;
     }
  set
     {
         CanWriteProperty("Phone");
        if (_Phone != value)
       {
         _Phone = value;
         PropertyHasChanged("Phone");
       }
    }
}

rxelizondo replied on Sunday, October 15, 2006

Not sure if this has been mentioned already but I think you will run into all kinds of problem if you where to obfuscate your project and rely on reflection to run code such as the PropertyHasChanged().

 

Your are better off (IMHO) to create constanst strings that can be used througut your code. For example:

 

const string PROP_PHONE = “Phone”;

 

CanReadProperty(PROP_PHONE , true);

iteProperty(PROP_PHONE ,true);

PropertyHasChanged(PROP_PHONE);

etc

 

You can use this constant on your properties, validation rules and security rules and never have to worry about it, even if you change the property name and forgot to change the constant value it would not matter as long as you don’t use the shared reflection based validation functions.

 

Q Johnson replied on Tuesday, September 05, 2006

Here's what I found in the eBook (pdf version of the book) at the first of two instances of "noinlining" found with the search tool.  The "noinlining" isn't exactly mentioned specifically, but the note below about using MethodImpl() at all seems to explain it. The pasted text below begins near the bottom of page 116 in the VB book.

This is why the $10 cost for the pdf is so cheap.  You don't need the book with you at work.  Just have a copy of the pdf there and at home (and wherever else you might need it).

 

Calling PropertyHasChanged() by passing the property name as a string value would mean

hard-coding the property name in code. String literals are notoriously difficult to maintain, so

there’s an overload to automatically glean the property name at runtime:

<System.Runtime.CompilerServices.MethodImpl( _

System.Runtime.CompilerServices.MethodImplOptions.NoInlining)> _

Protected Sub PropertyHasChanged()

Dim propertyName As String = _

New System.Diagnostics.StackTrace(). _

GetFrame(1).GetMethod.Name.Substring(4)

PropertyHasChanged(propertyName)

End Sub

>> end pg 116 CHAPTER 3 n BUSINESS FRAMEWORK IMPLEMENTATION <<

This implementation uses System.Diagnostics to retrieve the name of the method or property

that called PropertyHasChanged(). The <MethodImpl()> attribute prevents the compiler from merging

this code directly into the property itself, since that would confuse the System.Diagnostics call.

There is a performance penalty (akin to using reflection) to calling System.Diagnostics like this,

but I am usually happy to pay that price to avoid using string literals for property names through a

business class. Using this method, a business object’s property will look like this:

Public Property Name() As String

Get

CanReadProperty(True)

Return mName

End Get

Set(ByVal value As String)

CanWriteProperty(True)

If mName <> value Then

mName = value

PropertyHasChanged()

End If

End Set

End Property

RangerGuy replied on Tuesday, September 05, 2006

Yeh, I'd like that it would be handy, where did you see it for $10 on apress it's $30 US.

Q Johnson replied on Wednesday, September 06, 2006

btw, sorry about my late-looking reply here.  I responded as soon as I got my e-mail notification of your message.  But clearly there were already replies here (that weren't sent to me yet) that beat mine.

But on to your question.  Look at the very back page of your book.  You'll see the offer there for the eBook at $10.  The question they will ask has you look to some specific page number in your book and supply the text you find there - so they know you actually have the book.

Enjoy.

Ton Smeets replied on Tuesday, November 07, 2006

Tell me if I'm wrong here, but I looked up the Csla/Core/BusinessBase.cs (C#) and I found the CanReadProperty() that takes no parameter has already implemented this attribute:

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]

public bool CanReadProperty()

{

string propertyName =

new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().Name.Substring(4);

return CanReadProperty(propertyName);

}

This is also true for the CanReadProperty(true) method. This one has in Csla/Core/BusinessBase.cs also the noinlining attribute implemented.

Or is this only relevant for the VB version. The templates implement this attribute as well.

Ton.

RRorije replied on Tuesday, November 07, 2006

That is true, but it is essential that the property itself is not inlined also. AFAIK with inlining the property will be removed altogether, so the system.diagnostics.StackTrace()......Substring(4) will not find the property because it is inlined.

Another question, I think it is rather easy to extend the csla property snippet to create the CanReadProperty/CanWriteProperty with the propertyName, is there a reason why this is not the case?

RockfordLhotka replied on Tuesday, November 07, 2006

RRorije:

Another question, I think it is rather easy to extend the csla property snippet to create the CanReadProperty/CanWriteProperty with the propertyName, is there a reason why this is not the case?


You can edit the snippets as you choose - they are merely examples.

My goal was to provide an alternative that didn't leave a string literal (or 3) embedded in the code, which reduces maintainability. The whole point of those overloads is to increase maintainability of code.

As I've said before, it is my view that if you are manually writing/maintaining the code you should use the noinlining option and avoid the string literals. If you are using code-gen, so you never touch that code by hand, then you should use the string literals and avoid the noinlining attribute.

rxelizondo replied on Wednesday, November 08, 2006

Although I think that the use of reflection to retrieve the property name is really cool, I don’t think this is necessarily a good idea. The reason I say that is because property names are used in many other places such as on the rule validation functionality for example and because of this, you now have to be really careful about keeping everything in sync. In other words, if the property name changes you also need to change the rest of the code.

So from my point of view, if you have to manually specify the property name by typing the actual property name in multiple places, you better come up with a way to minimize potential for error and code maintainability.

This is way I think that rather than typing the property name such as “SomePropertyName” wherever is required, I think you are much better off creating public static string that you can share all over. Below is an example of what I am talking about:

public static readonly string PROP_START_TIME = “StartTime”;

 The reason why it’s public is because the client code that needs the name of the property can use this exposed constant value to do thing such as retrieve the broken rules for a certain property. The reason why is readonly and not a constant is to avoid versioning problems.

Now, if you ever need to change the property name then you only have to change it in one place but most importantly, you  **DON’T** have to tell everyone that is using your dll to change the value.

If you where to change the PROP_START_TIME value to something like PROP_STARTO_THE_TIMO the client code will get compile errors making it very obvious that they need to adjust the code to comply with the new changes.

Also, I not sure if this will work since I never done it but I think you can change the above code to something like:

public static readonly string PROP_START_TIME = Guid.NewGuid().ToString();

This way you can spare yourself of the task of having to synchronize the string value with the property name.

Usage example:

CanReadProperty(PROP_START_TIME, true);
CanWriteProperty(PROP_START_TIME, true);
PropertyHasChanged(PROP_START_TIME);
ValidationRules.AddRule(MyDelegate, PROP_START_TIME);

Copyright (c) Marimer LLC