Questionable advice

W

woodbrian77

I watched some of the videos from the C++ conference at
Microsoft. Some of the advice given was to not use raw
pointers for ownership. I think that's going too far.

http://webEbenezer.net/misc/SendBuffer.hh
http://webEbenezer.net/misc/SendBuffer.cc

Someone may say that that doesn't scale if we need to
add another pointer to the class. I disagree. Classes
can have at least one pointer that isn't wrapped with
a smart pointer.

http://webEbenezer.net/misc/SendBufferCompressed.hh
http://webEbenezer.net/misc/SendBufferCompressed.cc

Finally, at the conference STL pointed out that using a
delegated constructor you can safely have multiple raw
pointers in a class:

http://webEbenezer.net/misc/Compressed.hh
http://webEbenezer.net/misc/Compressed.cc

Previously I was using unique_ptr more than now, but
have found in each of these cases that the code that
results without using it so much is a little smaller.
I've seen a lot of overuse of shared_ptr over the years
and now think it's also possible to use unique_ptr too
much.

The simplified advice came from Bjarne. I think for
student programs it doesn't make much difference, but
he may be focussing too much on beginners these days.


Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
 
Ö

Öö Tiib

Previously I was using unique_ptr more than now, but
have found in each of these cases that the code that
results without using it so much is a little smaller.
I've seen a lot of overuse of shared_ptr over the years
and now think it's also possible to use unique_ptr too
much.

I have a question. Why any of those byte buffers that you posted are
better than simple 'std::vector<char>'?
 
W

woodbrian77

I have a question. Why any of those byte buffers that you posted are
better than simple 'std::vector<char>'?


They are simpler than vector and don't have the overhead
of vector's resize. That overhead may be needed to support
user defined types, but it is just a drag in this case.
 
Ö

Öö Tiib

They are simpler than vector and don't have the overhead
of vector's resize. That overhead may be needed to support
user defined types, but it is just a drag in this case.

What overhead? Since the program never calls 'resize' no code for it
will be generated. 'std::vector' is template.

Do you mean few bytes per buffer you save? If that really matters then
that 'new char [x]' likely has overhead there but all your linked code
does uses it. For example take 'vector' with allocator from Intel's TBB
'std::vector<char,tbb::scalable_allocator<char>>'.
It likely outperforms every single one of your posted buffers on any
desktop PC by some margin if you really expect so lot of those that
few bytes per buffer matter.
 
W

woodbrian77

What overhead?

The overhead of default initializing additional elements.
In this case it was zeroing out bytes.
Since the program never calls 'resize' no code for it
will be generated. 'std::vector' is template.

I believe there were a couple of places where I was calling
resize, but I can only remember one of them for sure...
I have some code that marshalls files and before reading
a file into memory I was resizing the vector.

Do you mean few bytes per buffer you save? If that really matters then
that 'new char [x]' likely has overhead there but all your linked code
does uses it. For example take 'vector' with allocator from Intel's TBB
'std::vector<char,tbb::scalable_allocator<char>>'.
It likely outperforms every single one of your posted buffers on any
desktop PC by some margin if you really expect so lot of those that
few bytes per buffer matter.

I don't know much about or do much with Intel software yet.
It needs to be something that is portable though.
 
W

woodbrian77

Previously I was using unique_ptr more than now, but
have found in each of these cases that the code that
results without using it so much is a little smaller.
I've seen a lot of overuse of shared_ptr over the years
and now think it's also possible to use unique_ptr too
much.

I tried changing away from another use of unique_ptr and
was surprised by how big of a difference it made in terms
of reducing the size of one of my executables. I changed
this

::std::deque<::std::unique_ptr<cmw_request>> pendingTransactions;

to this

::std::deque<cmw_request*> pendingTransactions;

The code that news the cmw_request was aready in a try block
so I set my cmw_request* to nullptr prior to the try and
in the catch I delete it. There are about 4 more lines
that delete the instance when I'm popping it out of the
deque. Anyway, the size of the executable dropped by over
2,000 bytes which is a little over 5%. I've done a lot of
work to keep the size of the executable down so getting
that much out of this change was really surprising. As I
mentioned earlier in this thread, the amount of difference
in generated code size that I'd seen previously from
minimizing use of unique_ptr had been quite modest.

Here's the code I'm talking about above. You can search
for pendingTransactions or delete to see the new stuff.

