/* * Non-recursive version of object descend. this consumes more memory than recursive in-depth * traversal but prevents stack overflows on long chains of objects * or complex graphs (a max. recursion depth on my machine was ~5000 objects linked in a chain * so not too much). */ private static long MeasureObjectSize(object root) { // Objects seen so far. IdentityHashSet <object> seen = new IdentityHashSet <object>(); // Class cache with reference Field and precalculated shallow size. HashMap <Type, ClassCache> classCache = new HashMap <Type, ClassCache>(); // Stack of objects pending traversal. Recursion caused stack overflows. Stack <object> stack = new Stack <object>(); stack.Push(root); long totalSize = 0; while (stack.Count > 0) { object ob = stack.Pop(); if (ob == null || seen.Contains(ob)) { continue; } seen.Add(ob); Type obClazz = ob.GetType(); if (obClazz.IsArray) { /* * Consider an array, possibly of primitive types. Push any of its references to * the processing stack and accumulate this array's shallow size. */ long size = NUM_BYTES_ARRAY_HEADER; Array array = (Array)ob; int len = array.Length; if (len > 0) { Type componentClazz = obClazz.GetElementType(); if (componentClazz.IsPrimitive) { size += (long)len * PrimitiveSizes[componentClazz]; } else { size += (long)NUM_BYTES_OBJECT_REF * len; // Push refs for traversal later. for (int i = len; --i >= 0;) { object o = array.GetValue(i); if (o != null && !seen.Contains(o)) { stack.Push(o); } } } } totalSize += AlignObjectSize(size); } else { /* * Consider an object. Push any references it has to the processing stack * and accumulate this object's shallow size. */ try { ClassCache cachedInfo = classCache[obClazz]; if (cachedInfo == null) { classCache[obClazz] = cachedInfo = CreateCacheEntry(obClazz); } foreach (FieldInfo f in cachedInfo.ReferenceFields) { // Fast path to eliminate redundancies. object o = f.GetValue(ob); if (o != null && !seen.Contains(o)) { stack.Push(o); } } totalSize += cachedInfo.AlignedShallowInstanceSize; } catch (Exception e) { // this should never happen as we enabled setAccessible(). throw new Exception("Reflective field access failed?", e); } } } // Help the GC (?). seen.Clear(); stack.Clear(); classCache.Clear(); return(totalSize); }
/* * Non-recursive version of object descend. this consumes more memory than recursive in-depth * traversal but prevents stack overflows on long chains of objects * or complex graphs (a max. recursion depth on my machine was ~5000 objects linked in a chain * so not too much). */ private static long MeasureObjectSize(object root) { // Objects seen so far. IdentityHashSet <object> seen = new IdentityHashSet <object>(); // Class cache with reference Field and precalculated shallow size. IDictionary <Type, ClassCache> classCache = new JCG.Dictionary <Type, ClassCache>(IdentityEqualityComparer <Type> .Default); // Stack of objects pending traversal. Recursion caused stack overflows. Stack <object> stack = new Stack <object>(); stack.Push(root); long totalSize = 0; while (stack.Count > 0) { object ob = stack.Pop(); if (ob == null || seen.Contains(ob)) { continue; } seen.Add(ob); Type obClazz = ob.GetType(); // LUCENENET specific - .NET cannot return a null type for an object, so no need to assert it if (obClazz.Equals(typeof(string))) { // LUCENENET specific - we can get a closer estimate of a string // by using simple math. Reference: http://stackoverflow.com/a/8171099. // This fixes the TestSanity test. totalSize += (2 * (((string)ob).Length + 1)); } if (obClazz.IsArray) { /* * Consider an array, possibly of primitive types. Push any of its references to * the processing stack and accumulate this array's shallow size. */ long size = NUM_BYTES_ARRAY_HEADER; Array array = (Array)ob; int len = array.Length; if (len > 0) { Type componentClazz = obClazz.GetElementType(); if (componentClazz.IsPrimitive) { size += (long)len * primitiveSizes[componentClazz]; } else { size += (long)NUM_BYTES_OBJECT_REF * len; // Push refs for traversal later. for (int i = len; --i >= 0;) { object o = array.GetValue(i); if (o != null && !seen.Contains(o)) { stack.Push(o); } } } } totalSize += AlignObjectSize(size); } else { /* * Consider an object. Push any references it has to the processing stack * and accumulate this object's shallow size. */ try { if (!classCache.TryGetValue(obClazz, out ClassCache cachedInfo) || cachedInfo == null) { classCache[obClazz] = cachedInfo = CreateCacheEntry(obClazz); } foreach (FieldInfo f in cachedInfo.ReferenceFields) { // Fast path to eliminate redundancies. object o = f.GetValue(ob); if (o != null && !seen.Contains(o)) { stack.Push(o); } } totalSize += cachedInfo.AlignedShallowInstanceSize; } catch (Exception e) { // this should never happen as we enabled setAccessible(). throw new Exception("Reflective field access failed?", e); } } } // Help the GC (?). seen.Clear(); stack.Clear(); classCache.Clear(); return(totalSize); }
public void Resume(Object eventTarget) { if (GuiThreadHelper.IsInGuiThread()) { // Nothing to do return; } IEventTargetExtractor eventTargetExtractor = typeToEventTargetExtractorsDict.GetExtension(eventTarget.GetType()); if (eventTargetExtractor == null) { return; } eventTarget = eventTargetExtractor.ExtractEventTarget(eventTarget); if (eventTarget == null) { return; } IdentityLinkedSet <WaitForResumeItem> freeLatchMap = null; try { PausedEventTargetItem pauseETI; listenersWriteLock.Lock(); try { IdentityLinkedMap <Object, PausedEventTargetItem> pausedTargets = this.pausedTargets; pauseETI = pausedTargets.Get(eventTarget); if (pauseETI == null) { throw new System.Exception("No pause() active for target " + eventTarget); } pauseETI.PauseCount--; if (pauseETI.PauseCount > 0) { return; } pausedTargets.Remove(eventTarget); IList <Object> remainingPausedEventTargets = EvaluatePausedEventTargets(); IdentityHashSet <Object> remainingPausedEventTargetsSet = new IdentityHashSet <Object>(); Iterator <WaitForResumeItem> iter = waitForResumeSet.Iterator(); while (iter.MoveNext()) { WaitForResumeItem pauseItem = iter.Current; remainingPausedEventTargetsSet.AddAll(remainingPausedEventTargets); remainingPausedEventTargetsSet.RetainAll(pauseItem.PendingPauses); if (remainingPausedEventTargetsSet.Count == 0) { iter.Remove(); if (freeLatchMap == null) { freeLatchMap = new IdentityLinkedSet <WaitForResumeItem>(); } freeLatchMap.Add(pauseItem); } remainingPausedEventTargetsSet.Clear(); } } finally { listenersWriteLock.Unlock(); } } finally { if (freeLatchMap != null) { foreach (WaitForResumeItem wfrItem in freeLatchMap) { wfrItem.Latch.CountDown(); } foreach (WaitForResumeItem wfrItem in freeLatchMap) { try { wfrItem.ResultLatch.Await(); } catch (System.Exception e) { throw new System.Exception("Fatal state occured. This may result in a global deadlock", e); } } } } }