en:toolworks:docs:apparatus:architecture

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
en:toolworks:docs:apparatus:architecture [2021/06/07 17:12] – [Iterating] vladiusen:toolworks:docs:apparatus:architecture [2022/01/05 12:55] (current) – [Iterating] add TODO jispar
Line 1: Line 1:
 ====== Apparatus Architecture Overview ====== ====== Apparatus Architecture Overview ======
  
-Apparatus is a complex tool. It's more of a framework with its own ecosystem then some simple plugin. In order to use it effectively and consciously you have to understand how it actually works. We're not talking about the very specifics of the implementation however but the main top-level architectural concepts. We will begin our acquaintance with a top level "singletonian" entity called *Machine*.+Apparatus is a complex tool. It's more of a framework with its own ecosystem then simple plugin. In order to use it effectively and consciously you have to understand how it actually works. We're not talking about the very specifics of the implementation however but the main top-level architectural concepts. Let us begin our acquaintance with a top level "singletonian" entity called //Machine//.
  
 ===== Machine ===== ===== Machine =====
  
-Machine is the main system of Apparatus. It's a manager for the things global and thereby a global singleton itself. It's actually a UObject but its lifespan is defined by its internal state, not the standard garbage collecting procedures. If Machine has some Mechanicals defined within it, or there are still some Subjects in the "scene" it will be retained and remain available. Only when it's no longer needed and actually empty (meaninglessit will be available for a disposal+Machine is the main system of Apparatus. It's a manager for all the things global and thereby is a global singleton itself. It's actually a UObject but its lifespan is defined by its internal state, not the standard garbage collecting procedures. If the Machine has some Mechanisms defined within it, has some active Subjects spawned it will be retained and remain available. Only when it's no longer needed and becomes meaningless it will be enqueued for a disposal.
- +
-Within machine in particular and Apparatus as a whole, two "worlds" exist. Two levels of ECS data with their own unique features and optimizations.+
  
 The [[appi>class_u_machine.html|API documentation page]] for the ''UMachine'' class is of course available for your reference. The [[appi>class_u_machine.html|API documentation page]] for the ''UMachine'' class is of course available for your reference.
 +
 +===== Mechanisms =====
 +
 +//[[en:toolworks:docs:apparatus:mechanism|Mechanisms]]// to Apparatus are what Worlds to Unreal Engine. They provide a somewhat global state, a "scenery" context, comprising Subjects (Subjectives) and the Mechanics operating on them.
 +
 +Mechanisms are bound tight to their (Unrelean) World counterparts. If there are some Mechanics or Subjectives within your ''UWorld'', a Mechanism is created automatically. Of course, you can also obtain it manually or even create a separate (transient) Mechanism instance.
 +
 +Within the Machine/Mechanisms in particular and inside Apparatus as a whole, two relating "worlds" exist. These are two levels of ECS data processing with their own unique features and optimizations.
  
 ===== Low-Level Traits ===== ===== Low-Level Traits =====
  
-Let's start with the lower layer first. The *Traitssubsystem was actually developed later, but it's now at the core of the functionality and provides the needed base functionality for the upper layer to work properly.+Let's start with the lower layer first. The //[[en:toolworks:docs:apparatus:trait|Traits]]// subsystem was actually developed later in time, but it's now at the core of the framework and provides the needed functionality for the upper layer to work properly.
  
-ECS was once developed in performance in mind. Packing and storing the data linearly in memory. What could be simpler? While it's actually not that easy to implement this for dynamically structured entities and requires some sophisticated bookkeeping, the whole notion is correct. The whole hardware layer of CPUs and RAM is really tailored towards this memory organization. Modern day CPUs have some large cache capacities which are utilized more efficiently when used with data pieces stored next to each other.+ECS was once developed with performance in mind. Packing and storing the data linearly in memory, what could be simpler? While it's actually not that easy to implement this for dynamically structured entities and requires some sophisticated bookkeeping, the whole notion is correct. The hardware layer of CPUs and RAM is really tailored towards this memory organization. Modern-day CPUs have some large cache capacities which are utilized more efficiently when used with the data pieces stored next to each other.
  
 Unreal Engine's own memory model doesn't guarantee this level of linearity and using custom allocators is rather quirky or not viable at all. That's why we created the Traits subsystem. Unreal Engine's own memory model doesn't guarantee this level of linearity and using custom allocators is rather quirky or not viable at all. That's why we created the Traits subsystem.
  
