Closed ldilley closed 3 years ago
Sphere is a server based on ticks, this is the "main timer" to control all timer-based actions, like skill delay, actions, timers, etc, so it is expected that it should call clock_gettime() at each tick, which is something really fast
But this is a lightweight function and should not affect server performance, so indeed there's something wrong. Probably the error is not on clock_gettime(), but on something near it
Just to make sure, try compile the build using GCC instead CLang to check if it works fine, maybe this is a compiler-related issue
Thank you for the response, @coruja747.
I understand regarding the ticks. After some more experimentation, FreeBSD's implementation of clock_gettime()
with CLOCK_MONOTONIC
seems to be responsible for causing the performance issues. I recompiled spheresvr
with gcc 9.3.0 under FreeBSD and the same symptoms occurred. I am not able to replicate the symptoms under Linux (Debian 10.9).
As I mentioned previously, if I comment the call to clock_gettime()
, then performance is great (this is how I determined the root cause). If I also modify the clock ID to be CLOCK_MONOTONIC_FAST
(which is a FreeBSD extension), then performance becomes acceptable. An excerpt from golang/go#22942:
CLOCK_MONOTONIC_FAST will use getnanouptime, while CLOCK_MONOTONIC will use nanouptime
https://github.com/freebsd/freebsd/blob/release/11.1.0/sys/kern/kern_time.c#L345.
Functions with the "get" prefix returns a less precise result
much faster than the functions without "get" prefix and should
be used where a precision of 1/hz seconds is acceptable or where
performance is priority. (NB: "precision", not "resolution" !)
If this minor loss of precision is acceptable to you at the gain of running normally under FreeBSD while still using a monotonic clock, I can submit a PR to remedy the issue.
That's nice, thanks for the PR! Honestly I don't have FreeBSD here so I can't test it, but if it works for you I'll assume everything is ok
But by default sphere is compiled with Visual Studio on Windows and GCC on unix/linux, so to keep the code portable, we must compile it using GCC instead CLang to make sure all builds will have the same compiled code. Of course you can still using CLang on your local/custom build, but on main branch (nightly builds) it's recommended use GCC instead CLang
Anyway, try update your files to latest commit https://github.com/Sphereserver/Source/commit/0d2c1bef214706556d188e144e3ac4b8aac8c5fe, I did some changes to improve FreeBSD support and also merged PR changes, if something still missing feel free to update it
Fix merged in e01bb6f.
I've successfully built
spheresvr
0.56d (latest master commit e01bb6f) under FreeBSD 12.2 using Clang 10.0.1. However, after executingspheresvr
, there is a significant degradation of response time within thespheresvr
console for input/output, scripts are parsed slower than they should be, and client connections are delayed.After some investigation, CPU utilization is significantly elevated per the output below. The CPU utilization remains high for the runtime of the program.
Upon further inspection, it appears that the program is stuck in a loop calling
clock_gettime()
at a very high frequency per the output below. I've tracked this particular call to line 10 ofsrc/common/CTime.cpp
(clock_gettime(CLOCK_MONOTONIC, &ts);
). If the aforementioned line is commented,spheresvr
is rebuilt, and the program is executed again, the CPU utilization returns to much more acceptable levels. I am hoping for a fix while maintaining the call toclock_gettime()
if it is essential.