Tuesday, December 6, 2016

Go in Server Development

Introduction

Conquer Online server development usually consists of large projects and complex server designs; and unfortunately, choosing a best-fit programming language isn't always straightforward with projects of this scale. All programming languages come with their advantages and disadvantages, and Go is no exception to this. In this article, I talk about my decision to use Go for Chimera and how Go had the least disadvantages in comparison to other languages.

What is the purpose of Go?

In case you're not aware - Google first developed Go to help replace aging C++ systems which were becoming more difficult to maintain and compile in a timely manor. Go was designed by engineers whom were frustrated with the features and environments of existing languages. When analyzing languages such as C# or C++, you find a lot of commonalities between the languages - frequently adding new syntactical features which converge the languages and generalize their uses. This comes at a huge complexity cost, and raises the difficulty for new programmers and experienced programmers maintaining complex software. Go was created to break away from the complexity of today's languages, not to overtake other languages and solve every problem, but to solve more specific problems such as threading, parallel computation, and networking. With a type system with no hierarchy, a structured package system with no conflicting feature sets, a software model with easy dependency analysis, and a clean and simple syntax, Go is a well designed language that shows promise.

Development Environment

One important problem Go solves is with its environment. Go is cross-platform and can compile for every (and from any) system and architecture. This means programming environments are irrelevant: Windows x64 can compile for Linux ARM. You don't need to worry about configuring build systems, setting up development environments, working against system restrictions or with system specific libraries, etc. As long as you have the compiler, you can compile with a simple "go install" command.

This is the same idea for Go's runtime environment. Go is a managed language with a full garbage collector, routine scheduler, etc; however, this managed runtime is statically built into executables in under 3MB. That means no redistributable packages or external runtime environments that need to be installed, such as in the case of QT, VC++, Python, or .NET. It compiles within seconds and runs natively for any targeted OS and architecture.

Chimera benefits from this light environment, as it can build libraries and executables for any system. It means the code is easier to setup and test, and easier to develop with across any system and with any Go developer. If Chimera was a company, this would mean less cost in training new developers, maintaining existing systems in Go, and less need for specialized systems for compiling code. If you're not familiar with large technology companies, these costs can easily be in the millions per year. Reducing these costs is of extreme benefit; but for Chimera, it's simply an added bonus for developers.

Development Reasons

Go specializes in parallel programming across networked systems. Chimera is a distributed system of servers which encapsulate the game world. Having a simple and managed infrastructure for connecting the map servers together was a large benefit, and meant saving months of development time in comparison to my C and C++ project variants. Not having to define a thread pool, database connection pool, etc. was extremely helpful. 

Go's package system also meant less time in development when writing ciphers and security routines, as Go comes with great cryptography and hashing support. In fact, the strength of their package system is that it is functionally complete - meaning no additional features will be added. This might be seen as a disadvantage, but my server design fits perfectly into their philosophy. With no additional features clouding development, there is always only one package for getting a task done in Go. This means that improvements to your application are normally delivered with the language rather than through refactoring. It means that you can be confident that your code is the best it can be for the language. Go also comes with a backwards compatibility guarantee - that your code will never break in language updates (or will be converted to work). 

Libraries in Go are also available through the open source community and delivered using Go's pre-defined interfaces. For example, to include a MySQL driver which defines syntax for Go's SQL connection scheduler, I include the official open source driver from github: "import github.com/go-sql-driver/mysql". This means Chimera no longer has to maintain external libraries which break across versions of VC++ and Visual Studio (for example with the C++ project). It just works and remains out-of-mind.

Technical Advantages

In addition to the advantages I listed above, Go is a very strong language for garbage collection and parallel computation. This helps eliminate my worries over multi-core execution. As mentioned before, Chimera doesn't focus on threading models or a thread pool any longer; rather, it depends on channels, Go routines, and Go's routine scheduler. Go routines are green threads which are scheduled by Go's statically compiled runtime. In recent tests, I was able to create a million of scheduled routines spin looping on a Raspberry Pi. It is incredible that the scheduler was able to not only avoid thrashing, but maintained a stable workload. Also, by relying on Go routines, I receive performance improvements with language updates.

I found in other tests that Chimera performed very well over the network. Pre-packaged functionality such as RPC and TCP delivered with the language were surprisingly well-written. When comparing networking routines with my C# variant, Go grossly out-performed C# but also was not susceptible to certain flooded attacks which I found crashed quite a few industry C# applications on local and remote systems.

Conclusion

By design, Go is more reliable, better on performance, and easily portable for a game server project such as Chimera. Go solves concurrent execution and communication specifications in Chimera with ease. It allows Chimera to scale quickly and keep a simple software model with less overhead and great performance. It also gives me the expansibility of a managed language with the feel of C. Though Go cannot be used to solve every problem, it is a great step in the right direction for network and parallel programming. And at the end of the day, it is my preference for maintaining a large distributed systems project such as Chimera.