public void TestMethod4() { ITracer tracer = new StackTracer(); var thread1 = new Thread(StartSlowMethods); thread1.Start(tracer); StartSuperFastMethods(tracer); StartFastMethods(tracer); StartSuperSlowMethods(tracer); thread1.Join(); var traceResult = tracer.GetTraceResult(); int methodsAtAll = 0; foreach (var thread in traceResult.threads) { foreach (var method in thread.methods) { methodsAtAll += 1 + countNestedMethods(method); } } Assert.AreEqual(6, methodsAtAll, string.Format("Expected {0} methods at all, instead got {1}", 6, methodsAtAll)); }
public IEnumerable <object> FetchParameters() { var st = new StackTracer(Source.Body, 1000); BadInstructions = st.TraceCall(Call).ToList(); return(st.Stack.Select(entry => entry.Value.OptimizeValue())); }
public void TestMethod1() { ITracer tracer = new StackTracer(); var slow = new SlowClass(tracer); slow.SuperSlow(); var traceResult = tracer.GetTraceResult(); Assert.IsNotNull(traceResult); Assert.AreEqual(1, traceResult.threads.Count, string.Format("Expected {0} threads, instead got {1}", 1, traceResult.threads.Count)); }
public void TestMethod3() { ITracer tracer = new StackTracer(); StartFastMethods(tracer); StartSuperSlowMethods(tracer); StartFastMethods(tracer); StartSuperSlowMethods(tracer); var traceResult = tracer.GetTraceResult(); Assert.AreEqual(4, traceResult.threads[0].methods.Count, string.Format("Expected {0} root methods in main thread, instead got {1}", 4, traceResult.threads[0].methods.Count)); }
public void TestMethod2() { ITracer tracer = new StackTracer(); var thread = new Thread(StartFastMethods); thread.Start(tracer); StartSuperSlowMethods(tracer); thread.Join(); var traceResult = tracer.GetTraceResult(); Assert.AreEqual(2, traceResult.threads.Count, string.Format("Expected {0} threads, instead got {1}", 2, traceResult.threads.Count)); }
public Spark(dynamic model) { _callingMethod = StackTracer.GetPreviousMethodName(GetType().GetConstructors().Where(ci => ci.GetParameters().Count() == 1).First()); _model = model; }
public Spark() { _callingMethod = StackTracer.GetPreviousMethodName(GetType().GetConstructor(Type.EmptyTypes)); }
private SpokeObject evaluateMethod(SpokeMethod fm, SpokeObject[] paras) { SpokeObject[] variables; #if stacktrace dfss.AppendLine( fm.Class.Name +" : : "+fm.MethodName+" Start"); #endif SpokeObject lastStack; int stackIndex = 0; SpokeObject[] stack = new SpokeObject[3000]; int index = 0; StackTracer st; if (reprintStackIndex == -1) { variables = new SpokeObject[fm.NumOfVars]; for (int i = 0; i < fm.Parameters.Length; i++) { variables[i] = paras[i]; } stackTrace.Add(st = new StackTracer(stack, variables)); } else { StackTracer rp = reprintStackTrace[stackTrace.Count]; stack = rp.StackObjects; variables = rp.StackVariables; index = rp.InstructionIndex; stackIndex = rp.StackIndex; stackTrace.Add(st = new StackTracer(stack, variables)); if (stackTrace.Count == reprintStackIndex) { stack[stackIndex++] = rp.Answer; reprintStackIndex = -1; reprintStackTrace = null; } } for (; index < fm.Instructions.Length; index++) { var ins = fm.Instructions[index]; #if stacktrace dfss.AppendLine(stackIndex + " :: " + ins.ToString()); #endif // var fs = new fixStackTracer(stackTrace.ToArray()); // stackTrace = new List<StackTracer>(fs.Start(true)); SpokeObject[] sps; SpokeObject bm; switch (ins.Type) { case SpokeInstructionType.CreateReference: stack[stackIndex++] = new SpokeObject(new SpokeObject[ins.Index], ins.StringVal); break; case SpokeInstructionType.CreateArray: stack[stackIndex++] = new SpokeObject(new List<SpokeObject>(20)); break; case SpokeInstructionType.CreateMethod: stack[stackIndex++] = NULL;//new SpokeObject(ObjectType.Method) { AnonMethod = ins.anonMethod }; break; case SpokeInstructionType.Label: // throw new NotImplementedException(""); break; case SpokeInstructionType.Goto: index = ins.Index; break; case SpokeInstructionType.Comment: break; case SpokeInstructionType.CallMethod: st.InstructionIndex = index; st.StackIndex = stackIndex; sps = new SpokeObject[ins.Index3]; for (int i = ins.Index3 - 1; i >= 0; i--) { sps[i] = stack[--stackIndex]; } stack[stackIndex++] = evaluateMethod(Methods[ins.Index], sps); break; case SpokeInstructionType.CallMethodFunc: st.InstructionIndex = index; st.StackIndex = stackIndex; sps = new SpokeObject[ins.Index3]; for (int i = ins.Index3 - 1; i >= 0; i--) { sps[i] = stack[--stackIndex]; } stack[stackIndex++] = Methods[ins.Index].MethodFunc(sps); break; case SpokeInstructionType.CallInternal: sps = new SpokeObject[ins.Index3]; for (int i = ins.Index3 - 1; i >= 0; i--) { sps[i] = stack[--stackIndex]; } st.InstructionIndex = index + 1; st.StackIndex = stackIndex; SpokeObject l = InternalMethods[ins.Index](sps); if (ins.Index == 16) { GameBoard d = buildBoard(sps[4]); throw new AskQuestionException(stackTrace, new SpokeQuestion(sps[1].Variables[0].StringVal, sps[2].StringVal, sps[3].ArrayItems.Select(a => a.StringVal).ToArray()), d); } else { stack[stackIndex++] = l; } break; case SpokeInstructionType.BreakpointInstruction: Console.WriteLine("BreakPoint"); break; case SpokeInstructionType.Return: #if stacktrace dfss.AppendLine(fm.Class.Name + " : : " + fm.MethodName + " End"); #endif stackTrace.Remove(st); return stack[--stackIndex]; break; case SpokeInstructionType.IfTrueContinueElse: if (stack[--stackIndex].BoolVal) continue; index = ins.Index; break; case SpokeInstructionType.Or: stack[stackIndex - 2] = (stack[stackIndex - 2].BoolVal || stack[stackIndex - 1].BoolVal) ? TRUE : FALSE; stackIndex--; break; case SpokeInstructionType.And: stack[stackIndex - 2] = (stack[stackIndex - 2].BoolVal && stack[stackIndex - 1].BoolVal) ? TRUE : FALSE; stackIndex--; break; case SpokeInstructionType.StoreLocalInt: lastStack = stack[--stackIndex]; bm = variables[ins.Index]; variables[ins.Index] = new SpokeObject(ObjectType.Int) { IntVal = lastStack.IntVal }; break; case SpokeInstructionType.StoreLocalFloat: lastStack = stack[--stackIndex]; bm = variables[ins.Index]; variables[ins.Index] = new SpokeObject(ObjectType.Float) { FloatVal = lastStack.FloatVal }; break; case SpokeInstructionType.StoreLocalBool: lastStack = stack[--stackIndex]; bm = variables[ins.Index]; variables[ins.Index] = lastStack.BoolVal ? TRUE : FALSE; break; case SpokeInstructionType.StoreLocalString: lastStack = stack[--stackIndex]; bm = variables[ins.Index]; variables[ins.Index] = new SpokeObject(ObjectType.String) { StringVal = lastStack.StringVal }; break; case SpokeInstructionType.StoreLocalMethod: case SpokeInstructionType.StoreLocalObject: lastStack = stack[--stackIndex]; variables[ins.Index] = lastStack; break; case SpokeInstructionType.StoreLocalRef: lastStack = stack[--stackIndex]; bm = variables[ins.Index]; bm.ClassName = lastStack.ClassName; bm.Type = lastStack.Type; //bm.Variables = lastStack.Variables; //bm.ArrayItems = lastStack.ArrayItems; bm.StringVal = lastStack.StringVal; bm.IntVal = lastStack.IntVal; bm.BoolVal = lastStack.BoolVal; bm.FloatVal = lastStack.FloatVal; break; case SpokeInstructionType.StoreFieldBool: lastStack = stack[--stackIndex]; lastStack.Variables[ins.Index] = stack[--stackIndex].BoolVal ? TRUE : FALSE; break; case SpokeInstructionType.StoreFieldInt: lastStack = stack[--stackIndex]; lastStack.Variables[ins.Index] = new SpokeObject(ObjectType.Int) { IntVal = stack[--stackIndex].IntVal }; break; case SpokeInstructionType.StoreFieldFloat: lastStack = stack[--stackIndex]; lastStack.Variables[ins.Index] = new SpokeObject(ObjectType.Float) { FloatVal = stack[--stackIndex].FloatVal }; break; case SpokeInstructionType.StoreFieldString: lastStack = stack[--stackIndex]; lastStack.Variables[ins.Index] = new SpokeObject(ObjectType.String) { StringVal = stack[--stackIndex].StringVal }; break; case SpokeInstructionType.StoreFieldMethod: case SpokeInstructionType.StoreFieldObject: lastStack = stack[--stackIndex]; lastStack.Variables[ins.Index] = stack[--stackIndex]; break; case SpokeInstructionType.IfEqualsContinueAndPopElseGoto: if (SpokeObject.Compare(stack[stackIndex - 2], stack[stackIndex - 1])) { stackIndex = stackIndex - 2; continue; } stackIndex = stackIndex - 1; index = ins.Index; break; case SpokeInstructionType.StoreToReference: lastStack = stack[--stackIndex]; stack[stackIndex - 1].Variables[ins.Index] = lastStack; break; case SpokeInstructionType.GetField: stack[stackIndex - 1] = stack[stackIndex - 1].Variables[ins.Index]; break; case SpokeInstructionType.GetLocal: stack[stackIndex++] = variables[ins.Index]; break; case SpokeInstructionType.PopStack: stackIndex--; break; case SpokeInstructionType.Not: stack[stackIndex - 1] = stack[stackIndex - 1].BoolVal ? FALSE : TRUE; break; case SpokeInstructionType.AddStringInt: stack[stackIndex - 2] = new SpokeObject(ObjectType.String) { StringVal = stack[stackIndex - 2].StringVal + stack[stackIndex - 1].IntVal }; stackIndex--; break; case SpokeInstructionType.AddIntString: stack[stackIndex - 2] = new SpokeObject(ObjectType.String) { StringVal = stack[stackIndex - 2].IntVal + stack[stackIndex - 1].StringVal }; stackIndex--; break; case SpokeInstructionType.IntConstant: stack[stackIndex++] = intCache(ins.Index); break; case SpokeInstructionType.BoolConstant: stack[stackIndex++] = ins.BoolVal ? TRUE : FALSE; break; case SpokeInstructionType.FloatConstant: stack[stackIndex++] = new SpokeObject(ObjectType.Float) { FloatVal = ins.FloatVal }; break; case SpokeInstructionType.StringConstant: stack[stackIndex++] = new SpokeObject(ObjectType.String) { StringVal = ins.StringVal }; break; case SpokeInstructionType.Null: stack[stackIndex++] = NULL; break; case SpokeInstructionType.AddIntInt: stack[stackIndex - 2] = intCache(stack[stackIndex - 2].IntVal + stack[stackIndex - 1].IntVal); stackIndex--; break; case SpokeInstructionType.AddIntFloat: break; case SpokeInstructionType.AddFloatInt: break; case SpokeInstructionType.AddFloatFloat: break; case SpokeInstructionType.AddFloatString: stack[stackIndex - 2] = new SpokeObject(ObjectType.String) { StringVal = stack[stackIndex - 2].FloatVal + stack[stackIndex - 1].StringVal }; stackIndex--; break; case SpokeInstructionType.AddStringFloat: stack[stackIndex - 2] = new SpokeObject(ObjectType.String) { StringVal = stack[stackIndex - 2].StringVal + stack[stackIndex - 1].FloatVal }; stackIndex--; break; case SpokeInstructionType.AddStringString: stack[stackIndex - 2] = new SpokeObject(ObjectType.String) { StringVal = stack[stackIndex - 2].StringVal + stack[stackIndex - 1].StringVal }; stackIndex--; break; case SpokeInstructionType.SubtractIntInt: stack[stackIndex - 2] = intCache(stack[stackIndex - 2].IntVal - stack[stackIndex - 1].IntVal); stackIndex--; break; case SpokeInstructionType.SubtractIntFloat: break; case SpokeInstructionType.SubtractFloatInt: break; case SpokeInstructionType.SubtractFloatFloat: break; case SpokeInstructionType.MultiplyIntInt: stack[stackIndex - 2] = intCache(stack[stackIndex - 2].IntVal * stack[stackIndex - 1].IntVal); stackIndex--; break; case SpokeInstructionType.MultiplyIntFloat: break; case SpokeInstructionType.MultiplyFloatInt: break; case SpokeInstructionType.MultiplyFloatFloat: break; case SpokeInstructionType.DivideIntInt: stack[stackIndex - 2] = intCache(stack[stackIndex - 2].IntVal / stack[stackIndex - 1].IntVal); stackIndex--; break; case SpokeInstructionType.DivideIntFloat: break; case SpokeInstructionType.DivideFloatInt: break; case SpokeInstructionType.DivideFloatFloat: break; case SpokeInstructionType.GreaterIntInt: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal > stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterIntFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal > stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterFloatInt: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal > stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterFloatFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal > stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessIntInt: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal < stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessIntFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal < stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessFloatInt: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal < stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessFloatFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal < stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterEqualIntInt: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal >= stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterEqualIntFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal >= stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterEqualFloatInt: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal >= stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.GreaterEqualFloatFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal >= stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessEqualIntInt: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal <= stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessEqualIntFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].IntVal <= stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessEqualFloatInt: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal <= stack[stackIndex - 1].IntVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.LessEqualFloatFloat: stack[stackIndex - 2] = (stack[stackIndex - 2].FloatVal <= stack[stackIndex - 1].FloatVal) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.Equal: stack[stackIndex - 2] = SpokeObject.Compare(stack[stackIndex - 2], stack[stackIndex - 1]) ? TRUE : FALSE; stackIndex = stackIndex - 1; break; case SpokeInstructionType.InsertToArray: break; case SpokeInstructionType.RemoveToArray: break; case SpokeInstructionType.AddToArray: lastStack = stack[--stackIndex]; stack[stackIndex - 1].AddArray(lastStack); break; case SpokeInstructionType.AddRangeToArray: lastStack = stack[--stackIndex]; stack[stackIndex - 1].AddRangeArray(lastStack); break; case SpokeInstructionType.LengthOfArray: break; case SpokeInstructionType.ArrayElem: lastStack = stack[--stackIndex]; stack[stackIndex - 1] = stack[stackIndex - 1].ArrayItems[lastStack.IntVal]; break; case SpokeInstructionType.StoreArrayElem: var indexs = stack[--stackIndex]; var ars = stack[--stackIndex]; ars.ArrayItems[indexs.IntVal] = stack[--stackIndex]; break; default: throw new ArgumentOutOfRangeException(); } } #if stacktrace dfss.AppendLine(fm.Class.Name + " : : " + fm.MethodName + " End"); #endif stackTrace.Remove(st); return null; }
public static int Run(string[] args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { EnsureProperDebugDllsAreLoadedForWindows(); } _app = new CommandLineApplication { Name = "Raven.Debug", Description = "Debugging tool from RavenDB" }; _app.HelpOption(HelpOptionString); _app.Command("stack-traces", cmd => { cmd.ExtendedHelpText = cmd.Description = "Prints stack traces for the given process."; cmd.HelpOption(HelpOptionString); var waitOption = cmd.Option("--wait", "Wait for user input", CommandOptionType.NoValue); var pidOption = cmd.Option("--pid", "Process ID to which the tool will attach to", CommandOptionType.SingleValue); var attachTimeoutOption = cmd.Option("--timeout", "Attaching to process timeout in milliseconds. Default 15000", CommandOptionType.SingleValue); var outputOption = cmd.Option("--output", "Output file path", CommandOptionType.SingleValue); var threadIdsOption = cmd.Option("--tid", "Thread ID to get the info about", CommandOptionType.MultipleValue); var includeStackObjectsOption = cmd.Option("--includeStackObjects", "Include the stack objects", CommandOptionType.NoValue); cmd.OnExecute(() => { if (waitOption.HasValue()) { Console.ReadLine(); // wait for the caller to finish preparing for us } if (pidOption.HasValue() == false) { return(cmd.ExitWithError("Missing --pid option.")); } if (int.TryParse(pidOption.Value(), out var pid) == false) { return(cmd.ExitWithError($"Could not parse --pid with value '{pidOption.Value()}' to number.")); } HashSet <uint> threadIds = null; if (threadIdsOption.HasValue()) { foreach (var tid in threadIdsOption.Values) { if (uint.TryParse(tid, out var tidAsInt) == false) { return(cmd.ExitWithError($"Could not parse --tid with value '{tid}' to number.")); } if (threadIds == null) { threadIds = new HashSet <uint>(); } threadIds.Add(tidAsInt); } } uint attachTimeout = 15000; if (attachTimeoutOption.HasValue() && uint.TryParse(attachTimeoutOption.Value(), out attachTimeout) == false) { return(cmd.ExitWithError($"Could not parse --attachTimeout with value '{attachTimeoutOption.Value()}' to number.")); } string output = null; if (outputOption.HasValue()) { output = outputOption.Value(); } var includeStackObjects = includeStackObjectsOption.Values.FirstOrDefault() == "on"; try { StackTracer.ShowStackTrace(pid, attachTimeout, output, cmd, threadIds, includeStackObjects); return(0); } catch (Exception e) { string desc; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) == false) { desc = ""; } else { desc = $"Make sure to run enable-debugging.sh script as root from the main RavenDB directory."; } return(cmd.ExitWithError($"Failed to show the stacktrace. {desc}Error: {e}")); } }); }); _app.Command("dump", cmd => { cmd.ExtendedHelpText = cmd.Description = "Creates dump for the given process."; cmd.HelpOption(HelpOptionString); var pidOption = cmd.Option("--pid", "Process ID to which the tool will attach to", CommandOptionType.SingleValue); var outputOption = cmd.Option("--output", "Output file path", CommandOptionType.SingleValue); var typeOption = cmd.Option("--type", "Type of dump (Heap or Mini). ", CommandOptionType.SingleValue); cmd.OnExecuteAsync(async(_) => { if (pidOption.HasValue() == false) { return(cmd.ExitWithError("Missing --pid option.")); } if (int.TryParse(pidOption.Value(), out var pid) == false) { return(cmd.ExitWithError($"Could not parse --pid with value '{pidOption.Value()}' to number.")); } if (typeOption.HasValue() == false) { return(cmd.ExitWithError("Missing --type option.")); } if (Enum.TryParse(typeOption.Value(), ignoreCase: true, out Dumper.DumpTypeOption type) == false) { return(cmd.ExitWithError($"Could not parse --type with value '{typeOption.Value()}' to one of supported dump types.")); } string output = null; if (outputOption.HasValue()) { output = outputOption.Value(); } try { var dumper = new Dumper(); await dumper.Collect(cmd, pid, output, diag: false, type).ConfigureAwait(false); return(0); } catch (Exception e) { return(cmd.ExitWithError($"Failed to collect dump. Error: {e}")); } }); }); _app.Command("gcdump", cmd => { cmd.ExtendedHelpText = cmd.Description = "Creates GC dump for the given process."; cmd.HelpOption(HelpOptionString); var pidOption = cmd.Option("--pid", "Process ID to which the tool will attach to", CommandOptionType.SingleValue); var outputOption = cmd.Option("--output", "Output file path", CommandOptionType.SingleValue); var timeoutOption = cmd.Option("--timeout", "Give up on collecting the gcdump if it takes longer than this many seconds. The default value is. Default 30", CommandOptionType.SingleValue); var verboseOption = cmd.Option("--verbose", "Output the log while collecting the gcdump.", CommandOptionType.NoValue); cmd.OnExecuteAsync(async token => { if (pidOption.HasValue() == false) { return(cmd.ExitWithError("Missing --pid option.")); } if (int.TryParse(pidOption.Value(), out var pid) == false) { return(cmd.ExitWithError($"Could not parse --pid with value '{pidOption.Value()}' to number.")); } string output = null; if (outputOption.HasValue()) { output = outputOption.Value(); } int timeout = 30; if (timeoutOption.HasValue() && int.TryParse(timeoutOption.Value(), out timeout) == false) { return(cmd.ExitWithError($"Could not parse --timeout with value '{timeoutOption.Value()}' to number.")); } var verbose = verboseOption.HasValue(); try { await GCHeapDumper.Collect(token, cmd, pid, output, timeout, verbose).ConfigureAwait(false); return(0); } catch (Exception e) { return(cmd.ExitWithError($"Failed to collect GC dump. Error: {e}")); } }); }); _app.OnExecute(() => { _app.ShowHelp(); return(1); }); try { return(_app.Execute(args)); } catch (CommandParsingException e) { return(_app.ExitWithError(e.Message)); } }