Archive

Author Archive

The Move That Wasn’t

June 30, 2015 3 comments

While trying to duplicate the results I measured in my “Time To Get Moving!” post, an astute viewer posted this  comment:

move comment

For your convenience, I re-list the code in question here for your inspection:


#include <iostream>
#include <vector>
#include <utility>
#include <chrono>
using namespace std;

struct Msg{
  vector<double> vDoubs;
  Msg(const int NUM_ELS) : vDoubs(NUM_ELS){
  }
};

int main() {
//Construct a big Msg object!
const int NUM_ELS = 10000000;
Msg msg1{NUM_ELS};

//reduce subsequent code verbosity
using std::chrono::steady_clock;
using std::chrono::duration_cast;
using std::chrono::microseconds;

//Measure the performance of
//the "free" copy operations
auto tStart = steady_clock::now();
Msg msg2{msg1}; //copy ctor
msg1 = msg2; //copy assignment
auto tElapsed = steady_clock::now() - tStart;
cout << "Copy ops took "
     << duration_cast<microseconds>(tElapsed).count()
     << " microseconds\n";

//Measure the performance of
//the "free" move operations
tStart = steady_clock::now();
Msg msg3{std::move(msg1)}; //move ctor
msg1 = std::move(msg3); //move assignment
tElapsed = steady_clock::now() - tStart;
cout << "Move ops took "
     << duration_cast<microseconds>(tElapsed).count()
     << " microseconds\n";

cout << "Size of moved-from object = "
     << msg3.vDoubs.size();
} //"free" dtor is executed here for msg1, msg2, msg3

Sure enough, I duplicated what my friend Gyula discovered about the “move” behavior of the VS2013 C++ compiler:

VS2013 move

move response

Intrigued by the finding, I dove deeper into the anomaly and dug up these statements in the fourth edition of Bjarne Stroustrup’s “The C++ Programming Language“:

default ops

Since the Msg structure in the code listing does not have any copy or move operations manually defined within its definition, the compiler is required to generate them by default. However, since Bjarne doesn’t state that a compiler is required to execute moves when the programmer explicitly directs it to with std::move() expressions, maybe the compiler isn’t required to do so. However, common sense dictates that it should. Hopefully, the next update to the VS2013 compiler will do the right thing – like GCC (and Clang?) currently does.

By How Much?

June 27, 2015 6 comments

Thanks to a social media friend, I was directed to an agile transformation case study written by a management consultant and posted on the consultancy’s site along side several other huge success stories. At the end of the long writeup, the following outcomes were asserted:

Xform Outcomes

When I see fancy, professionally-crafted, “qualitative” success lists like these, knowing that they are touted by highly subjective people whose livelihoods require the projection of infallibility, my BS detector starts beeping. For this specific list, these questions come to mind:

  • Feature time-to-market has been reduced“: by how much?
  • Ability to release frequently has been increased“: by how much?
  • Technical debt has been reduced“: by how much?
  • Reactivity to portfolio prioritization is much improved“: by how much?
  • “WIP has been reduced”: by how much?
  • Morale is strongly improved within and between teams“: by how much?
  • Trust between sites is improved“: by how much?
  • The dispersion of development over many sites has been reduced“: by how much?
  • Global product and technical leadership is visible“: by how much?
  • How much did this 18 month transformation cost the client? How much money did you make?
  • How much have client revenues increased and costs decreased as a result of your effort?

Of course, no quantitative percentages were given because no pre-transformation benchmarking was performed. If benchmarking was indeed performed, there would’ve been a chance that the before-and-after metrics may have driven the client to conclude that the whole effort was a huge waste of time and money.

huge success

It’s funny how managers who love to hold others accountable for adhering to micro-defined, quantitatively specified, burndown charts, not only get to evaluate themselves, but they get to do so qualitatively, with no supporting data.

In God we trust; all others must bring data. – W. E. Deming

In Consultants we trust; all others must bring data. – BD00

Solutions, Not Problems!

June 24, 2015 2 comments

My absolute favorite leadership quote of all time comes from philosopher Karl Popper:

“The day soldiers stop bringing you their problems is the day you have stopped leading them. They have either lost confidence that you can help or concluded that you don’t care. Either case is a failure of leadership.” – Karl Popper