http://webEbenezer.net/misc/cmwAmbassador.cc

Please let me know if you have suggestions on how to
improve that.
 
I

Ian Collins

Anyway, the size of the executable dropped by over
2,000 bytes which is a little over 5%. I've done a lot of
work to keep the size of the executable down so getting
that much out of this change was really surprising. As I
mentioned earlier in this thread, the amount of difference
in generated code size that I'd seen previously from
minimizing use of unique_ptr had been quite modest.

You keep mentioning "the size of the executable" without ever saying
what you are measuring (or why it matters). The only environment where
you can accurately measure the size of the executable is on a
standalone, embedded, device.
 
J

jacob navia

Le 09/09/13 09:58, Ian Collins a écrit :
You keep mentioning "the size of the executable" without ever saying
what you are measuring (or why it matters). The only environment where
you can accurately measure the size of the executable is on a
standalone, embedded, device.

This is wrong. In most environments you can see the size of the text
section and in most executable formats the size of the loaded image is
written in the executable file
 
S

SG

I watched some of the videos from the C++ conference at
Microsoft. Some of the advice given was to not use raw
pointers for ownership. I think that's going too far.

http://webEbenezer.net/misc/SendBuffer.hh
http://webEbenezer.net/misc/SendBuffer.cc

Some of the advice was qualified with "outside of a managing class"
(or something like this). And even then you don't have to use raw
pointers for just managing memory. You're obviously targeting C++11
Someone may say that that doesn't scale if we need to
add another pointer to the class. I disagree. Classes
can have at least one pointer that isn't wrapped with
a smart pointer.

The more things a class has to keep track of, the more things can go
wrong. If you let your class manage more than one resource directly,
you're making your life possibly harder than it has to be.
Finally, at the conference STL pointed out that using a
delegated constructor you can safely have multiple raw
pointers in a class:

He did. He also said that he's not sure about what to think of that
approach. He certainly did not present it in a very positive light.
Previously I was using unique_ptr more than now, but
have found in each of these cases that the code that
results without using it so much is a little smaller.

You mean the compiled code? The binaries? Weird. I would not expect
that. I still don't.
I've seen a lot of overuse of shared_ptr over the years
and now think it's also possible to use unique_ptr too
much.

What makes you think so?
The simplified advice came from Bjarne. I think for
student programs it doesn't make much difference, but
he may be focussing too much on beginners these days.

The problem is that what one should and sould not do is not easily
put into a short word sequence. "no owning raw pointers" is an
approximation to that. It does require some explanation.

I would put this probably differently. "Delegate a resource management
problem to a class. Avoid writing classes that need to keep track of
too many things by breaking it into smaller classes". But it's not as
short as "no owning raw pointers". :)

Cheers!
SG
 
W

woodbrian77

It is also fair to say that it is mainly in embedded systems that a size
difference of 5% or 2000 bytes is particularly relevant - on a PC, it is
very unlikely to matter (unless you happen to hit instruction cache size
boundaries - sometimes "small" can mean a lot faster if loops fit within
the cache).

The executable in this case is a server intended to run at a
user's location. I expect it to be running on a machine with
other servers. The more well-behaved and efficient it is the
happier the user will be.
 
W

woodbrian77

On Sunday, September 8, 2013 6:28:53 PM UTC+2, (e-mail address removed) wrote:

Some of the advice was qualified with "outside of a managing class"
(or something like this). And even then you don't have to use raw
pointers for just managing memory. You're obviously targeting C++11


The more things a class has to keep track of, the more things can go
wrong. If you let your class manage more than one resource directly,
you're making your life possibly harder than it has to be.


He did. He also said that he's not sure about what to think of that
approach. He certainly did not present it in a very positive light.

OK, he may have said he used it in some code though.
You mean the compiled code? The binaries? Weird. I would not expect
that. I still don't.

Executables. It was just 8 bytes in one case. Another case
was a little more.

To add to something in my original post about scaling. If
you need to add an additional resource to a class that has
one already you can leave the first one as is and then either
use a unique_ptr or raw pointer and delegated constructor
depending for the additional resource.
What makes you think so?

I thought that when I wrote the original post and now
more so after changing another use of unique_ptr to a
raw pointer. I'm just looking at code sizes.
The problem is that what one should and sould not do is not easily
put into a short word sequence. "no owning raw pointers" is an
approximation to that. It does require some explanation.

