David H. Flint commented on merge request !420 at Scribble / GDLEnhanced2

David H. Flint
2019-05-06T15:58:04Z

Documentation on what Debug Iterators provide is at https://docs.microsoft.com/en-us/cpp/standard-library/debug-iterator-support?view=vs-2019. As far as I can tell, they just provide additional runtime checking, not debug information per se. I hadn't even realized that they existed, since I've not encountered them before.

I had to raise the scope lock to where it is as intervening threads can cause the range iterators to be invalidated. There does not seem to be any significant contention, as threads are limited to the concurrency of the machine, and the search and insertion is a small fraction of the thread's operating time compared to reading and processing the json file.

The cell file is already loaded and mapped earlier in startup. The issue with the dungeon drops is that server reads and parses in every single dungeon in the game on startup, rather than on-demand. This takes about a third of the overall startup time for me in a Release build. As you said, it's only used by an admin command though. I don't know how important the command is to people. Would it make sense to move this processing to a spawned background thread?

Yes, I've been in the position where I've been developing features that require loading many weenies on an underpowered machine. I don't know what the workflow is like for content creators, but as content creation is so important, anything we can do to make it faster and easier seems worthwhile.

I checked, and you are correct! std::async uses a ThreadPool. That explains why the performance isn't as bad as if we really were spawning over 6,000 threads! Thanks for pointing that out.

The C++ standard states that if policy is launch::async, the function creates a new thread. However the Microsoft implementation is currently non-conforming. It obtains its threads from the Windows ThreadPool, which in some cases may provide a recycled thread rather than a new one. This means that the launch::async policy is actually implemented as launch::async|launch::deferred. Another implication of the ThreadPool-based implementation is that there is no guarantee that thread-local variables will be destroyed when the thread completes. If the thread is recycled and provided to a new call to async, the old variables will still exist. We therefore recommend that you do not use thread-local variables with async.