The Swiss Ephemeris(SE) is the standard library for astronomical calculations in astrological software. The SE is written in Ansi C and is easy to use by programs written in C or C++. For software in other languages, a dll is available but this of course is only usable in a Windows environment.
My intention is to rewrite the core of Enigma in Go and the user interface in Flutter/Dart. This means that I need to access the SE using code in Go. Three options are available:
- rewriting the SE in Go. This would be an enormous task.
- using the DLL. This would restrict the usage of Enigma to a Windows environment and I want to move to a cross-platform application.
- accessing the C-code of the SE via a FFI (Foreign Function Interface) solution. Fortunately, such a solution exists for Go. It’s called cgo.
Using cgo, I can use the original c-code in my application and call C-functions from Go. This approach does require converting Go-variables into their C counterparts and it has some limitations on constructions with pointers. And there is a performance penalty: the conversion takes time and calling a C-function from Go is much slower than calling a C-function from C.
How does this work out in practice? I can already tell you that you would not be able to see any difference for a chart-calculation. But it could be an issue if a large sequence of calculations is required, e.g. for cycles.
I wanted to be sure about this, so I built a small wrapper for the SE, using cgo. The wrapper supports two functions: initializing the SE and calculating the position of a celestial body. I used code from the existing Go wrapper by Kaveh Shahbazian (https://github.com/workshop-depot/gosweph ) but needed to make some changes. I used this wrapper in a small program that calculates the position of Sun, Moon and Mercury for 1,000,000 consecutive days. I also wrote a program with the same functionality in C#, using the standard dll from the SE. The following table shows the time these calculations took, measured in milliseconds.
Calculation for | Milliseconds when using Go and cgo | Milliseconds when using C# and the SE dll |
---|---|---|
Sun | 10,351 | 8,935 |
Moon | 10,402 | 8,784 |
Mercury | 11,450 | 9,623 |
The results show clearly that the combination of C# and the SE dll is faster but the differences are pretty small, a bit over 15%. In both cases we are talking about roughly 100,000 calculations per second. My conclusion: there is a small performance penalty when accessing the SE with Go but it is negligible.
I performed the tests on a PC with Windows 11, an AMD Ryzen 9 processor and 32 GB internal memory.