Read Only Attribute?

Discussion in 'C++' started by Brian Genisio, Jan 8, 2004.

  1. Hello all,

    I am developing a class where speed is important, and memory size is
    also important. I need to give the user of the class read-only access
    to one of the private members (size as an int). I have two options:

    1. Make a method : int getSize() {return m_size;}
    2. Use a reference: const int &size;, and link it to the private size value

    Option #1 is nice, because it does not take an extra member, but it is
    slower.
    Option #2 is nice, because it is faster than a method, but it takes 4
    bytes per instance of the class

    In a non-optimized mode, option 1 is 2 times slower than option 2 (from
    some simple tests I did). On the other hand, in optimized mode, I did
    not notice a difference, as far as I can tell... but I think my
    optimizer was optimizing a lot more, so I am not sure that my test was
    accurate.

    What do you think? What is the most EFFICIENT way to do things?
    Usability and maintenance is not much of a concirn for me, since
    efficiency is much more important.

    Thanks,
    Brian

    I think I gave enough info, but in case you want to see the code, here
    is the test application.


    #include <iostream.h>
    #include "timer.h"

    class Tester
    {
    public:
    int getSize() { return m_size; }
    const int &size;

    Tester() : m_size(0), size(m_size) {}
    Tester(int setter) : m_size(setter), size(m_size) {}
    private:
    int m_size;
    };


    #define LOOP_SIZE 10000000

    int main(void)
    {
    int i;
    Tester my_test(20);
    int temp_size;
    BGTimer timer;

    timer.start();
    for(i=0; i<LOOP_SIZE; i++)
    temp_size = my_test.getSize();
    timer.end_and_print();

    timer.start();
    for(i=0; i<LOOP_SIZE; i++)
    temp_size = my_test.size;
    timer.end_and_print();

    return 0;
    }
     
    Brian Genisio, Jan 8, 2004
    #1
    1. Advertising

  2. On Thu, 08 Jan 2004 09:33:21 -0500, Brian Genisio wrote:

    > Hello all,
    >
    > I am developing a class where speed is important, and memory size is
    > also important. I need to give the user of the class read-only access
    > to one of the private members (size as an int). I have two options:
    >
    > 1. Make a method : int getSize() {return m_size;}
    > 2. Use a reference: const int &size;, and link it to the private size value
    >
    > Option #1 is nice, because it does not take an extra member, but it is
    > slower.
    > Option #2 is nice, because it is faster than a method, but it takes 4
    > bytes per instance of the class
    >
    > In a non-optimized mode, option 1 is 2 times slower than option 2 (from
    > some simple tests I did). On the other hand, in optimized mode, I did
    > not notice a difference, as far as I can tell... but I think my
    > optimizer was optimizing a lot more, so I am not sure that my test was
    > accurate.


    Any decent compiler will generate exactly the same code for the two
    methods with even modest optimization turned on. #1 is way more idiomatic
    and maintenance friendly. #2 has the added disadvantage it grows the
    object. Go with #1 and endure the slower speeds on debug builds.

    HTH,
    M4
     
    Martijn Lievaart, Jan 8, 2004
    #2
    1. Advertising

  3. "Brian Genisio" <> wrote...
    > I am developing a class where speed is important, and memory size is
    > also important. I need to give the user of the class read-only access
    > to one of the private members (size as an int). I have two options:
    >
    > 1. Make a method : int getSize() {return m_size;}
    > 2. Use a reference: const int &size;, and link it to the private size

    value
    >
    > Option #1 is nice, because it does not take an extra member,


    What do you mean by "extra member"?

    > but it is
    > slower.


    And you assert this based on what?

    > Option #2 is nice, because it is faster than a method, but it takes 4
    > bytes per instance of the class


    Again, what is the base for this assertion? The language Standard
    says that it is unspecified whether references require storage.

    > In a non-optimized mode, option 1 is 2 times slower than option 2 (from
    > some simple tests I did).


    Please explain how those _simple_ tests relate to the real programs
    you're to write.

    > On the other hand, in optimized mode, I did
    > not notice a difference, as far as I can tell... but I think my
    > optimizer was optimizing a lot more, so I am not sure that my test was
    > accurate.


    How can you be sure of the accuracy of the non-optimised code, then?
    What if your non-optimiser added some running-around a lot more?

    > What do you think? What is the most EFFICIENT way to do things?


    The simpler and more straight-forward it is, the more efficient it
    is. I would undoubtedly use the method #1.

    > Usability and maintenance is not much of a concirn for me, since
    > efficiency is much more important.


    Usability and maintenance is always a concern. If not to you, then
    to somebody who's going to maintain your code. Also, efficiency and
    maintainability are not mutually exclusive. Code doesn't have to be
    obfuscated to perform well.

    >
    > Thanks,
    > Brian
    >
    > I think I gave enough info, but in case you want to see the code, here
    > is the test application.
    >
    >
    > #include <iostream.h>
    > #include "timer.h"
    >
    > class Tester
    > {
    > public:
    > int getSize() { return m_size; }
    > const int &size;
    >
    > Tester() : m_size(0), size(m_size) {}
    > Tester(int setter) : m_size(setter), size(m_size) {}
    > private:
    > int m_size;
    > };
    >
    >
    > #define LOOP_SIZE 10000000
    >
    > int main(void)
    > {
    > int i;
    > Tester my_test(20);
    > int temp_size;


    You should declare temp_size 'volatile'. Otherwise the optimiser
    should throw your loops away as having no side effect.

    > BGTimer timer;
    >
    > timer.start();
    > for(i=0; i<LOOP_SIZE; i++)
    > temp_size = my_test.getSize();
    > timer.end_and_print();
    >
    > timer.start();
    > for(i=0; i<LOOP_SIZE; i++)
    > temp_size = my_test.size;
    > timer.end_and_print();
    >
    > return 0;
    > }
    >
     
    Victor Bazarov, Jan 8, 2004
    #3

  4. >>Usability and maintenance is not much of a concirn for me, since
    >>efficiency is much more important.

    >
    >
    > Usability and maintenance is always a concern. If not to you, then
    > to somebody who's going to maintain your code. Also, efficiency and
    > maintainability are not mutually exclusive. Code doesn't have to be
    > obfuscated to perform well.
    >


    No, code does not have to be obfuscated to perform well... but sometimes
    it does. I also agree that Usability and maintenance is always a
    concern, but in this case, for this issue, it is not _much_ of a concern
    (as I noted).

    B
     
    Brian Genisio, Jan 8, 2004
    #4
  5. Brian Genisio

    Kevin Saff Guest

    "Brian Genisio" <> wrote in message
    news:3ffd6a5d@10.10.0.241...
    > Hello all,
    >
    > I am developing a class where speed is important, and memory size is
    > also important. I need to give the user of the class read-only access
    > to one of the private members (size as an int). I have two options:
    >
    > 1. Make a method : int getSize() {return m_size;}


    That should be : int getSize() const {return m_size;}
    "const" should be used on all member functions that do not change the state
    of an object.

    First, you should not worry about efficiency until you have readable,
    tested, and correct code for your entire program. Then, use a profiler to
    see what exact functions need to be improved. Intuition is often wrong
    about these things, and you are better off having readable code than making
    possibly unnecessary optimizations.

    If you include the function definition in the class definition like you do
    here, C++ treats the function as "inline", which is a strong hint to the
    compiler to "inline" the function - directly incorporating the function code
    into the calling code without a function call. In this case, only a very
    bad compiler would generate a function call for this. The compiled code
    will probably be identical for:

    int x = object.getSize();

    as for:

    int x = object.m_size;

    if m_size were public.

    > 2. Use a reference: const int &size;, and link it to the private size

    value

    This is a bad idea. See http://cpptips.hyperformix.com/cpptips/ref_danger
    for some reasons.

    In addition, contrary to your opinion, a reference is usually stored as a
    pointer, so using a public reference like this introduces an additional
    pointer indirection which is not present when the above code is inlined - in
    other words #1 in a release build will (probably) access the int directly
    whereas #2 requires a pointer lookup. Your intuition on the speeds of these
    functions is reverse of the truth.

    From a design standpoint, if you couple your design so tightly to storing
    size as an int, you may as well make that member public.

    Furthermore, "size" is something that might not make sense to store directly
    as an int, and not accessing it through a function will restrict your
    design. "Optimizing" here can prevent you from doing more important
    algorithmic improvements. Short-sighted optimization like this is unlikely
    to result in an overall faster program, but is likely to restrict your
    options in making algorithmic improvements.

    > In a non-optimized mode, option 1 is 2 times slower than option 2 (from
    > some simple tests I did). On the other hand, in optimized mode, I did
    > not notice a difference, as far as I can tell... but I think my
    > optimizer was optimizing a lot more, so I am not sure that my test was
    > accurate.


    Your "non-optimized" mode is probably a debug build, which does not inline
    the function because then you cannot manually step through the source.

    If you don't trust your tests, why do them? Here's another test for you:
    dynamically allocate (operator "new") a bunch of these objects. In most
    programs dynamic allocation is a much larger bottleneck than function calls
    (even if the function were not inlined). Since your 2nd method increases
    the size of the object, I bet it will be much slower in dynamic allocation
    in both debug and release builds.

    > What do you think? What is the most EFFICIENT way to do things?


    The inline function. Hands down.

    > Usability and maintenance is not much of a concirn for me,


    In that case, please do not write any code which I may ever have to look at.

    > since efficiency is much more important.


    You cannot know if efficiency is important unless you have tests of correct
    code which indicate in which areas efficiency is important.

    HTH
    --
    KCS
     
    Kevin Saff, Jan 8, 2004
    #5
  6. Brian Genisio

    Howard Guest

    "Kevin Saff" <> wrote in message
    news:...
    >
    > You cannot know if efficiency is important unless you have tests of

    correct
    > code which indicate in which areas efficiency is important.
    >
    > HTH
    > --
    > KCS
    >

    I agreed with everything you wrote, up to this point. I work with real-time
    audio software that has portions of it where procesing must take place in
    the absolute minimum amount of time possible, with as little access to other
    objects or function calls as possible. In these instances, I sometimes have
    to intentionally do what would otherwise be poor coding practices, because I
    need to get in, compute a large volume of information VERY quickly, and get
    out. So there *are* occasions where efficiency is *known* to be more
    important. It's rare, admittedly, and I only do this in these rare,
    isolated circumstances. But it does happen, and unless you know the details
    of why the OP says efficiency is more important, you cannot state with
    accuracy that he's wrong.
    -Howard
     
    Howard, Jan 9, 2004
    #6
  7. Brian Genisio

    Kevin Saff Guest

    "Howard" <> wrote in message
    news:btn65b$...
    >
    > "Kevin Saff" <> wrote in message
    > news:...
    > >
    > > You cannot know if efficiency is important unless you have tests of

    > correct
    > > code which indicate in which areas efficiency is important.
    > >
    > > HTH
    > > --
    > > KCS
    > >

    > I agreed with everything you wrote, up to this point. I work with

    real-time
    > audio software that has portions of it where procesing must take place in
    > the absolute minimum amount of time possible, with as little access to

    other
    > objects or function calls as possible. In these instances, I sometimes

    have
    > to intentionally do what would otherwise be poor coding practices, because

    I
    > need to get in, compute a large volume of information VERY quickly, and

    get
    > out. So there *are* occasions where efficiency is *known* to be more
    > important. It's rare, admittedly, and I only do this in these rare,
    > isolated circumstances. But it does happen, and unless you know the

    details
    > of why the OP says efficiency is more important, you cannot state with
    > accuracy that he's wrong.
    > -Howard


    I'll take you word for it. I phrased it strongly since the OP was so sure
    efficiency was important without indicating some experience proving it so;
    and fascination with these kinds of "efficiency" issues is so often a
    distraction for beginners. I have to trust experts to make the right
    decisions, but the question asked was not an expert's question. Do you find
    the following amendment more palatable, or still unnecessarily harsh?

    > > You cannot know if efficiency is important unless you have tests of
    > > correct code which indicate in which areas efficiency is important,


    OR efficiency interferes with the development of such tests.

    --
    KCS
     
    Kevin Saff, Jan 14, 2004
    #7
  8. Brian Genisio

    Howard Guest

    "Kevin Saff" <> wrote in message
    news:...
    > I'll take you word for it. I phrased it strongly since the OP was so sure
    > efficiency was important without indicating some experience proving it so;
    > and fascination with these kinds of "efficiency" issues is so often a
    > distraction for beginners. I have to trust experts to make the right
    > decisions, but the question asked was not an expert's question. Do you

    find
    > the following amendment more palatable, or still unnecessarily harsh?
    >
    > > > You cannot know if efficiency is important unless you have tests of
    > > > correct code which indicate in which areas efficiency is important,

    >
    > OR efficiency interferes with the development of such tests.
    >


    That's fine.

    Or. just add "In general, " before your statement "You cannot know...".
    Sorry to be such a nit-picker, but statements of "absolutes" tend to attract
    my attention, especially when they contradict my personal experience.
    (Similar statements I've noticed have been "Never use global variables",
    "Always limit function bodies to one screenful of information", etc... I've
    responded to those as well, and sometimes started rather lengthy debates.
    :))

    -Howard
     
    Howard, Jan 14, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ferro
    Replies:
    2
    Views:
    372
    Adam Maass
    Nov 1, 2003
  2. keithb
    Replies:
    2
    Views:
    8,074
    keithb
    Jun 7, 2006
  3. Florian Lindner

    Mark attribute as read-only

    Florian Lindner, Mar 16, 2005, in forum: Python
    Replies:
    1
    Views:
    322
    Steven Bethard
    Mar 16, 2005
  4. Replies:
    10
    Views:
    888
    Default User
    Feb 17, 2006
  5. Replies:
    3
    Views:
    1,608
    Brandon McCombs
    May 2, 2007
Loading...

Share This Page