I would put this probably differently. "Delegate a resource management
problem to a class. Avoid writing classes that need to keep track of
too many things by breaking it into smaller classes". But it's not as
short as "no owning raw pointers". :)

Yes, it is hard to quickly formulate what you want to say sometimes.
I don't have to do it very often so am glad for that. Anyway there
was quite a range of advice at the conference and some of it was
pretty good I think. Andrei's "Tweaking matters" was good advice
I think.
 
I

Ian Collins

The executable in this case is a server intended to run at a
user's location. I expect it to be running on a machine with
other servers. The more well-behaved and efficient it is the
happier the user will be.

So the size of the test segment is a measure of good behaviour and
efficiency? You do know that optimisations often trade size for
performance, don't you?
 
W

woodbrian77

So the size of the test segment is a measure of good behaviour and
efficiency? You do know that optimisations often trade size for
performance, don't you?

I'll try to do some run time testing of the two versions.
 
W

woodbrian77

I'll try to do some run time testing of the two versions.


OK these numbers are based on gcc 4.8.1 with -O3. I ran
each version 3 times. The version that used unique_ptr
had these results

user: 9.378
sys: 9.883

user: 9.286
sys: 9.790

user: 9.330
sys: 9.837

If you add that up and divide by 3 it is 19.168.

The version with the raw pointer:

user: 9.485
sys: 9.690

user: 9.369
sys: 9.857

user: 9.315
sys: 9.871

Add and divide by 3 and it is 19.196

So the raw pointer version is 0.15% slower than the
unique_ptr version. I would point out that the testing
was done on a machine that was over 98% idle when the
tests weren't running. In my opinion that favors the
unique_ptr version with its 5% more code. I haven't
thought about how to test things when the system is busier.
 
W

woodbrian77

Users will be happy if the program works as they want and they feel they
can control it. Size of the text segment is nowhere in sight here, I bet
most users would actually be rather unhappy if they had to learn what a
text segment is.

There may be a conflict between what you want and what you need.
I aim to provide what's needed. It doesn't matter if users don't
know about text segments.
 
W

woodbrian77

OK these numbers are based on gcc 4.8.1 with -O3. I ran
each version 3 times. The version that used unique_ptr
had these results

Sorry, ignore those results. I measured the wrong thing.
I'm retesting and plan to post again in 12 or so hours.
 
Ö

Öö Tiib

Do you mean few bytes per buffer you save? If that really matters then
that 'new char [x]' likely has overhead there but all your linked code
does uses it. For example take 'vector' with allocator from Intel's TBB
'std::vector<char,tbb::scalable_allocator<char>>'.
It likely outperforms every single one of your posted buffers on any
desktop PC by some margin if you really expect so lot of those that
few bytes per buffer matter.

I don't know much about or do much with Intel software yet.
It needs to be something that is portable though.

By "portable" people mean code base that is "configurable to compile for
several platforms". TBB seems to speed memory management up to 3 times
so it is worthy option to use it where available.
 
V

Victor Bazarov

There may be a conflict between what you want and what you need.
I aim to provide what's needed. It doesn't matter if users don't
know about text segments.

You're on a slippery slope pretending to be a judge of what users need
and how that's in conflict with what they want. Shouldn't the users be
the actual judges of that? Provide the best of what they _ask for_, not
what *you think* they "need"; don't waste your resources on making what
you think is a better solution, unless you know by having asked them
first. Same as with optimization - only improve what matters (IOW, no
sense in optimizing code that is rarely or never executed) and *only*
based on actual measurements, not conjecture.

V
 
W

woodbrian77

You're on a slippery slope pretending to be a judge of what users need
and how that's in conflict with what they want. Shouldn't the users be
the actual judges of that? Provide the best of what they _ask for_, not
what *you think* they "need"; don't waste your resources on making what
you think is a better solution, unless you know by having asked them
first.

I took Paavo's words about control to be an objection to my
on line and partially closed source approach. I'm not
forcing anyone to use the software. If someone wants to
provide an alternative service to what I'm doing, but
with open source all the way, that's fine. I wish them
well. Quality in my opinion is what's needed.
If someone wants whatever quality is available from my
service, they have to give up some control. When you
buy something, you are giving up control of some of your
money. This is just another example of the proliferation
of on line services. I didn't pioneer on line services,
but would just point to how this is popular business model
today.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top