| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel
- {
- using System;
- using System.IO;
- using System.Threading;
- using System.Security;
- using System.Runtime.InteropServices;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- using System.Runtime.Versioning;
- // Enable this code to track which thread operations occur on
- #if false
- static class ThreadTrace
- {
- static LocalDataStoreSlot slot;
- static List<ThreadLog> logs;
- static string logFileName;
- static bool isEnabled;
- static long frequency;
- static ThreadTrace()
- {
- logFileName = Environment.GetEnvironmentVariable("ThreadTrace");
- if (logFileName == null)
- logFileName = "";
- isEnabled = logFileName.Length > 0;
- if (isEnabled)
- {
- slot = Thread.AllocateDataSlot();
- logs = new List<ThreadLog>();
- NativeMethods.QueryPerformanceFrequency(out frequency);
- Console.WriteLine("ThreadTrace: enabled");
- new Thread(ThreadProc).Start();
- }
- }
- static bool stopTracing;
- public static void StopTracing()
- {
- stopTracing = true;
- }
- static void ThreadProc()
- {
- while (!stopTracing)
- {
- Thread.Sleep(20000);
- WriteLogFile();
- Console.WriteLine("ThreadTrace: " + logFileName + " saved.");
- }
- }
- static object ThisLock
- {
- get { return logs; }
- }
- public static void Trace(string operation)
- {
- if (isEnabled)
- {
- TraceInternal(operation);
- }
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TraceInternal(string operation)
- {
- long time;
- NativeMethods.QueryPerformanceCounter(out time);
- ThreadLog log = (ThreadLog)Thread.GetData(slot);
- if (log == null)
- {
- Thread currentThread = Thread.CurrentThread;
- log = new ThreadLog(currentThread);
- lock (ThisLock)
- {
- logs.Add(log);
- }
- Thread.SetData(slot, log);
- }
- log.Append(time, operation);
- }
- static void WriteLogFile()
- {
- Trace("ThreadTrace.Save");
- TextWriter writer = File.CreateText(logFileName);
- using (writer)
- {
- ThreadLogSnapshot[] logSnapshots = new ThreadLogSnapshot[logs.Count];
- writer.Write("Time");
- for (int i = 0; i < logs.Count; i++)
- {
- logSnapshots[i] = logs[i].GetSnapshot();
- writer.Write(", Thread ");
- writer.Write(i.ToString());
- }
- writer.WriteLine();
- writer.Write("(Ms)");
- foreach (ThreadLog log in logs)
- {
- if (log.IsThreadPoolThread)
- writer.Write(", (ThreadPool)");
- else if (log.IsBackgroundThread)
- writer.Write(", (Background)");
- else
- writer.Write(", (Main)");
- }
- writer.WriteLine();
- int[] indices = new int[logs.Count];
- int count = 0;
- for (int i = 0; i < logs.Count; i++)
- count += logSnapshots[i].Count;
- for (int j = 0; j < count; j++)
- {
- int earliestIndex = -1;
- long earliestTime = long.MaxValue;
- for (int i = 0; i < logs.Count; i++)
- {
- ThreadLogSnapshot logSnapshot = logSnapshots[i];
- int index = indices[i];
- if (index >= logSnapshot.Count)
- continue;
- long time = logSnapshot[index].time;
- if (time < earliestTime)
- {
- earliestIndex = i;
- earliestTime = time;
- }
- }
- ThreadLogEntry entry = logSnapshots[earliestIndex][indices[earliestIndex]];
- double timeInMilliseconds = (entry.time * 1000) / (double)frequency;
- writer.Write(timeInMilliseconds);
- for (int i = 0; i < logs.Count; i++)
- {
- writer.Write(", ");
- if (i == earliestIndex)
- {
- writer.Write('\"');
- writer.Write(entry.operation);
- writer.Write('\"');
- }
- }
- writer.WriteLine();
- indices[earliestIndex]++;
- }
- }
- }
- struct ThreadLogEntry
- {
- public long time;
- public string operation;
- public ThreadLogEntry(long time, string operation)
- {
- this.time = time;
- this.operation = operation;
- }
- }
- class ThreadLogSnapshot
- {
- ThreadLogEntry[] entries;
- public ThreadLogSnapshot(ThreadLogEntry[] entries)
- {
- this.entries = entries;
- }
- public int Count
- {
- get
- {
- return this.entries.Length;
- }
- }
- public ThreadLogEntry this[int index]
- {
- get
- {
- return this.entries[index];
- }
- }
- }
- class ThreadLog
- {
- int count;
- ThreadLogEntry[] buffer;
- const int bufferSize = 5000;
- const int maxBuffers = 4096;
- bool isThreadPoolThread;
- bool isBackgroundThread;
- ThreadLogEntry[][] buffers;
- int bufferCount;
- public ThreadLog(Thread thread)
- {
- this.isThreadPoolThread = thread.IsThreadPoolThread;
- this.isBackgroundThread = thread.IsBackground;
- this.buffer = new ThreadLogEntry[bufferSize];
- this.buffers = new ThreadLogEntry[maxBuffers][];
- }
- object ThisLock
- {
- get { return this; }
- }
- public bool IsThreadPoolThread
- {
- get { return this.isThreadPoolThread; }
- }
- public bool IsBackgroundThread
- {
- get { return this.isBackgroundThread; }
- }
- public void Append(long time, string operation)
- {
- if (this.count == bufferSize)
- {
- lock (ThisLock)
- {
- this.buffers[bufferCount++] = this.buffer;
- this.buffer = new ThreadLogEntry[bufferSize];
- this.count = 0;
- }
- }
- this.buffer[this.count++] = new ThreadLogEntry(time, operation);
- }
- public ThreadLogSnapshot GetSnapshot()
- {
- int currentBufferCount;
- int currentCount;
- ThreadLogEntry[] currentBuffer;
- lock (ThisLock)
- {
- currentBufferCount = this.bufferCount;
- currentCount = this.count;
- currentBuffer = this.buffer;
- }
- ThreadLogEntry[] entries = new ThreadLogEntry[currentBufferCount * bufferSize + currentCount];
- int index = 0;
- for (int i = 0; i < currentBufferCount; i++)
- {
- Array.Copy(buffers[i], 0, entries, index, bufferSize);
- index += bufferSize;
- }
- Array.Copy(currentBuffer, 0, entries, index, currentCount);
- return new ThreadLogSnapshot(entries);
- }
- }
- [SuppressUnmanagedCodeSecurity]
- static class NativeMethods
- {
- [DllImport("kernel32.dll")]
- [ResourceExposure(ResourceScope.None)]
- public static extern int QueryPerformanceCounter(out long time);
- [DllImport("kernel32.dll")]
- [ResourceExposure(ResourceScope.None)]
- public static extern int QueryPerformanceFrequency(out long frequency);
- }
- }
- #else
- static class ThreadTrace
- {
- public static void Trace(string operation)
- {
- }
- public static void StopTracing()
- {
- }
- public static void Save()
- {
- }
- }
- #endif
- }
|