High performance encapsulation and networking in Casanova 2
Introduction
The video games industry is an ever growing sector with sales surpassing 20 billion dollars in 2014 [1]. Video games are not only built for entertainment purposes, but they are also used for Edutainment, Higher Education, Health Care, Corporate, Military, Research, and others [2], [3]. These so-called serious games usually do not enjoy the budgets available in the entertainment industry [4]. Therefore, developers of serious games are interested in tools capable of overcoming the coding difficulties associated with the complexity of games, and reducing the long development times.
Video games are composed of several inter-operating components, which accomplish different and coordinated tasks, such as drawing game objects, running the physics simulation of bodies, and moving non-playable characters using artificial intelligence. These components are periodically activated in turn to update the game state and draw the scene. When game complexity increases, this leads to an increase in size and complexity of components, which, in turn, leads to an increase in the complexity of developing and maintaining them, and thus an increase of development costs.
A possible approach to reduce development costs is to use game development tools (e.g., GameMaker, Unity3D, or UnrealEngine [5]), which tend to produce simple games that are hard to customize and bound to a specific genre. To provide some level of customization, game developers rely on general-purpose languages (GPLs) [6]. GPLs are typically unable to provide domain-specific abstractions and constructs. This means that when developing games by means of a GPL the resulting code will be complex and expensive to maintain [7], [8]. According to [9], the typical life cycle of software implemented by means of a GPL is: (i) building a prototype; (ii) designing a version in which the code is readable and maintainable; and eventually (iii) refactoring, after obtaining confidence with the context and the problem, the code from the previous point, so as to realize the last (often non-functional) requirements.
We can see that the just introduced cycle is applicable to game development as well: (i) building a game prototype is always necessary to take confidence with the context of the problem and the chosen tool; (ii) designing game code that is maintainable and readable requires developers to abstract the problem and to focus more on the high-level interactions of the game and its data structures. Software development techniques have been studied to improve software maintainability and tackle complexity [10]. Encapsulation, which consists of isolating a set of data and operations on those data within a module and providing precise specifications for the module [11], is an example of a technique aimed at increasing code maintainability and readability; and (iii) refactoring is a common process in game development, see for example the case of performance optimization, which is of high importance for games, since it is strictly connected to game smoothness, i.e., to the game’s frame rate, and smoothness strongly influences the perceived quality of a game [12]. Indeed developing a game is a highly dynamic process [13] involving a wide variety of team members with different roles, such as designers, programmers, etc. Design very often changes during the development stage, as proven in several examples from the industry, such as Starcraft, Duke Nuke’em Forever, and Final Fantasy XV [14]. Small changes at the abstract design level translates into considerable amount of code, which might affect the overall architecture; thus every stage of the above life cycle requires effort and is time consuming. An example of this is when using encapsulation [15] in the code. Since a game may feature many small entities, encapsulation forces those entities to interact through specific interfaces. When calling methods of the interfaces, overhead is added due to dynamic dispatching [15]. Such overhead ultimately affects the performance of games at runtime negatively, so a complete refactoring that accommodates performance becomes necessary. Similar negative effects come from various design patterns, which all add layers of indirection. These effects impact negatively cache coherency and force CPU prediction failures. Traditional networking in games is another example that typically breaks encapsulation as the what to send over the network is dependent on the game logic; thus small changes in the game structure could affect heavily the networking layer.
What seems ideal is to have the advantages coming from both stages (ii) and (iii): game code that is well maintainable and readable, and at the same time with a fast run time. For this purpose, we investigated this problem and developed a solution that allows developers to write encapsulated code. Encapsulation is “a language mechanism for restricting direct access to some of the object components.”. According to the definition of encapsulation, data and operations on them must be isolated within a module and a precise interface must be provided. Our solution turns, through extensive automated optimization, encapsulated code into an equivalent high-performance executable, therefore relieving developers from refactoring important design structures by hand, thus reducing the chances to make mistakes. As a further note, we want to underline that this optimization could be performed at source code level; however the logic of the program would be irremediably lost in the complex details of the architecture needed for the optimization, and thus debugging the code would be impractical. This is why we decided to look for a solution at a lower level of abstraction.
To sum up, in this paper we present a solution, which makes use of optimization transformations, that addresses the problem of the loss of performance in encapsulated games and of abstracting networking primitives. We present our solution as an extension for a domain specific language for games, called “Casanova 2”, which allows developers to write high quality games at reduced development costs.
We start with a discussion about the focus of this paper1 and related work (Section 2). Then we start with a discussion of encapsulation and typical optimizations (which break encapsulation) and their complexity, by introducing a case study. We use the case study to identify issues in using both encapsulation and faster implementation for games (Section 3). We introduce our idea for dealing with encapsulation without losing performance (Section 4). We propose a specific implementation, with corresponding semantics, within the Casanova 2 language (Section 5). We discuss a further extension of Casanova 2 in the domain of networking and show how the language can also provide significant improvement in productivity (Sections 6 Networking in Casanova 2, 7 Networking architecture). We then evaluate the effectiveness of our approach in terms of performance and compactness (Section 8), round off with conclusions, and present future challenges within this scope (Section 9).
Section snippets
Focus of the work and related work
The focus of this paper lies exclusively within the restricted, non-general-purpose field of game development (and its sibling, real-time simulations). This greatly narrows the scope of the problem, but also severly constrains the spectrum of possible solutions. To understand this, consider that on one hand we have the deep complexity of the underlying mathematics of the physical aspects of the game and the highly concurrent nature of the discrete logic; on the other hand, we have the
Encapsulation in games
In this section we discuss first common issue arising from traditional facilities for game development. We then introduce a short example to explain the problem of encapsulation in games. Eventually, we discuss the advantages and disadvantages of using encapsulation when designing a game.
Optimizing encapsulation
In this section we introduce the idea of a code transformation technique that changes encapsulated programs into semantically equivalent but more efficient implementations.
Implementation details
In this section we show how to select the predicates and the associated blocks of code that can be optimized.
Most games represent simulations of some sort. A property of simulations is a certain temporal locality of behaviors [31]. This translates to the fact that some predicates tend to have a high chance of no value change between frames. To reduce the amount of interactions and achieve better performance, we could optimize those predicates that exhibit temporal locality. This can be
Networking in Casanova 2
In this section we introduce the basic concepts of the implementation of multiplayer game development for Casanova 2. This implementation aims to relieve the programmer of the complexity of hard-coding the network implementation for an online game, while preserving encapsulation in code. We show that code analysis is required to generate the appropriate network primitives to send and receive data. Finally, we present a simple multiplayer game to show a concrete example.
Networking architecture
In this section we introduce a small example that addresses the requirements of designing a multiplayer game. We then present an architecture that aims to fulfill these requirements.
Evaluation
In this section we evaluate the performance of our approach. A comparison on the same Casanova game code between the non-optimized implementation, the optimized one, and an implementation in C#, will be shown and discussed in terms of run-time performance and code complexity.
Conclusions
Game developers often have to choose between maintainability of their code and speed of execution, a choice that more often than not favors speed over maintainability. By using encapsulation, game code may be written in a maintainable way, but compilation of encapsulated code in general-purpose languages often leads to slower games. We proposed a solution to the loss of performance in encapsulated programs using automated optimization at compile time. We presented an implementation of this
References (45)
- E. software association (esa), Essential facts about the computer and video game industry, 2016....
- CMP Media Game Developers Conference, 2004....
- M. Prensky, Computer games and learning: digital game-based learning, Handbook of Computer Game Studies,...
Serious games: serious opportunities
- et al.
An engine selection methodology for high fidelity serious games
- et al.
Game engines in scientific research
Commun. ACM
(2002) - et al.
The future of accelerator programming: abstraction, performance or can we have both?
- et al.
Delite: a compiler architecture for performance-oriented embedded domain-specific languages
ACM Transactions on Embedded Computing Systems (TECS)
(2014) Extreme Programming Explained: Embrace Change
(2000)- E. Collar Jr, R. Valerdi, Role of software readability on software development cost, Tech. rep., Western Connecticut...
Perspectives, frame rates and resolutions: it’s all in the game
The new product development game
Harvard Business Review
Interactive development: the new hell
Variety
Partial Evaluation for Optimized Compilation of Actor-oriented Models
High performance encapsulation in Casanova 2
Object, message, and performance: how they coexist in Self
Computer
A classification of scripting systems for entertainment and serious computer games
Bridging the gap between general-purpose and domain-specific compilers with synthesis
Searching for concurrent design patterns in video games
Cited by (2)
Automated video game parameter tuning with XVGDL+
2022, Journal of Universal Computer ScienceMetacasanova: An optimized meta-compiler for domain-specific languages
2017, SLE 2017 - Proceedings of the 10th ACM SIGPLAN International Conference on Software Language Engineering, co-located with SPLASH 2017