From: NL on
Hi,

I'm thinking about changing some of my arrays of structures to
vectors, but it seems like it might be quite a bit slower. Can anybody
shed some light on the following example?
With the array method, when I want to add to the FooList, I call
GetNextFoo() which returns a pointer, and I can just fill in my foo
object directly.
With the vector method, it seems like I have to make a local copy of
the foo structure, fill it out, and then call vector.push_back, which
to me seems like it would have to make a copy to put in the vector.
This could be expensive since the foo object is quite large.
Are there ways to avoid the copying?

Thanks,
NL


struct Foo{
double x[1000];
double y[1000];
};

Array method :
class FooList {
Foo theFoos[5000];
int numFoo;
Foo* GetNextFoo() {
return &theFoos[numFoo++];
}
}

Vector method;
...
Foo f;
<fill out f>
fooVector.push_back(f) // I assume this makes a copy before adding the
object to the vector?



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: nabulke on
On 3 Feb., 23:41, NL <norv...(a)gmail.com> wrote:
> Hi,
>
> I'm thinking about changing some of my arrays of structures to
> vectors, but it seems like it might be quite a bit slower. Can anybody
> shed some light on the following example?

"Premature optimization is the root of all evil". Did you measure/
profile it?

> With the array method, when I want to add to the FooList, I call
> GetNextFoo() which returns a pointer, and I can just fill in my foo
> object directly.

You could just use a vector of pointers to Foo, or even better a
vector of smart pointers to foo so you don't get any issues with
memory allocation/deallocation.

> With the vector method, it seems like I have to make a local copy of
> the foo structure, fill it out, and then call vector.push_back, which
> to me seems like it would have to make a copy to put in the vector.
> This could be expensive since the foo object is quite large.
> Are there ways to avoid the copying?
>
> Thanks,
> NL
>
> struct Foo{
> double x[1000];
> double y[1000];
>
> };
>
> Array method :
> class FooList {
> Foo theFoos[5000];
> int numFoo;
> Foo* GetNextFoo() {
> return &theFoos[numFoo++];
> }
>
> }
>
> Vector method;
> ..
> Foo f;
> <fill out f>
> fooVector.push_back(f) // I assume this makes a copy before adding the
> object to the vector?
>

Yes, push_back uses the copy constructor to make one copy of the
element Foo. Using pointers would make this very cheap.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Feb 3, 11:41 pm, NL <norv...(a)gmail.com> wrote:
> Hi,
>
> I'm thinking about changing some of my arrays of structures to
> vectors, but it seems like it might be quite a bit slower. Can anybody
> shed some light on the following example?
> With the array method, when I want to add to the FooList, I call
> GetNextFoo() which returns a pointer, and I can just fill in my foo
> object directly.
> With the vector method, it seems like I have to make a local copy of
> the foo structure, fill it out, and then call vector.push_back, which
> to me seems like it would have to make a copy to put in the vector.
> This could be expensive since the foo object is quite large.
> Are there ways to avoid the copying?

First question you need to answer, to yourself, is: does it matter, in
your code, the way it's supposed to run in at least some usage
scenarios? (IOW, did you conclude that it's slower through
measurement?). Because if not, you are in premature optimization land.

That said, not entirely, no. But note that vector and your array have
different capabilities. vector will grow as large as needed, or as
there is memory. Your array grow up to compile-time defined constant.
Note also that for small values of numFoo, you're mightily wasting
storage (that's IMO the number 2 reason why one should never use fixed-
size storage, number 1 being "what if you need element 5001 and there
__indeed is__ space for it on the heap?").

Mitigating factors:

1. you can use reserve() to minimize heap re-allocations (but the
price is wasted storage like with compile-time-fixed size).

2. you can also use resize() and numFoo (similar price as with above).

3. you can use vector<Foo*>, but expose reference-like semantics in
access to Foo-s from FooList (why "List", BTW? It's an array, or a
vector, and list is something else; I personally prefer to name
containers with a simple plural (Foos) whenever possible and use tools
to find out what operations on them are). That practically avoids
copying overhead, but needs more storage and possible fragmentation.

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ralf Fassel on
* NL <norvinl(a)gmail.com>
| Array method :
| class FooList {
| Foo theFoos[5000];
| int numFoo;
| Foo* GetNextFoo() {
| return &theFoos[numFoo++];
| }
| }
|
| Vector method;

class FooList {
FooList() : theFoos(5000) {};
std::vector<Foo> theFoos;
int numFoo;
Foo* GetNextFoo() {
return &theFoos[numFoo++];
}
};

There really should be no difference. Just init the vector the same
size as your array, then you don't need push_back().

R'

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: NL on
Hi

First of all, thanks for the replies:

Regarding premature optimization, the creation and filling of the
vector is currently 90% of the execution time in the semi real time
system, so I'm just exploring what overhead I'm adding before jumping
in with both feet.

>
> You could just use a vector of pointers to Foo, or even better a
> vector of smart pointers to foo so you don't get any issues with
> memory allocation/deallocation.
>

I don't understand. What container are the actual Foo's stored in? If
a vector, then my issue still exists. (My issue is in creating and
filling the container of Foo objects. With the array, I currently fill
in an already existing chunk of memory, with a vector I'll need to do
the same, but then copy the memory to another location.)
The temporary object I'm creating and filling is local to the
function, so a pointer to it would be useless outside the function,
no? Or maybe smart pointers could help here?

Thanks,
Norvin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]