diff --git a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
index 52a552c196..c81604ff34 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
@@ -34,7 +34,7 @@ namespace ICSharpCode.Profiler.Controller.Data
///
/// Creates a new SQLite profiling data provider and opens a database stored in a file.
///
- private ProfilingDataSQLiteProvider(string fileName, bool allowUpgrade)
+ ProfilingDataSQLiteProvider(string fileName, bool allowUpgrade)
{
this.nameMappingCache = new Dictionary();
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs
index ef5aed0259..28167133ee 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs
@@ -321,39 +321,48 @@ namespace ICSharpCode.Profiler.Controller.Data
{
using (SQLiteTransaction trans = this.connection.BeginTransaction()) {
using (SQLiteCommand cmd = this.connection.CreateCommand()) {
+ using (SQLiteCommand cmd2 = this.connection.CreateCommand()) {
- SQLiteParameter idParam = new SQLiteParameter("id");
- SQLiteParameter nameParam = new SQLiteParameter("name");
- SQLiteParameter dataSetParam = new SQLiteParameter("dataset");
- SQLiteParameter valueParam = new SQLiteParameter("value");
- SQLiteParameter minParam = new SQLiteParameter("min");
- SQLiteParameter maxParam = new SQLiteParameter("max");
- SQLiteParameter unitParam = new SQLiteParameter("unit");
-
- cmd.CommandText =
- "INSERT OR IGNORE INTO PerformanceCounter(id, name, minvalue, maxvalue, unit)" + // should I split these queries
- "VALUES(@id,@name,@min,@max,@unit);" + // for better performance?
- "INSERT INTO CounterData(datasetid, counterid, value)" +
- "VALUES(@dataset,@id,@value);";
-
- cmd.Parameters.AddRange(new SQLiteParameter[] { idParam, nameParam, dataSetParam, valueParam, minParam, maxParam, unitParam });
-
- int id = 0;
-
- foreach (PerformanceCounterDescriptor counter in counters) {
- idParam.Value = id;
- nameParam.Value = counter.Name;
- minParam.Value = counter.MinValue;
- maxParam.Value = counter.MaxValue;
- unitParam.Value = counter.Unit;
+ SQLiteParameter idParam = new SQLiteParameter("id");
+ SQLiteParameter nameParam = new SQLiteParameter("name");
+ SQLiteParameter dataSetParam = new SQLiteParameter("dataset");
+ SQLiteParameter valueParam = new SQLiteParameter("value");
+ SQLiteParameter minParam = new SQLiteParameter("min");
+ SQLiteParameter maxParam = new SQLiteParameter("max");
+ SQLiteParameter unitParam = new SQLiteParameter("unit");
+ SQLiteParameter formatParam = new SQLiteParameter("format");
- for (int i = 0; i < counter.Values.Count; i++) {
- dataSetParam.Value = i;
- valueParam.Value = counter.Values[i];
- cmd.ExecuteNonQuery();
- }
+ cmd.Parameters.AddRange(new SQLiteParameter[] { idParam, dataSetParam, valueParam });
+ cmd2.Parameters.AddRange(new SQLiteParameter[] { idParam, nameParam, minParam, maxParam, unitParam, formatParam });
+
+ cmd2.CommandText =
+ "INSERT INTO PerformanceCounter(id, name, minvalue, maxvalue, unit, format)" +
+ "VALUES(@id,@name,@min,@max,@unit,@format);";
- id++;
+ cmd.CommandText =
+ "INSERT INTO CounterData(datasetid, counterid, value)" +
+ "VALUES(@dataset,@id,@value);";
+
+ int id = 0;
+
+ foreach (PerformanceCounterDescriptor counter in counters) {
+ idParam.Value = id;
+ nameParam.Value = counter.Name;
+ minParam.Value = counter.MinValue;
+ maxParam.Value = counter.MaxValue;
+ unitParam.Value = counter.Unit;
+ formatParam.Value = counter.Format;
+
+ for (int i = 0; i < counter.Values.Count; i++) {
+ dataSetParam.Value = i;
+ valueParam.Value = counter.Values[i];
+ cmd.ExecuteNonQuery();
+ }
+
+ cmd2.ExecuteNonQuery();
+
+ id++;
+ }
}
}
trans.Commit();
diff --git a/src/AddIns/Misc/Profiler/Controller/Profiler.cs b/src/AddIns/Misc/Profiler/Controller/Profiler.cs
index 0eb800ac34..b24f532749 100644
--- a/src/AddIns/Misc/Profiler/Controller/Profiler.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Profiler.cs
@@ -707,9 +707,9 @@ namespace ICSharpCode.Profiler.Controller
return true;
} else if (readString.StartsWith("event ", StringComparison.Ordinal)) {
- string[] parts = readString.Split(' ');
+ IList parts = readString.SplitSeparatedString(' ');
// event
- if (parts.Length != 4)
+ if (parts.Count != 4)
return false;
int type = int.Parse(parts[1], CultureInfo.InvariantCulture);
int name = int.Parse(parts[2], CultureInfo.InvariantCulture);
@@ -718,6 +718,7 @@ namespace ICSharpCode.Profiler.Controller
lock (this.dataWriter) {
this.dataWriter.WriteEventData(new[] { new EventDataEntry() { DataSetId = this.dataWriter.DataSetCount, NameId = name, Type = (EventType)type, Data = data } });
}
+ return true;
} else {
if (readString.StartsWith("error-", StringComparison.Ordinal)) {
string[] parts = readString.Split('-');
diff --git a/src/AddIns/Misc/Profiler/Controller/structs.cs b/src/AddIns/Misc/Profiler/Controller/structs.cs
index 393319f186..b8e2805656 100644
--- a/src/AddIns/Misc/Profiler/Controller/structs.cs
+++ b/src/AddIns/Misc/Profiler/Controller/structs.cs
@@ -221,6 +221,7 @@ namespace ICSharpCode.Profiler.Controller
{
public int ThreadID;
public volatile int InLock;
+ public volatile bool Active;
public TargetProcessPointer32 Predecessor;
public TargetProcessPointer32 Follower;
public LightweightStack32 Stack;
diff --git a/src/AddIns/Misc/Profiler/Hook/LightweightList.cpp b/src/AddIns/Misc/Profiler/Hook/LightweightList.cpp
index eb578e69b5..1348cc9972 100644
--- a/src/AddIns/Misc/Profiler/Hook/LightweightList.cpp
+++ b/src/AddIns/Misc/Profiler/Hook/LightweightList.cpp
@@ -23,6 +23,8 @@ ThreadLocalData *LightweightList::add()
void *itemMemory = stackAllocator.malloc(sizeof(ThreadLocalData));
assert(itemMemory != nullptr);
ThreadLocalData *item = new (itemMemory) ThreadLocalData();
+
+ item->active = true;
if (this->lastItem == nullptr) {
this->lastItem = item;
diff --git a/src/AddIns/Misc/Profiler/Hook/Profiler.cpp b/src/AddIns/Misc/Profiler/Hook/Profiler.cpp
index f7dcf66f4d..82cc8c479b 100644
--- a/src/AddIns/Misc/Profiler/Hook/Profiler.cpp
+++ b/src/AddIns/Misc/Profiler/Hook/Profiler.cpp
@@ -77,6 +77,9 @@ ASSEMBLER_CALLBACK FunctionEnterGlobal(int functionID)
FunctionEnterCreateNewRoot(data, __rdtsc());
} else
profiler.EnterLock(data);
+
+ if (!data->active)
+ goto EXIT;
// this call allows GetOrAddChild to update the value at the top of the stack
// if the FunctionInfo is resized
@@ -109,7 +112,7 @@ ASSEMBLER_CALLBACK FunctionEnterGlobal(int functionID)
data->stack.push(StackEntry(child, __rdtsc()));
}
-
+EXIT:
data->inLock = 0;
}
@@ -131,6 +134,9 @@ ASSEMBLER_CALLBACK FunctionLeaveGlobal()
ThreadLocalData *data = getThreadLocalData();
profiler.EnterLock(data);
+
+ if (!data->active)
+ goto EXIT;
if (data->stack.empty()) {
//DebugWriteLine(L"FunctionLeaveGlobal (but stack was empty)");
@@ -143,7 +149,8 @@ ASSEMBLER_CALLBACK FunctionLeaveGlobal()
data->stack.pop();
}
}
-
+
+EXIT:
data->inLock = 0;
}
@@ -238,7 +245,6 @@ CProfiler::CProfiler()
this->pICorProfilerInfo = nullptr;
this->pICorProfilerInfo2 = nullptr;
this->sigReader = nullptr;
- this->active = true;
}
// ---- ICorProfilerCallback IMPLEMENTATION ------------------
@@ -626,12 +632,14 @@ STDMETHODIMP CProfiler::JITCompilationStarted(FunctionID functionID, BOOL /*fIsS
void CProfiler::Activate()
{
-
+ ThreadLocalData *data = getThreadLocalData();
+ data->active = true;
}
void CProfiler::Deactivate()
{
-
+ ThreadLocalData *data = getThreadLocalData();
+ data->active = false;
}
const ULONG FAT_HEADER_SIZE = 0xC; /* 12 bytes = WORD + WORD + DWORD + DWORD */
diff --git a/src/AddIns/Misc/Profiler/Hook/Profiler.h b/src/AddIns/Misc/Profiler/Hook/Profiler.h
index 58e873f5c4..92f6ee62ef 100644
--- a/src/AddIns/Misc/Profiler/Hook/Profiler.h
+++ b/src/AddIns/Misc/Profiler/Hook/Profiler.h
@@ -132,8 +132,6 @@ private:
TUThreadIDMap unmanagedThreadIDMap;
TMethodTokenMap methodMap;
- bool active;
-
// function to set up our event mask
HRESULT SetEventMask();
void Rewrite(FunctionID functionID, int type, int nameId, WCHAR *name);
diff --git a/src/AddIns/Misc/Profiler/Hook/constants.cpp b/src/AddIns/Misc/Profiler/Hook/constants.cpp
index 5d184b6982..09e70f4260 100644
--- a/src/AddIns/Misc/Profiler/Hook/constants.cpp
+++ b/src/AddIns/Misc/Profiler/Hook/constants.cpp
@@ -18,5 +18,5 @@ WCHAR *winFormsGroupList[WINFORMS_GROUP_LENGTH] = {
};
WCHAR *wpfGroupList[WPF_GROUP_LENGTH] = {
- L"dummy"
+ L"System.Windows.UIElement.OnLeftMouseButtonDown"
};
\ No newline at end of file
diff --git a/src/AddIns/Misc/Profiler/Hook/global.h b/src/AddIns/Misc/Profiler/Hook/global.h
index 9c706de4df..75b7e8ccf3 100644
--- a/src/AddIns/Misc/Profiler/Hook/global.h
+++ b/src/AddIns/Misc/Profiler/Hook/global.h
@@ -40,6 +40,7 @@ struct StackEntry {
struct ThreadLocalData {
int threadID;
volatile int inLock;
+ volatile bool active;
ThreadLocalData *predecessor;
ThreadLocalData *follower;
diff --git a/src/AddIns/Misc/Profiler/Hook/main.cpp b/src/AddIns/Misc/Profiler/Hook/main.cpp
index ad9e18c3bd..e4d08f6761 100644
--- a/src/AddIns/Misc/Profiler/Hook/main.cpp
+++ b/src/AddIns/Misc/Profiler/Hook/main.cpp
@@ -8,6 +8,7 @@
#include "main.h"
#include "global.h"
#include "FunctionInfo.h"
+#include "ProfilerMetaData.h"
//sharedMemoryAllocator mallocator;
freeListAllocator mallocator;
@@ -43,37 +44,41 @@ STDAPI rdtsc(ULONGLONG *tsc) {
return S_OK;
}
+
+std::wstring EscapeString(const WCHAR *input)
+{
+ std::wostringstream output;
+ output.str(L"");
+
+ for (const WCHAR *ptr = input; *ptr != 0; ptr++) {
+ WCHAR c = *ptr;
+ if (c == '"')
+ output << "\"\"";
+ else
+ output << c;
+ }
+
+ return output.str();
+}
+
extern "C" {
void __stdcall DeactivateProfiler()
{
- profiler.LogString(L"DeactivateProfiler called!");
profiler.Deactivate();
}
void __stdcall ActivateProfiler()
{
- profiler.LogString(L"ActivateProfiler called!");
profiler.Activate();
}
void __stdcall LogEvent(int type, int id, WCHAR *controlName, WCHAR *controlText)
{
- WCHAR *format = L"";
-
- switch (type) {
- case 0:
- format = L"event %d %d --";
- break;
- case 1:
- format = L"event %d %d --";
- break;
- case 2:
- format = L"event %d %d -name:\"%s\"text:\"%s\"-";
- break;
- case 3:
- break;
- }
+ if (controlName == nullptr)
+ controlName = L"";
+ if (controlText == nullptr)
+ controlText = L"";
- DebugWriteLine(format, type, id, controlName, controlText);
+ profiler.LogString(L"event %d %d \"%s:%s\"", type, id, EscapeString(controlName).c_str(), EscapeString(controlText).c_str());
}
}
\ No newline at end of file