Const reference

Pages: 12
pointers to objects are being passed significantly slower than objects themselves
It is actually only slightly slower. And passing large objects by value is going to slow down even more than before. Not to mention that if you are passing something into function by reference and it is not inlined, you have a pointer pass anyway.

If you really want data locality, overload operator new for these classes and use custom memory allocator to ensure data locality.
Deleted.
Last edited on
 Last edited on Aug 13, 2015 at 12:52pm Krogoth wrote:
Is const reference like

class ...
int _kappa;
...
int const& kappa = _kappa;
...

somehow optimized by compiler?
I would like it to not create any actual reference at all.

Spent my time at this simplest question but didn't find a clear answer.


 On Aug 13, 2015 at 12:54pm MiiNiPaa wrote:
references (costant or not) can be optimised away by compiler but it is not required to do so. Generally references in same scope and passed to inlined functions are optimised away entirely. For others you will need to look into resulting code to see if that particular instance was optimised away.

Sometimes I don't believe people actually want an answer -- because they don't come any more simple or direct than that.

The problem is you keep changing your question to try and do something that isn't a good idea. And MiiNiPaa has been very patient with you and now you are being rude.
you are being rude
If so, excuse me please. Thank you for being so patient!

I would like to know the reason of something being not a good idea.

References are no longer a question.

The question is how to organize my objects better.

Look at shadowmouse's suggestion. If I understood it correctly, there are supposed stacks for each type of objects and a vector of pointers.
But: vector of pointers is located in one place, stacks are in different. That's why every cycle you jump from vector to stack. Stacks of different objects have additional distance, so it should slow the process even more.
(This is very far from being performance-critical, but what I am doing is just trying to find the best performance-wise solution)

By doing it through pointers, I also have to make the method virtual.

But I think this one is better:
1) make a vector of same type objects;
2) give a type id for each object;
3) put a short switch by type id into the method.

Pros: No pointers, No virtual methods
Cons: More members, Short switch

Am I wrong with the conclusion?
Last edited on
Sorry.


What I see happening is that you are worrying too much about "playing compiler", as I call it.
Don't try to do things weird and fanciful ways -- do them the way that the C++ books recommend. The compiler is designed to optimize things that are done the C++ way.

The second thing is that you are trying to generalize without giving specific "use cases". One structure may be more efficient than another, depending on how it is used.


What you are suggesting doing is essentially throwing out the C++ way of doing things and trying to recreate it with a clunkier, error-prone method involving a lot of switches and code that knows too much about your program.

The overhead of using virtual functions is minuscule, especially compared to trying to rewrite a method dispatch for every function. Seriously, you need to have some pretty good data from a profiler proving that your application is is bottlenecked at vtable lookup.


What actually affects performance is the high-level algorithm you are using. If you want code that is best performance-wise, make sure your algorithms behave properly. This is where university-level courses such as "Design and Analysis of Algorithms" come in handy.

Otherwise, it is a waste of time (and money) to spend a lot of effort trying to second-guess the efficiency of some feature of the language.


tl;dr: yes, your conclusion is premature. Use a simple vector (or other appropriate standard container) of polymorphic pointers. This will perform better than anything else you can do.

Hope this helps.
Ty all. I am still considering, what is better. )

Here is some of my code, implementing exactly my version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#ifndef GFX_HPP_INCLUDED
#define GFX_HPP_INCLUDED

#include <vector>

namespace keng {

class gfx {

public: // types
    enum types {
        sprite,
        base,
        point
    };
    static const int base_default_size = 10;

private: // default base
    static gfx* const default_base;

public: // special construct methods
    static gfx* create_sprite(
        int position = 0,
        int map = 0,
        int x = 0,
        int y = 0,
        float scale = 1.0f,
        gfx* base = default_base
    );

    static gfx* create_base(
        int position = 0,
        int size = 0,
        float scale = 1.0f,
        gfx* base = default_base
    );

    static gfx* create_point(
        int position = 0,
        int x = 0,
        int y = 0,
        float scale = 1.0f,
        gfx* base = default_base
    );

public: // switching methods
    void render();

    ~gfx();

private: // untitled special constructors
    // sprite
    gfx(
        int map,
        int x,
        int y,
        float scale
    );

    // base
    gfx(
        int size,
        float scale
    );

    // point
    gfx(
        int x,
        int y,
        float scale
    );

private: // help
    typedef std::vector<std::vector<gfx>> gfx_container_t;

    template<typename... Args>
    static gfx* construct(gfx* base, int position, Args... args);

private: // type data
    int type;

private: // switching data
  union {
    int map; // sprite
    gfx_container_t* gfx_container; // base
  };
  union {
    int map_x; // sprite
  };
  union {
    int map_y; // sprite
  };
  union {
    int x; // sprite / point
  };
  union {
    int y; // sprite / point
  };
  union {
    float scale; // sprite / base / point
  };
  union {
    bool mirror_x; // sprite
  };
  union {
    bool mirror_y; // sprite
  };

}; // class gfx

} // namespace keng

#include "gfx.hh"

#endif // GFX_HPP_INCLUDED 


There are 3 special types, implemented in 1 class: Sprite, Base and Point. They are put in order of use frequency.
Sprite happens most frequently, Base contains vector of Gfx, Point is just a demonstration thing. Default Base is the primary Gfx at which other Gfxs are created. If no specific base mentioned in constructor a Gfx is created at Default Base.
Default Base is meant to be like a screen, and other Bases - windows, and their sub-Bases - their sub-windows.
Base applies translation, scaling, filtering, etc to its sub-Gfxs.

Switching methods is how I call methods like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
inline void gfx::render() {
    switch (type) {
        case sprite:
        {
            int vertex_x1 = mirror_x * Spriteset::width[map];
            int vertex_x2 = (1 - mirror_x) * Spriteset::width[map];
            int vertex_y1 = mirror_y * Spriteset::height[map];
            int vertex_y2 = (1 - mirror_y) * Spriteset::height[map];
            GLfloat texture_x1 = Spriteset::normed_width[map] * map_x;
            GLfloat texture_x2 = texture_x1 + Spriteset::normed_width[map];
            GLfloat texture_y1 = Spriteset::normed_height[map] * map_y;
            GLfloat texture_y2 = texture_y1 + Spriteset::normed_height[map];
            glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, Spriteset::texture[map]);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glBegin(GL_POLYGON);
                glTexCoord2f(texture_x1, texture_y1);
                glVertex2f(vertex_x1, vertex_y1);
                glTexCoord2f(texture_x1, texture_y2);
                glVertex2f(vertex_x1, vertex_y2);
                glTexCoord2f(texture_x2, texture_y2);
                glVertex2f(vertex_x2, vertex_y2);
                glTexCoord2f(texture_x2, texture_y1);
                glVertex2f(vertex_x2, vertex_y1);
            glEnd();
            glDisable(GL_TEXTURE_2D);
            break;
        }

        case base:
            for (std::vector<gfx>& vg : *gfx_container)
                for (gfx& g : vg)
                    g.render();

        case point:
            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            glBegin(GL_POINTS);
                glVertex2f(.0f, .0f);
            glEnd();
            break;
    }
}


Any additional thoughts
?
Last edited on
Last edited on
Ty! Trying it.
Last edited on
Topic archived. No new replies allowed.
Pages: 12