public void ThreadLock_SpeedTest() { UT_INIT(); Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/"); Log.MapThreadName("UnitTest"); Log.SetDomain("TestTLock", Scope.Method); ThreadLock aLock = new ThreadLock(); int repeats = 100000; int rrepeats = 5; Ticks stopwatch = new Ticks(); for (int r = 0; r < rrepeats; r++) { Log.Info("Run " + rrepeats); aLock.SetSafeness(Safeness.Unsafe); stopwatch.Set(); for (int i = 0; i < repeats; i++) { aLock.Acquire(); aLock.Release(); } long time = stopwatch.Age().InMillis(); Log.Info("Safe mode, " + repeats + " lock/unlock ops: " + time + " ms"); aLock.SetSafeness(Safeness.Safe); stopwatch.Set(); for (int i = 0; i < repeats; i++) { //aLock.acquire(); //aLock.release(); // in java, adding the following two loops, results in similar execution speed for (int tt = 0; tt < 70; tt++) { i += tt; } for (int tt = 0; tt < 70; tt++) { i -= tt; } } time = stopwatch.Age().InMillis(); Log.Info("Unsafe mode, " + repeats + " lock/unlock ops: " + time + " ms"); } }
void PerformanceTestRL() { // create a lox for release logging Lox lox = new Lox("ReleaseLox"); TextLogger relLogger = Lox.CreateConsoleLogger(); MemoryLogger ml = new MemoryLogger(); lox.SetVerbosity(relLogger, Verbosity.Verbose, "/CON"); lox.SetVerbosity(ml, Verbosity.Verbose, "/MEM"); lox.Info("/CON", "Logging simple info lines into a memory logger"); AString msgBuf = new AString( ); long fastest = long.MaxValue; Ticks timer = new Ticks(); int qtyLines = 1000; int qtyLoops = 2000; //1000 if (System.Diagnostics.Debugger.IsAttached) { qtyLines = qtyLoops = 10; } for (int i = 0; i < qtyLoops; i++) { #if ALOX_DBG_LOG || ALOX_REL_LOG ml.MemoryLog.Clear(); #endif timer.Set(); for (int ii = 0; ii < qtyLines; ii++) { lox.Info("/MEM", "Test Line"); if (i == 0 && ii == 0) { Console.WriteLine(ml.MemoryLog.ToString()); } } long t = timer.Age().Raw(); if (fastest > t) { fastest = t; lox.Info("/CON", msgBuf.Clear()._("Pass ")._(i, 3)._(" is new fastest: ") ._((int)(new Ticks(fastest)).InMicros(), 0) ._(" micros per ")._(qtyLines)._(" logs.")); } } double microsPerLog = ((double)(new Ticks(fastest)).InMicros()) / qtyLines; int logsPerSecond = (int)(1000000.0 / microsPerLog); lox.Info("/CON", msgBuf._()._(" ")._(ESC.MAGENTA)._("Fastest Release Logging: ") ._(microsPerLog)._(" micros per log (resp ") ._(logsPerSecond)._(" logs per second) ")); lox.RemoveLogger(ml); lox.RemoveLogger(relLogger); }
public void SpeedTest() { UT_INIT(); Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/"); Log.MapThreadName("UnitTest"); Log.SetDomain("TickWatch", Scope.Method); Log.Info("\n### TicksSpeedTest ###"); for (int runs = 0; runs < 5; runs++) { int aLotOf = 100; Ticks t = new Ticks(); Ticks tkMeasure = new Ticks(); for (int i = 0; i < aLotOf; i++) { t.Set(); } long nanos = tkMeasure.Age().InNanos(); long averageNanos = nanos / aLotOf; Log.Info("Doing " + aLotOf + " Ticks.Set() calls took " + nanos + " ns. This is an average of " + averageNanos + " nanoseconds per call"); UT_TRUE(averageNanos < 20000); // this is much slower on Windows than on mono/linux. } }
// ############################################################################################# // Interface // ############################################################################################# /** ******************************************************************************************** * Thread which invokes this method gets registered as the current owner of this object, until the * same thread releases the ownership invoking Release(). * In the case that this object is already owned by another thread, the invoking thread is suspended * until ownership can be gained. * Multiple (nested) calls to this method are counted and the object is only released when the same * number of Release() calls have been made. * * @param cln (Optional) Caller info, compiler generated. Please omit. * @param csf (Optional) Caller info, compiler generated. Please omit. * @param cmn (Optional) Caller info, compiler generated. Please omit. **********************************************************************************************/ public void Acquire( [CallerLineNumber] int cln = 0, [CallerFilePath] String csf = "", [CallerMemberName] String cmn = "") { // are we in unsafe mode? if (mutex == null) { // we are still increasing the lockCount lockCount = lockMode == LockMode.Recursive ? lockCount + 1 : 1; // reached warning limit if (lockCount <= 0) { ALIB.ERROR("Unsafe mode: Counter invalid (<= 0): This should never happen. Set lock to safe mode!"); } else if (lockCount % RecursionWarningThreshold == 0) { ALIB.WARNING("Recursion depth " + lockCount + ". To prevent this, change ThreadSafe.recursionWarningThreshold or fix your code!"); } // end of unsafe version of this method return; } // get current thread Thread thisThread = Thread.CurrentThread; // synchronize on mutex lock ( mutex ) { // we already own the thread if (owner == thisThread) { // we are still increasing the lockCount lockCount = lockMode == LockMode.Recursive ? lockCount + 1 : 1; // reached warning limit if (lockCount % RecursionWarningThreshold == 0) { ALIB.WARNING("Recursion depth " + lockCount + ". To prevent this, change ThreadSafe.recursionWarningThreshold or fix your code!"); } return; } // we do not own this thread, wait until lock is free bool hasWarned = false; while (owner != null) { try { // wait unconditional if (waitWarningTimeLimitInMillis <= 0 || hasWarned) { Monitor.Wait(mutex); } // wait with time limit else { waitTime.Set(); Monitor.Wait(mutex, waitWarningTimeLimitInMillis); long time = waitTime.Age().InMillis(); if (time >= waitWarningTimeLimitInMillis) { hasWarned = true; ALIB.WARNING("Timeout (" + waitWarningTimeLimitInMillis + " ms). Change your codes critical section length if possible." + CString.NewLineChars + "This thread: " + thisThread.ManagedThreadId + "/" + thisThread.Name + CString.NewLineChars + "Owning thread: " + (owner != null ? (owner.ManagedThreadId + "/" + owner.Name) : "null") #if DEBUG + CString.NewLineChars + "Location of acquirement: " + acquirementSourcefile + ":" + acquirementLineNumber + " " + acquirementMethodName + "()" #endif ); } } } catch (Exception) {} // ignore spurious wakeups } // take control owner = thisThread; #if DEBUG acquirementLineNumber = cln; acquirementSourcefile = csf; acquirementMethodName = cmn; #endif lockCount = 1; } // synchronized }