In today’s post, we will finally take a look at the last remaining piece of the new job system: adding dependencies between jobs.
Category Archives: Core
Job System 2.0: Lock-Free Work Stealing – Part 4: parallel_for
Continuing from where we left off last time, today we are going to discuss how to build high-level algorithms such as parallel_for using our job system.
Job System 2.0: Lock-Free Work Stealing – Part 3: Going lock-free
This week, we will finally tackle the heart of the job system: the implementation of the lock-free work-stealing queue. Read on for a foray into low-level programming.
Job System 2.0: Lock-Free Work Stealing – Part 2: A specialized allocator
As promised in the last post, today we will be looking at how to get rid of new and delete when allocating jobs in our job system. Allocations can be dealt with in a much more efficient way, as long as we are willing to sacrifice some memory for that. The resulting performance improvement is huge, and certainly worth it..
Job System 2.0: Lock-Free Work Stealing – Part 1: Basics
Back in 2012, I wrote about the task scheduler implementation in Molecule. Three years have passed since then, and now it’s time to give the old system a long deserved lifting.
Using runtime-compiled C++ code as a scripting language: under the hood
Some time ago, I announced that the Molecule Engine uses C++ as a scripting language. Today, I can share implementation details and a few additional tricks that were used to keep compilation times and executable sizes down.
Implementing a semi-automatic structure-of-arrays data container
In performance-sensitive applications like games it is crucial to access data in a cache-friendly manner. Especially when dealing with a large number of objects of the same type, e.g. individual components in an entity-component-architecture, we should make sure to read as little data as possible. However, simple arrays-of-structures are often not suited for this, with structures-of-arrays yielding better performance. But the latter are not natively supported by the C++ language.
Using runtime-compiled C++ code as a scripting language
Today’s post is less of an insight into how Molecule works, and more of an announcement about an upcoming feature we are very proud of!
Molecule Engine’s scripting system uses runtime-compiled C++ code as a scripting language, and you can see the system in action here (please make sure to watch the video in original quality).
This allows the engine to leverage the full performance potential of native C++ code, while providing designers and scripters with extremely short iteration times, commonly only experienced when using traditional scripting languages such as lua, python, or others.
Scripters won’t have to deal with internal engine details, and don’t need to worry about pointers or other low-level language stuff. They only work with a pure C-interface and opaque structs, as can be seen in the video. But programmers can easily dive in and feel right at home with the whole engine available to them in native C++-code.
Furthermore, programmers can aid scripters easily by using their favourite debuggers and IDEs for debugging and development. Scripters will love certain IDE features such as IntelliSense, completion listboxes, and other things a modern IDE provides!
Let us know what you think in the comments!
Memory allocation strategies: a growing stack-like (LIFO) allocator
Continuing from where we left of last time, I would like to discuss how we can build growing allocators using a virtual memory system. This post describes how to build a stack-like allocator that can automatically grow up to a given maximum size.
Memory allocation strategies interlude: virtual memory
Before we can delve into the inner workings of growing allocators, I would like to explain the concept of virtual memory and discuss what it is, why it is needed, and what we can use it for.
Continue reading
Memory allocation strategies: a pool allocator
As promised last time, today we will see how pool allocators can help with allocating/freeing allocations of a certain size, in any order, in O(1) time.
Memory allocation strategies: a stack-like (LIFO) allocator
Last time, we were looking at a linear allocator, probably the simplest of all memory allocators. This time, we will detail how to implement a non-growing stack-like allocator, along with conventional use-cases.
Memory allocation strategies: a linear allocator
During the next few weeks, I’d like to detail how the memory allocators inside Molecule work, starting with a simple, non-growing linear allocator today in order to cover some base first.
Building a load-balanced task scheduler – Part 4: False sharing
Even though a task scheduler can help with alleviating the burden of having to distribute small pieces of work to different threads, it cannot help preventing a few issues common in multi-threaded programming, especially in multi-processor environments.
Building a load-balanced task scheduler – Part 3: Parent-child relationships
Continuing from where we left off last time, this post explains how parent-child relationships are handled inside the task scheduler, and how streaming tasks can be split automatically by the scheduler.
Building a load-balanced task scheduler – Part 2: Task model
In this part of the series, we will discuss Molecule’s task model in detail, and have a look at the underlying C++ code and some subleties we need to watch out for, as well as some unique optimization opportunities.
Building a load-balanced task scheduler – Part 1: Basics
With multicore hardware becoming the norm in both PC/console-based gaming as well as on mobile platforms, it is crucial to take advantage of every processor core and thread being thrown at us developers. Therefore, it is important to build technology alleviating the task of writing correct, multi-threaded code.
In order to achieve that, this series will try to explain how to build a load-balancing, work-stealing task scheduler.
Living without dynamic strings
If there is one thing that’s completely banned from the Molecule Engine, it’s dynamic strings. I’ve always cringed at how many string operations and string-based look-ups where done in the last codebase I’ve been working with, hence I wanted to get completely rid of them in the run-time part of the engine – no exceptions.
SIMD’ifying multi-platform math
Nowadays, with each platform (even mobiles) supporting some sort of SIMD registers and operations, it is crucial for every codebase/engine to fully utilize the underlying SIMD functionality. However, SIMD instruction sets, registers and types vary for each platform, and sometimes between compilers as well.
This blog post explains how a platform-agnostic SIMD implementation can be built, without having to port large portions of the codebase for each new supported platform.
Generic, type-safe delegates and events in C++
While other languages such as C# offer type-safe callbacks/delegates out-of-the-box, C++ unfortunately does not offer such features. But delegates and events provide a nice way of “coupling” completely unrelated classes without having to write a lot of boilerplate code.
This blog post describes a generic, type-safe implementation of such delegates and events using advanced C++ features such as non-type template arguments and partial template specialization, supporting both free functions and member functions alike, without any restrictions or dynamic memory allocation.