-Traits are primarily based on [[ue>ProgrammingAndScripting/Blueprints/UserGuide/Variables/Structs|Structs]]. Those are managed exclusively by Apparatus and are stored in special buffers called Chunks. Right how it's supposed to be - one by one, sequentially, no gaps.+Traits are primarily based on [[ue>ProgrammingAndScripting/Blueprints/UserGuide/Variables/Structs|Structs]]. Those are managed exclusively by Apparatus and are stored in special buffers called //Chunks//, right how it's supposed to be stored - one by one, sequentially, no gaps.
  
-Traits are in turn assembled into collections (or it wouldn't be ECS after all). Those collections are called *Subjects* and are referenced through special *Handles*, not pointers. They are absolutely GC-independent and are disposed explicitly.+Traits are in turn assembled into collections (or this wouldn't be an ECS after all). Those collections are called //Subjects//Subjects are referenced through some specially designed //Handles//, not pointers. They are absolutely GC-independent and are disposed explicitly.
  
-The whole design maximizes the performance of the Mechanics running on the Subjects, but it actually has some limitations comparing to the higher-level *Details*.+The whole design maximizes the performance of the Mechanics running on the Subjects, but it actually has some limitations comparing to the higher-level //Details//.
  
 ===== High-Level Details ===== ===== High-Level Details =====
  
-Unlike Traits, Details are not Structs. They are "Unrealean" types of things - Objects (or [[ue>API/Runtime/CoreUObject/UObject/UObject|UObjects]] to be more specific). This makes them really versatile in terms of utilizing existing Unreal Engine's functionality. Not only that but they also support hierarchical filtering and even multi-detail iterating.+Unlike Traits, Details are not Structs. They are high-order "Unrealean" types of things - Objects (or [[ue>API/Runtime/CoreUObject/UObject/UObject|UObjects]] to be more specific). This makes them really versatile in terms of utilizing existing Unreal Engine's functionality. Not only that but they also support hierarchical filtering and even multi-detail iterating (which is quite useful when dealing with multiple details of the same type on a single Subject).
  
-Details are always stored in their respective *Subjectives* - this is a special type of container that is directly associated with an Unreal Actor or User Widget. Subjectives are not iterated directly however but through a special caching storage called *Belt*. It's a sparse type of storage and is used as an optimization mainly, containing only references to original details.+Details are always stored in their respective *Subjectives* - this is a special type of container that is directly associated with an Unreal Actor or User Widget. Subjectives are not iterated directly however but through a special caching storage called //Belt//. It's a sparse type of storage and is used as an optimization mainly, containing only references to original details. You can assign custom Belts manually on a per-Subjective basis and they will expand appropriately when needed.
  
-Please note, that all of the Subjectives are actually Subjects internally. They all have a Subject [[appi>struct_f_subject_handle.html|Handle]] in them. This means you can add traits to them. You can interchangeably utilize the both worlds together when/if needed. It's all up to you.+Please note, that all of the Subjectives are actually Subjects internally. They all have a Subject [[appi>lass_i_subjective.html#a0193ef8d2268c03c0aedc5d584383f71|Handle]] in them. This essentially means that you can add traits to them. You can interchangeably utilize the both worlds together when/if needed. It's all up to you.
  
 ===== Enchaining ===== ===== Enchaining =====
  
-One of the main technical goals of Apparatus is to effectively process some very large amounts of subjects and subjectives (our [[en:toolworks:docs:apparatus:ecs-glossary|own term]] for ECS' entities) under a specific filter. With that in mind a special concept of *enchainingwas developed.+One of the main technical goals of Apparatus is to effectively process some very large amounts of Subjects and Subjectives (our [[en:toolworks:docs:apparatus:ecs-glossary|own term]] for ECS' Entities) under a specific filter. With that in mind a special concept of //enchaining// was developed.
  
-Enchaining is a process of collecting all of the currently available belts and chunks matching a certain filter and embodying them in a special type of array called *chain*. Chains are managed by the machine singleton and you won't be creating them manually, even when using C++ workflow.+Enchaining is a process of collecting all of the currently available Belts and Chunks matching a certain filter and embodying them in a special type of array called //Chain//. Chains are managed by the corresponding Mechanisms and you won't be creating them manually, even when using the C++ workflow.
  
