rustgd / vnodes

[Experimental] Virtual node system
Apache License 2.0
6 stars 0 forks source link

Performance of `InternedMap` #2

Open torkleyy opened 6 years ago

torkleyy commented 6 years ago

While the performance isn't bad, it is "only" about two times faster than FnvHashMap (with strings!).

@OvermindDL1 did you do any benchmarks on your maps? Do you know how they compare to string maps given a size of 32?

torkleyy commented 6 years ago

Relevant benchmark:

https://github.com/rustgd/vnodes/blob/0cc76c17361e4dc452c2741df1f8517ecafde3ee/benches/intern.rs#L38-L49

OvermindDL1 commented 6 years ago

I actually didn't benchmark my maps, I mostly just used the unordered_map from Boost up until a few-odd years ago when https://github.com/greg7mdp/sparsepp came out. I only do path lookups rarely, mostly at 'loading' time (like level load or so) and just cached the result where needed in the systems. For dynamic access I'd often use more direct calls as they know what they are accessing anyway so could refine the type to be specific. Mostly at 'play time' the paths would be accessed for debugging information, but otherwise it was almost entirely cached.

Do note, the (hash/tree)maps I generally only used on branching nodes, most specific nodes were a unique type that held it's own information much more specific for it's purpose, like if they were an entity link or a piece of hardware or so.

So honestly I'd not worry too much about performance, it's good to improve it, but it's primarily accessed not at play-time itself so it was never an issue for me.

torkleyy commented 6 years ago

I'm pretty sure there will be cases where I don't know the type of the node, but I can cache them, yes.

OvermindDL1 commented 6 years ago

Yeah, in my systems I'd often have them be like (not at home so from memory):

struct some_system {
private:
    SomeNode *nodeblah_;
    AnotherNode *nodebloop_;
    Node *unknownnode_;
public:
    some_system(Context &ctx) {
        nodeblah_ = ctx.rootnode<SomeNode>["/dev/some"]; // These are type safe, null pointer if not the right type
        nodebloop_ = ctx.rootnode<AnotherNode>["/vwoop"]["/vweep"];
        unknownnode_ = ctx.rootnode["/some/node/that/I/don't/know/the/type/of"];
        assert(nodeblah_);
        assert(nodebloop_);
        assert(unknownnode_);
    }

    void operator()() {
        // process system, maybe access `nodeblah_` straight, maybe access a
        // child of nodebloop_, maybe set event hooks on unknownnode_, whatever...
    }

    // ... other things  It was templated so only relevant parts were accessed
    // efficiently without pointer indirections needed as well as being able to
    // generate 'most' of the dependency graph at compile-time and generated the
    // rest at load-time.
}
torkleyy commented 6 years ago

The problem I see with hardcoding the type is that the node cannot be easily overwritten, which could be quite useful for modding.

OvermindDL1 commented 6 years ago

The problem I see with hardcoding the type is that the node cannot be easily overwritten, which could be quite useful for modding.

Hmm, I've never actually needed to script-up a node that wasn't an entity so I've never seen the need. Most of my 'nodes' are just entity link's (EntityNode), which you then pass to systems as normal. Systems, on the other hand, have been heavily scripted and modded (as well as components). Scripts/mods can, however, 'access' Nodes with no issues, including via their fully dynamic interfaces.