2014-07-12 - faster by encapsulation

encapsulation usually means for ppl abstraction and abstraction in turn is often blamed for decreasing performance. this is not C++ style. C++ is all about lightweight abstractions. the same way one can have abstract algorithms like sort, that are highly optimized and fast, the same way encapsulation can be used for speeding things up.

input example

as an example consider raw pointer to some type X and two functions operating on it:

int foo(X* ptr)
{
  if(not ptr)
    throw std::runtime_error{"unexpected null"};
  return ptr->getNumber() + 42;
}
 
double bar(X* ptr)
{
  if(not ptr)
    throw std::runtime_error{"unexpected null"};
  return ptr->averageValue() / 4.2;
}

what do they have in common? they both do simple things, obfuscated by constant not-null checking.

encapsulation

now imagine class, that would ensure pointer held inside is not null. something as simple as this:

template<typename T>
struct NotNull
{
  explicit NotNull(T* t):
    t_{t}
  {
    if(not t_)
      throw std::runtime_error{"pointer is null"};
  }
  // more operators, c-tors, etc...
 
  T* operator->() { return t_; }
  // more getters, swaps, etc...
private:
T* t_;
};

now lets use it in our previous code:

int foo(NotNull<X> ptr)
{
  return ptr->getNumber() + 42;
}
 
double bar(NotNull<X> ptr)
{
  return ptr->averageValue() / 4.2;
}

code just got shorter and more readable. it also auto-protects from mistakes – null-pointers dereferences are no longer a problem.

but how it got faster? notice that now you need to do not-null check only once – in a constructor. from that point, merely knowing type ensures you the pointer cannot be null, so you no longer need to check it! it means not only less code, but a faster code – not chance of branch miss-prediction. :) this may not appear to be lot, but when you multiply this by number of method/functions in your project, gain will became obvious. plus you get shorter code, for free. :D

presented idea is a RAII way of expressing properties, as an extension of usual “ownerships”. logically it works exactly the same way RAII constructors do: once constructor is done, each method needs not to check if object is initialized. this way property can be encapsulated in a type, to free user from checking certain invariants at each step.

genesis

the idea is not new to me. it first crossed my mind when we were developing ACARM-ng. as we had a chance to make the whole system from scratch, many interesting ideas popped out at that time. on of this was to make boost::shared_ptr version, that cannot be null. since system is open source, you can check out the original implementation.

it all worked like a charm! simple, valid code without extra checks, where not needed. exactly what one needs! :)

this was back in C++03 era. now we can do more. i plan to implement general pointer wrapper (NotNull<>) as a part of Basic Utilities and Tools library.

blog/2014/07/12/faster_by_encapsulation.txt · Last modified: 2021/06/15 20:08 by 127.0.0.1
Back to top
Valid CSS Driven by DokuWiki Recent changes RSS feed Valid XHTML 1.0