Does defining a fluent interface have a performance impact?

736 views Asked by At

I just read this question, which raises for me another question:

Consider this class:

class Foo
{
public:
  void setA(int a) { m_a = a; }
  void setB(int b) { m_b = b; }
private:
  int m_a, m_b;
};

Which could also be written using the "fluent interface" method:

class Foo
{
public:
  Foo& setA(int a) { m_a = a; return *this; }
  Foo& setB(int b) { m_b = b; return *this; }
private:
  int m_a, m_b;
};

Now, if I write the following code snippet:

int main()
{
  Foo foo;
  foo.setA(1);
  foo.setB(2);
}

Is there a performance difference induced by the additional return directives if I use the second implementation of the class ?

Should I bother ? (My guess is "no")

6

There are 6 answers

0
Mark B On BEST ANSWER

Since the methods are inlined, the compiler should be able to see that the return value is unused and possibly optimize it away.

Use whichever way makes the most sense for your project design. Then, measure the performance and only if it's not good enough would you consider optimizing the code.

0
vinnyspb On

I think there will be no difference due to compiler optimization.

0
Fred Nurk On

Is there a performance difference induced by the additional return directives if I use the second implementation of the class?

I don't know, is there with your compiler and optimizer settings? I see nothing that prevents any overhead from being optimized away in the exact case you give, but I can imagine writing a naive, sub-optimal compiler for an esoteric platform which did not optimize this case.

If you think it matters in a given situation, test it instead of assuming.

0
Arun On

If the 2nd implementation is used and the return value of the set functions are not required, then it may be better to write as

  (void) foo.setA(1);
  (void) foo.setB(2);

so that the compiler or static analyzer does not complain that the return value is not used.

As for performance, returning the reference may (I am not sure) generate one/two additional assembly instructions compared to the 1st implementation, but may not any "real" difference.

7
Zac Howland On

With the way you've defined the classes, you won't see much of a difference (if any) between the two. However, if you fix your design a bit, you will:

class Foo1
{
public:
    Foo1(int a, int b) : m_a(a), m_b(b) {}
    void setA(int a) { m_a = a; }
    void setB(int b) { m_b = b; }
private:
    int m_a, m_b;
};

class Foo2
{
public:
    Foo& setA(int a) { m_a = a;  return *this; }
    Foo& setB(int b) { m_b = b;  return *this; }
private:
    int m_a, m_b;
};

Initializing Foo1:

Foo1 f(1, 2); // only constructor called

will be far more efficient than initializing Foo2:

Foo2 b; // constructor called
b.setA(1).setB(2); // 2 functions called

In some cases, that won't be a concern.

An additional concern you have with Fluent Interfaces is the ability for the end-user to use them incorrectly. When designing an interface, you want to design it so that it is very difficult for the user of your interface to break it. By returning a reference from every setter, if the user-code stored that reference and then the object is moved or deallocated, you have a dangling reference (and may not even realize it).

0
Raedwald On

Those kinds of performance differences are never important. But, prove me wrong with some measurements of a real application.