Asked  1 Year ago    Answers:  5   Viewed   9 times

I know that inline is a hint or request to compiler and its used to avoid function call overheads.

So on what basis one can determine whether a function is a candidate for inlining or not ? In which case one should avoid inlining ?

 Answers

3

Avoiding the cost of a function call is only half the story.

do:

  • use inline instead of #define
  • very small functions are good candidates for inline: faster code and smaller executables (more chances to stay in the code cache)
  • the function is small and called very often

don't:

  • large functions: leads to larger executables, which significantly impairs performance regardless of the faster execution that results from the calling overhead
  • inline functions that are I/O bound
  • the function is seldom used
  • constructors and destructors: even when empty, the compiler generates code for them
  • breaking binary compatibility when developing libraries:
    • inline an existing function
    • change an inline function or make an inline function non-inline: prior version of the library call the old implementation

when developing a library, in order to make a class extensible in the future you should:

  • add non-inline virtual destructor even if the body is empty
  • make all constructors non-inline
  • write non-inline implementations of the copy constructor and assignment operator unless the class cannot be copied by value

Remember that the inline keyword is a hint to the compiler: the compiler may decide not to inline a function and it can decide to inline functions that were not marked inline in the first place. I generally avoid marking function inline (apart maybe when writing very very small functions).

About performance, the wise approach is (as always) to profile the application, then eventually inline a set of functions representing a bottleneck.

References:

  • To Inline or Not To Inline
  • [9] Inline functions
  • Policies/Binary Compatibility Issues With C++
  • GotW #33: Inline
  • Inline Redux
  • Effective C++ - Item 33: Use inlining judiciously

EDIT: Bjarne Stroustrup, The C++ Programming Language:

A function can be defined to be inline. For example:

inline int fac(int n)
{
  return (n < 2) ? 1 : n * fac(n-1);
}

The inline specifier is a hint to the compiler that it should attempt to generate code for a call of fac() inline rather than laying down the code for the function once and then calling through the usual function call mechanism. A clever compiler can generate the constant 720 for a call fac(6). The possibility of mutually recursive inline functions, inline functions that recurse or not depending on input, etc., makes it impossible to guarantee that every call of an inline function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate 720, another 6 * fac(5), and yet another an un-inlined call fac(6).

To make inlining possible in the absence of unusually clever compilation and linking facilities, the definition–and not just the declaration–of an inline function must be in scope (§9.2). An inline especifier does not affect the semantics of a function. In particular, an inline function still has a unique address and so has static variables (§7.1.2) of an inline function.

EDIT2: ISO-IEC 14882-1998, 7.1.2 Function specifiers

A function declaration (8.3.5, 9.3, 11.4) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.

Tuesday, June 1, 2021
 
Nate
 
5

No, IDisposable items are not disposed when they go out of scope. It is for precisely this reason that we need IDisposable - for deterministic cleanup.

They will eventually get garbage collected, and if there is a finalizer it will (maybe) be called - but that could be a long time in the future (not good for connection pools etc). Garbage collection is dependent on memory pressure - if nothing wants extra memory, there is no need to run a GC cycle.

Interestingly (perhaps) there are some cases where "using" is a pain - when the offending class throws an exception on Dispose() sometimes. WCF is an offender of this. I have discussed this topic (with a simple workaround) here.

Basically - if the class implements IDisposable, and you own an instance (i.e. you created it or whatever), it is your job to ensure that it gets disposed. That might mean via "using", or it might mean passing it to another piece of code that assumes responsibility.

I've actually seen debug code of the type:

#if DEBUG
    ~Foo() {
        // complain loudly that smoebody forgot to dispose...
    }
#endif

(where the Dispose calls GC.SuppressFinalize)

Saturday, July 17, 2021
2

Whilst MRC is a generic co-processor inter-op instruction, cp15 is the control processor - which all modern ARM CPUs have and this has been used by ARM was a means of extending the instruction set for on-chip units such as the cache, MMU, performance monitoring and lots else besides.

Taking your instruction a bit at a time:

mrc p15, 0, %0, c9, c13, 0" : : "r" (counter)

According to the ARM Cortex A7 MPCore Reference the instruction format is:

MRC{cond} P15, <Opcode_1>, <Rd>, <CRn>, <CRm>, <Opcode_2>

And on Page 4-11 this is described as a transfer of a CPU register to the performance monitor count register (I guess count=0 and this is a reset of the performance counter).

As for the syntax of inline assembler. refer to this for a x86 overview - which is probably similar to ARM.

The : : "r" (counter) means that the instruction has:

  • No output in a register that needs to end up in a local variable
  • Takes input from variable counter, and the register this is in should be used as %0.
  • There are no side effects the compiler ought to be aware of (clobbers)
Saturday, August 7, 2021
 
kmunky
 
1

when it is needed/best practice to use the keyword this

This is usually used when you want to access something in some. So for instance, if you have a custom object and want to use some property inside some method, you should use this.

function Person(fname, lname){
  this.fname = fname;
  this.lname = lname;
  this.fullName = function(){
    return this.fname + ' ' + this.lname;
  }
}

var p = new Person('foo', 'bar');
console.log(p.fullName())

If you see, in current constructor, I created a function(fullName) which needs to access fname and lname properties of the object it is part of. This is a place this must be used.


Now while declaration, when to use this?

Any property in a constructor that is a part of this will be a part of the object. So if you need something that is only accessible to you but not outside, you can use function instead of this.

function Person(fname, lname){
  var self = this;
  self.fname = fname;
  self.lname = lname;
  
  // This function is private
  function getFullName() {
    var name = '';
    var seperator = '';
    if (fname) {
      name += self.fname;
      seperator = ' ';
    }
    if (lname) {
      name += seperator + self.lname;
    }
    return name;
  }
  this.fullName = function(){
    return getFullName();
  }
}

var p = new Person('foo', 'bar');
console.log(p.fullName())

As for your code, I have already explained in comment why it works:

In non-strict mode, this will point to window and any declaration not in a function will be a part of global scope.

But as rightly pointer by @Jonas W its a bad practice. Why it is bad?

  • Any variable defined without declaration statement(var|let|const) will become part of global scope.
  • Any variable with declaration statement outside any functions will become part of global scope.
Saturday, September 18, 2021
 
4

The C++ standard says, in 12.1[class.ctor]/5

An implicitly-declared default constructor is an inline public member of its class

and in 12.4[class.dtor]/3

An implicitly-declared destructor is an inline public member of its class.

Sunday, October 31, 2021
 
PHLAK
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :