45

I have a Particle System Engine in my C++ project and the particles themselves are just structs of variables with no functions. Currently, each particle (Particle) is updated from its parent class (ParticleSystem) by having its variables accessed directly. E.g.

particle.x += particle.vx;

I am however, debating using getters and setters like this:

particle.setX( particle.getX()+particle.getVX() );

My question is: Is there any performance overhead from calling getters and setters as opposed to just straight up data access?

After all, I do have many many particles to update through...

Pubby
  • 51,882
  • 13
  • 139
  • 180
sgtHale
  • 1,507
  • 1
  • 16
  • 28
  • 2
    The setters/getter are mainly for readability/maintainability of the code. Calling a function will have performance overhead than straight up data access. – Mohammed H Dec 13 '12 at 05:20
  • 4
    Getters and setters are ONLY for incapsulating the data, and the access to it. There is NO performance overhead, simple getters and setters are inlined by the compiler. – Martin Kristiansen Dec 13 '12 at 05:28
  • 4
    @habeebperwad: I can't imagine how they increase readability, but they certainly make it easier to change the implementation down the road. – Ed S. Dec 13 '12 at 05:29
  • 2
    @MartinKristiansen: Yeah, you'd hope so, and you're right most of the time, but not always. It's a good idea to check if you're calling functions in a tight loop which is performance critical. – Ed S. Dec 13 '12 at 05:30
  • 2
    @All. Obviously, the performance overhead won't be significant. But at the time of comparing calling-function and straight up data access, we can tell straight up data access will be faster even if the overhead is not a significant one. – Mohammed H Dec 13 '12 at 05:31
  • 1
    It's time to become familiar with a performance profiler; using profiling tools can answer the question definitively for a particular problem/environment .. as well as showing if this issue is the "real" performance bottleneck or not. It will also lead to *better questions* such as "*Why* is X [significantly] slower than Y?", should such a case be found. –  Dec 13 '12 at 05:33
  • @habeebperwad How is it faster with data access? – sgtHale Dec 13 '12 at 05:36
  • I like getters and setters and use them. But if you're looking for a different (and relatively old) viewpoint from Jonathan Blow, you could check out his rant (http://number-none.com/blow/rants.html) on 18 July 2004. He does make a neat argument for implicit vs explicit costs. – wrhall Dec 13 '12 at 07:11
  • Unrelated to performance, a better design would be to encapsulate this code inside a method `particle.move()` which can access the particles internal state. IMHO it is not really object oriented to use getters and setters in this style. – Jörn Horstmann Dec 13 '12 at 16:43

5 Answers5

66

Setters and getters have a performance overhead when not optimized out. They are almost always optimized out on compilers that do link time optimization. And on compilers that do not, if they have knowledge of the function body (ie not just a prototype) it will be optimized out. Just look up inline optimization.

However, you use getters and setters are there because you might want getting or setting that variable to have additional side effects. Like changing the position of an object also changes the position of nearby objects in a physics simulation or some such.

Finally, the overhead of a getter and setter operation, within the context of optimized code, is very small, not worth worrying about unless the code is hot. And if it's hot, it's SO EASY to just move the getter or setter to the header file and inline it.
However, in long running scientific simulations it can add up - but it requires millions and millions of calls.

So to sum up, getters and setters are well worth the minor or non-existent overhead, as it allows you to specify very specifically what can and cannot happen with your object, and it also allows you to marshal any changes.

zerocukor287
  • 555
  • 2
  • 8
  • 23
OmnipotentEntity
  • 16,531
  • 6
  • 62
  • 96
  • 5
    +1 for inlining (although the rest is spot on too). Inline and forget. – MPelletier Dec 13 '12 at 05:34
  • 6
    But be sure to remember, that inlining a function is a) only a suggestion, and b) will only work if the source file has all of the information available, so it has to be in the header. – OmnipotentEntity Dec 13 '12 at 05:35
  • @sgtHale, your compiler will take care of that for you, if it can. But the overhead we're talking about is so minuscule that you'd need to call the function in question millions of times to notice the difference. – OmnipotentEntity Dec 13 '12 at 05:36
  • 7
    Regarding the comments on "miniscule" and "insignificant": A function call costs cycles, and in scientific computing (where lots of gets/sets happen in large, long-running loops), they can cost you significant (wall) time if not optimized out. That said, inlining getters/setters is generally a good idea for future code flexibility. – Tony K. Dec 13 '12 at 05:42
  • 2
    @TonyK. I agree that it can be needed, but it very often isn't. Good point though that it can add up. Always use profiling to determine hot points in the code. And optimize as needed. – OmnipotentEntity Dec 13 '12 at 05:44
  • 1
    don't trust your compiler, you never know how it does the optimization. just code in the efficient way. – tomriddle_1234 Dec 13 '12 at 06:01
  • 1
    @tomriddle_1234: You mean assembly right ? Because otherwise your so carefully optimized code could be jumbled by the compiler anyway... – Matthieu M. Dec 13 '12 at 07:44
  • 2
    @MatthieuM. And we know that CPUs today don't do instruction pipeline reordering, because such techniques require the use of neural gelpacks. Oops, wait. They do. So there goes your carefully optimized assembly code, meaning you are *still* at the mercy of an optimizer. Besides, the compiler *probably* knows assembly language better than the OP does. – user Dec 13 '12 at 10:11
  • 3
    @OmnipotentEntity: On recent compilers, inlining can be done at link-time, meaning that a function can be inlined even if its definition is in an implementation file and not in a header. *Edit*: Oh wait, I just saw that you are the author of the answer! Since you evoke link-time optimization in your answer, I don't understand your comment about inlining being possible only if the definition is in a header. – Luc Touraille Dec 13 '12 at 11:36
  • 2
    @LucTouraille, on recent compilers, sure. I know clang has link time optimization, but you have to specify `-O4`, iirc. gcc has link time optimization, but you have to specifically request it using `-flto`, as `-O3` doesn't do it. Not sure about MSVC. – OmnipotentEntity Dec 13 '12 at 15:53
16

I have a different opinion to this than the previous answers.

Getters and setters are signs that your class isn't designed in a useful way: if you don't make the outer behaviour abstract from the internal implementation, there's no point in using an abstract interface in the first place, you might as well use a plain old struct.

Think about what operations you really need. That's almost certainly not direct access to the x- y- and z-coordinates of position and momentum, you rather want to treat these as vector quantities (at least in most calculations, which is all that's relevant for optimisation). So you want to implement a vector-based interface*, where the basic operations are vector addition, scaling and inner product. Not component-wise access; you probably do need to do that sometimes as well, but this can be done with a single std::array<double,3> to_posarray() member or something like that.

When the internal components x, y ... vz aren't accessible from the outside, you can then safely change the internal implementation without braking any code outside your module. That's pretty much the whole point af getters/setters; however when using those these there's only so much optimisation you can do: any real change of implementation with inevitably make the getters much slower.
On the other hand, you can optimise the hell out of a vector-based interface, with SIMD operations, external library calls (possibly on accelerated hardware like CUDA) and suchlike. A "batch-getter" like to_posarray can still be implemented reasonably efficient, single-variable setters can't.


*I mean vector in the mathematical sense here, not like std::vector.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
4

Getters and setters allow your code to evolve more easily in the future, if getting and setting turn out to be slightly more complicated tasks. Most C++ compilers are smart enough to inline those simple methods and eliminate the overhead of the function call.

Reuben Morais
  • 1,013
  • 1
  • 8
  • 20
2

There could be various answers to this question, but I put my thoughts here.

For the performance, the cost can be mostly ignored for simple POD type. But there 's still cost, and it depends on what type you return. For particle, there couldn't be much data. If this is a image class (like OpenCV cv::Mat), or 3d data (like PolyData in VTK), it is better that setter/getter deals with pointers/iterators than the actual data to avoid memory allocation problem.

When you want to template things, the setter/getter can be a lot useful to avoid inexplicit type conversion. A setter/getter can be a way to access private/protected member, which is also allows you to avoid using x as the common name of variable. More over, the setter/getter can return a Lvalue reference which allows you to do particle.getX() = 10.0 ;

tomriddle_1234
  • 3,145
  • 6
  • 41
  • 71
  • 1
    particle.getX() = 10.0 ; - But where/when does one need that? – SChepurin Dec 13 '12 at 06:57
  • 3
    @SChepurin When you want to not just break encapsulation, but break it *horribly*? – user Dec 13 '12 at 10:13
  • @Michael Kjörling, I think in this way it's more natural , why you say it breaks encapsulation ? – tomriddle_1234 Dec 13 '12 at 23:15
  • 1
    If exposing a member variable directly violates encapsulation (as is commonly and reasonably argued), then how does having a function to return a reference to that variable not break encapsulation? And in this case we aren't even talking about a potentially complex class, but rather a primitive value type (that written with the reservation that I don't know what the exact terminology would be in C++ parlace). I most definitely would not expect `getX()` to return a reference to the internal member variable, which certainly would not *reduce* confusion. – user Dec 14 '12 at 19:10
  • but this is C++ ..., millions of particles. I agree with you if this class has safety concern. – tomriddle_1234 Dec 16 '12 at 04:42
0

In this case, the functional meaning of your calcul could be :

void Particle::updatePosition() { x += vx; y += vy; }

or:

void Particle::updatePositionX() { x += vx; }

then :

particle.updatePositionX();

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 28 '21 at 06:56