IMO, no other leadership quote comes close to hitting the nail on the head as Mr. Popper’s. Do you wanna know why? Because over my long and un-illustrious career, I’ve heard some anointed leaders say the equivalent of this:

“Don’t bring me problems, bring me solutions!”

I’ve heard that at least three times, and all three times I’ve thought:

If you’re not here to help solve your soldier’s problems problems too, then what do you do here besides watch numbers, approve/disapprove actions, reduce costs, and strut around; why are you even here at all?

Anyone with half of a brain in their head knows that saying shit like “don’t bring me your problems” drives important problems underground. And under the surface, they fester, grow, and morph into downstream crises that eat into the treasury from which these “keep your problems to yourselves” leaders draw their personal sustenance.

Great leaders encourage their troops to bring their problems forth into the light. Then they roll up their sleeves, jump into the tar pit, and help as much as they can, where they can. Paradoxically, this style is called “servant leadership“, and Theory-X managers just don’t get it. They never have, and never will. Solutions Not Problems In case you’re wondering why the nerd in the cartoon is just thinking the word “Clueless” instead of saying it out loud, it’s because:

To learn who rules over you, simply find out who you are not allowed to criticize. ~ Voltaire

Template Argument 1 Is Invalid

June 21, 2015 2 comments

cppcastlogo

I’d like to thank the hard working hosts of the first ever C++ podcast, Rob Irving and Jason Turner, for mentioning my “Time To Get Moving!” blog post on episode #16. If you’re a C++ coder and you’re not a subscriber to this great learning resource, then shame on you.

ttgm

Hey Rob and Jason, you guys gotta slightly modify your logo. You’re statement doesn’t compile because it’s illegal to use the “+” character in an identifier name :)

BadChar

Since I pointed out the bug, what do you guys think about changing your template argument,”C++“, to “Bulldozer00“?

bd00cast

Categories: C++ Tags: ,

Satirical Substitution

June 19, 2015 5 comments

Time To Get Moving!

June 15, 2015 8 comments

Prior to C++11, for every user-defined type we wrote in C++03, all standards-conforming C++ compilers gave us:

  • a “free” copy constructor
  • a “free” copy assignment operator
  • a “free” default constructor
  • a “free” destructor

The caveat is that we only got them for free if we didn’t manually override the compiler and write them ourselves. And unless we defined reference or pointer members inside of our type, we didn’t have to manually write them.

Starting from C++11 on, we not only get those operations for free for our user-defined types, we also get these turbo-boosters:

  • a “free” move constructor
  • a “free” move assignment operator

In addition, all of the C++ standard library containers have been “move enabled“.

When I first learned how move semantics worked and why this new core language feature dramatically improved program performance over copying, I started wondering about user-defined types that wrapped move-enabled, standard library types. For example,  check out this simple user-defined Msg structure that encapsulates a move-enabled std::vector.

MsgStruct

Logic would dictate that since I get “move” operations from the compiler for free with the Msg type as written, if I manually “moved” a Msg object in some application code, the compiler would “move” the vDoubs member under the covers along with it – for free.

Until now, I didn’t test out that deduction because I heard my bruh Herb Sutter say in a video talk that deep moves came for free with user-defined types as long as each class member in the hierarchical composition is also move-enabled. However, in a more recent video, I saw an excellent C++ teacher explicitly write a move constructor for a class similar to the Msg struct above:

ManualMoveCtor

D’oh! So now I was confused – and determined to figure out was was going on. Here is the program that I wrote to not only verify that manually written “move” operations are not required for the Msg struct, but to also measure the performance difference between moving and copying:

MoveCopyPerf

First, the program built cleanly as expected because the compiler provided the free “move” operations for the Msg struct. Second, the following, 5-run, output results proved that the compiler did indeed perform the deep, under the covers, “move” that my man Herb promised it would do. If the deep move wasn’t executed, there would have been no noticeable difference in performance between the move and copy operations.

copymoveperf

From the eye-popping performance difference shown in the results, we should conclude that it’s time to start replacing copy operations in our code with “move” operations wherever it makes sense. The only thing to watch out for when moving objects from one place to another is that in the scope of the code that performs the move, the internal state of the moved-from object is not needed or used by the code following the move. The following code snippet, which prints out 0, highlights this behavior.

postmovestate

A No Go For Me

June 13, 2015 2 comments
Follow

Get every new post delivered to your Inbox.

Join 504 other followers

%d bloggers like this: