static Config() { try { if (!MiNetServer.IsRunningOnMono()) //Fix issue on linux/mono. { var assembly = Assembly.GetExecutingAssembly().GetName().CodeBase; var path = new Uri(Path.GetDirectoryName(assembly)).LocalPath; var configFilePath = Path.Combine(path, ConfigFileName); if (File.Exists(configFilePath)) { FileContents = File.ReadAllText(configFilePath); } } else { if (File.Exists(ConfigFileName)) { FileContents = File.ReadAllText(ConfigFileName); } } } catch (Exception e) { Log.Warn("Error configuring parser", e); } }
static Config() { try { string username = Environment.UserName; string fileContents = string.Empty; if (!MiNetServer.IsRunningOnMono()) //Fix issue on linux/mono. { var assembly = Assembly.GetExecutingAssembly().GetName().CodeBase; string rawPath = Path.GetDirectoryName(assembly); if (rawPath != null) { var path = new Uri(rawPath).LocalPath; var configFilePath = Path.Combine(path, $"server.{username}.conf"); Log.Info($"Trying to load config-file {configFilePath}"); if (File.Exists(configFilePath)) { fileContents = File.ReadAllText(configFilePath); } else { configFilePath = Path.Combine(path, ConfigFileName); Log.Info($"Trying to load config-file {configFilePath}"); if (File.Exists(configFilePath)) { fileContents = File.ReadAllText(configFilePath); } } Log.Info($"Loading config-file {configFilePath}"); } } else { if (File.Exists(ConfigFileName)) { fileContents = File.ReadAllText(ConfigFileName); } } LoadValues(fileContents); } catch (Exception e) { Log.Warn("Error configuring parser", e); } }
public HighPrecisionTimer(int interval, Action <object> action, bool useSignaling = false, bool skipTicks = true) { // The following is dangerous code. It will increase windows timer frequence to interrupt // every 1ms instead of default 15ms. It is the same tech that games use to increase FPS and // media decoders to increase precision of movies (chrome does this). // We use this here to increase the precision of our thread scheduling, since this will have a big // impact on overall performance of the server. DO note that changing this is a global setting in // Windows and will affect every running process. It will automatically disable itself and reset // to default after closing the process. // It will have a major impact bettery and energy consumption in general. So don't go tell GreenPeace about // this, thanks. // // HERE BE DRAGONS! if (!MiNetServer.IsRunningOnMono()) { WinApi.TimeBeginPeriod(1); } // END IS HERE. SAFE AGAIN ... Avarage = interval; Action = action; if (interval < 1) { throw new ArgumentOutOfRangeException(); } CancelSource = new CancellationTokenSource(); var watch = Stopwatch.StartNew(); long nextStop = interval; var task = new Task(() => { Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; while (!CancelSource.IsCancellationRequested) { long msLeft = nextStop - watch.ElapsedMilliseconds; if (msLeft <= 0) { if (msLeft < -1) { Misses++; } //if (!skipTicks && msLeft < -4) Log.Warn($"We are {msLeft}ms late for action execution"); long execTime = watch.ElapsedMilliseconds; Action(this); AutoReset.Reset(); execTime = watch.ElapsedMilliseconds - execTime; Avarage = (Avarage * 9 + execTime) / 10L; if (skipTicks) { // Calculate when the next stop is. If we're too slow on the trigger then we'll skip ticks nextStop = (long)(interval * (Math.Floor(watch.ElapsedMilliseconds / (float)interval /*+ 1f*/) + 1)); } else { long calculatedNextStop = (long)(interval * (Math.Floor(watch.ElapsedMilliseconds / (float)interval /*+ 1f*/) + 1)); nextStop += interval; // Calculate when the next stop is. If we're very behind on ticks then we'll skip ticks if (calculatedNextStop - nextStop > 2 * interval) { //Log.Warn($"Skipping ticks because behind {calculatedNextStop - nextStop}ms. Too much"); nextStop = calculatedNextStop; } } // If we can't keep up on execution time, we start skipping ticks until we catch up again. if (Avarage > interval) { nextStop += interval; } continue; } if (msLeft < 5) { Spins++; if (useSignaling) { AutoReset.WaitOne(50); } var stop = nextStop; if (watch.ElapsedMilliseconds < stop) { SpinWait.SpinUntil(() => watch.ElapsedMilliseconds >= stop); } continue; } if (msLeft < 16) { if (Thread.Yield()) { Yields++; continue; } Sleeps++; Thread.Sleep(1); if (!skipTicks) { long t = nextStop - watch.ElapsedMilliseconds; if (t < -5) { Log.Warn($"We overslept {t}ms in thread yield/sleep"); } } continue; } Sleeps++; Thread.Sleep(Math.Max(1, (int)(msLeft - 16))); if (!skipTicks) { long t = nextStop - watch.ElapsedMilliseconds; if (t < -5) { Log.Warn($"We overslept {t}ms in thread sleep"); } } } CancelSource.Dispose(); CancelSource = null; AutoReset.Dispose(); AutoReset = null; }, CancelSource.Token, TaskCreationOptions.LongRunning); task.Start(); }