-Instead you have to use a global (static) [[appi>class_u_machine.html#a2e5ea120176a0485076c903cc98e6ea2|Enchain methods]], passing them a filter of the desired selection. You can either enchain belts or chunks together. While they are being enchained and the chain actually exists the respective belts or chunk are also *locked*.+Instead you have to use Mechanism'[[appi>class_u_mechanism.html#a2e5ea120176a0485076c903cc98e6ea2|Enchain methods]], passing them a filter of the desired selection. You can either enchain Belts or Chunks (together called //Iterables//). While they are being enchained and the Chain actually exists the respective Belts or Chunks also remain //locked//.
  
 ===== Locking ===== ===== Locking =====
  
-During iterating the chains and their respective chunks and belts we have to guarantee a certain level of immutability for them. We don't want to process the same subject twice, for example, as it may be tossed around chunks while being structurally modified inside the currently ongoing iterating. The belt/chunk locking functionality is designed specifically for that purpose.+During iterating the chains and their respective chunks and belts we have to guarantee a certain level of immutability for them. We don't want to process the same subject twice, for example, as it may be tossed around Chunks while being structurally modified inside the currently ongoing iterating. The Belt/Chunk locking functionality was designed specifically for that purpose.
  
-When the chunk or belt becomes enchained, its internal locks counter is incremented essentially making it somewhat frozen to the evaluating mechanic that is going be working on that chain. You can worry-free use the chain cursor and let Apparatus handle all the immutability issues for you.+When the Chunk (or Belt) becomes enchained, its internal locks counter is incrementedmaking it somewhat frozen to the evaluating Mechanic (the one that is going be working on that Chain). You can worry-free use the Chain //Cursor// and let Apparatus handle all the immutability issues for you.
  
 ===== Filtering ===== ===== Filtering =====
  
-*Filteringis an essential part of the ECS paradigm implementation. It lets you select specific subjects and subjectives to work upon. Using the word *selectin this context is not by chance as the term could be very familiar to a database programmer, for example. Technically it's quite the same. You define a WHERE clause with a set of conditions to meet. These can be both inclusive (positive) and exclusive (negative).+//[[en:toolworks:docs:apparatus:filter|Filtering]]// is an essential part of the proper ECS implementation. It lets you select specific Subjects and Subjectives to work apon. Using the word "selectin this context is not by chance as the term could be very familiar to a database programmer. Technically it's quite the same. You define a "WHEREclause with a set of conditions to meet. These can be both inclusive (positive) and exclusive (negative).
  
 Apparatus uses all sorts of different optimization schemes and caches to make the filtering process as fast as possible. You shouldn't worry too much about that. Apparatus uses all sorts of different optimization schemes and caches to make the filtering process as fast as possible. You shouldn't worry too much about that.
- 
-[[appi>struct_f_filter.html|API documentation]] for filters. 
- 
  
 ===== Iterating ===== ===== Iterating =====
  
-Once you have your Subjects spawned and set. Belts or Chunks enchained you're ready to iterate on them to deliver the necessary logic of the game or application. This is done through a very common concept of *Iteratorsand *Cursors*.+Once you have your Subjects spawned and set. Belts or Chunks enchained you're ready to //[[en:toolworks:docs:apparatus:iterating|iterate]]// on them to deliver the necessary logic of the game or application. This is done through a very common concept of //Iterators// and //Cursors//.
  
-Both Belt and Chunk have their own types of Iterators, but you would rarely use them directly. Instead you'll almost always use Chain Cursors. They are essentially Iterators with a naming chosen to eliminate some possible ambiguity. For now you should only use the default (implicit) Cursor as the threading is still a planned feature and you would rarely need to iterate a Belt (or a Chunk) with multiple different Cursors.+Both Belt and Chunk have their own types of Iterators, but you would rarely use them directly. Instead you'll almost always use the Chain Cursors. They are essentially Iterators with a naming chosen to eliminate some possible ambiguity. /* TODO - update this line for current Apparatus version - For now you should only use the default (implicit) Cursor as the threading is still a planned feature and you would rarely need to iterate a Belt (or a Chunk) with multiple different Cursors. */
  
 The API documentation for [[appi>struct_f_chunk_chain.html#a81fe6a135e15ca00736cdd6ef527c3f3|Begin]] and [[appi>struct_f_belt_chain.html#a8552c76ac87bcafb0a8077bbea5ade90|Advance]] methods is provided accordingly. The API documentation for [[appi>struct_f_chunk_chain.html#a81fe6a135e15ca00736cdd6ef527c3f3|Begin]] and [[appi>struct_f_belt_chain.html#a8552c76ac87bcafb0a8077bbea5ade90|Advance]] methods is provided accordingly.
  
 +
 +===== Afterword =====
 +
 +This overview is of course just an overview of what Apparatus really is but we hope it helps you to grasp the main idea of the toolset. We will continue to elaborate on the specifics of the implementation in some separate articles of the Turbopedia. Stay tuned.
  
  • en/toolworks/docs/apparatus/architecture.1623075175.txt.gz
  • Last modified: 2021/06/07 17:12
  • by vladius