0

I have a Linux code.

I would like to pre-allocate 10000 items of different types as circular array. I always know which object type it is.

Since biggest object takes 54 bytes - I want to allocate 10000 x 54 chunk of memory.

Whats the correct pointer arithmetic to retrieve reference to an object with index i ?

x64 architecture

uint8_t cache[10000 * 54];

MyType* o = static_cast<MyType*>(cache + i * 54);
o.Prop1 = 10;

is this right?

EDIT: I need most efficient solution

EDIT2: these are instances of classes not structs (if that makes difference for aligning)

EDIT3: 54 byte is red herring, consider any "appropriate" aligned size, also I compile it with g++ as C++20 on CentOS9

12
  • 2
    seems okay, except are the biggest object is okay with 2-byte alignment? also since you never called a constructor MyType had better not need it Commented May 16, 2022 at 15:21
  • 1
    @JonathanS. That's not quite the case now. C++20 introduces implicit lifetime types and they are "created" as soon as suitable storage is created. Commented May 16, 2022 at 15:24
  • 2
    Because the types are obviously not related. There's no polymorphism involved here. Commented May 16, 2022 at 15:35
  • 2
    Why is this not a union or variant then? Commented May 16, 2022 at 15:41
  • 1
    That's a much better question, a union would go a long way to simplifying this code. Commented May 16, 2022 at 15:48

2 Answers 2

3

Use std::array<std::variant<Type1, Type2, Type3, ...>, 100000> cache;

Sign up to request clarification or add additional context in comments.

4 Comments

is it as efficient as say static_cast? or union or anything else?
@BoppityBop std::variant stores type information and only has type-checked accessors. If you don't need the type-safety because you have type information stored somewhere else a union will do.
@BoppityBop, you can't static_cast<> that array to your objects, that's what static_cast<> is meant to explicitly prevent. What you're doing is a reinterpret_cast<>.
erm.. how it works now - I got a wrapper class which has void* Data; which holds any type of object. then I need to access it as a concrete object I do: static_cast<RecordTypeA*>(Data) and it works!.. still my question - how variant compares to anything else in terms of cpu cycles?
0

The pointer arithmetic is correct, however be very careful about those structure sizes. Unless you prevent padding (with like #pragma pack, for example), the compiler could easily throw a curve ball your way.

Also because your allocation is unaligned, you will be paying a moderate performance tax on every access inside that structure. If memory isn't an issue, you should 64-bit align your objects.

16 Comments

Never ever use #pragma pack for anything you read or write more than once. The compiler has to access the data byte-by-byte on many architectures for packed data which is horribly slow.
I disagree completely, having a known pack value is essential for this exercise where you rely on known all the types' sizes, to determine the largest allocation needed. Also you make it sound like a packing size isn't used regardless of whether you manually define it or not. A packing value is always used, you just don't know it unless you specify it yourself.
ok. i dont have pragma pack. i was expecting the data will be aligned by compiler so i never paid attention.. should i? am confused
@BoppityBop just use a variant or union and let the compiler figure out the proper size.
Cast and union are identical in terms of speed, a union is just a cast.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.