-2

Say I have a struct

struct GRAPH {
 NODE* nodes[];
}

With a dynamic size for nodes[]. I also have

struct NODE {
 char filename[40];
 struct NODE* links[];
}

I will know how many links and nodes I need at runtime, and can calculate total required space. I know that running malloc() is runtime-costly, so doing a malloc() for nodes[], then adding the pointer from malloc() for each node would be bad.

I presume I will have to call malloc() for the total size of GRAPH, then manually handle pointers from this space, using a char* (1 byte) and saving offsets. Do I need to allocate for and handle null terminators at the end of each links[] (i.e. use calloc() with a larger size)? Is there a better way to be going about this?

04Khey
  • 3
  • 1
  • 1
    "I know that running malloc() is runtime-costly, so doing a malloc() for nodes[], then adding the pointer from malloc() for each node would be bad." It's bad in extremely high-performance scenarios that 99.99% of code does not care about. Just use `malloc` as needed, and consider bulk allocation only if performance is unacceptable. Trying to reimplement your own allocator on top of `malloc` (which is what this would entail) just in case `malloc` is too slow is the *definition* of premature optimization, which is the root of all evil. Regardless, we don't have nearly enough details to answer. – ShadowRanger Mar 15 '23 at 23:57
  • modern mallocs are extremely fast. Modern compilers are extremely good at optimizing code that juggles pointers. – pm100 Mar 16 '23 at 00:00
  • 1
    @pm100 whether you consider malloc fast or not is dependent on the platform, the size you are requesting, and whether you care about mean time, worst-case, best-case, etc. In some real-time applications, like games, runtime allocations are rarely ever done. – Nicholas Hayashi Mar 16 '23 at 00:05
  • I generally agree with the above commenters though, we would need more context about your problem to suggest the actual correct solution, and just malloc'ing memory as you need it *probably* is fine. When you said 'char* (1 byte)' did you mean that a char is 1 byte? A char* will be the size of a pointer on your platform, which is probably 4 or 8, not 1. In either case, you wouldn't need 'null terminators' at the end of your arrays if you know ahead of time how many 'links' each node will have. If you don't know ahead of time, it's more common to just explicitly store the 'count'. – Nicholas Hayashi Mar 16 '23 at 00:19

1 Answers1

1

You could do what you describe, but using malloc isnt inherently bad. In fact its not a problem the vast majority of the time. Depending on your platform and what your code will do with the graph, malloc is unlikely to be the performance bottleneck in your code.

In a HPC context for example, say it takes a few fractions of a second to allocate a large graph, you may then easily spend 1000x as long actually executing whatever your code is designed to do. That is probably what you should optimise.

That being said, if you did choose to make your own allocator you could use null terminators like you say, or if you knew how many of each structure you needed you could just allocate exactly what you need.