LuaProfiler.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. #########
  3. ############
  4. #############
  5. ## ###########
  6. ### ###### #####
  7. ### ####### ####
  8. ### ########## ####
  9. #### ########### ####
  10. #### ########### #####
  11. ##### ### ######## #####
  12. ##### ### ######## ######
  13. ###### ### ########### ######
  14. ###### #### ############## ######
  15. ####### ##################### ######
  16. ####### ###################### ######
  17. ####### ###### ################# ######
  18. ####### ###### ###### ######### ######
  19. ####### ## ###### ###### ######
  20. ####### ###### ##### #####
  21. ###### ##### ##### ####
  22. ##### #### ##### ###
  23. ##### ### ### #
  24. ### ### ###
  25. ## ### ###
  26. __________#_______####_______####______________
  27. 我们的未来没有BUG
  28. * ==============================================================================
  29. * Filename: LuaProfiler
  30. * Created: 2018/7/13 14:29:22
  31. * Author: エル・プサイ・コングリィ
  32. * Purpose:
  33. * ==============================================================================
  34. */
  35. #if UNITY_EDITOR || USE_LUA_PROFILER
  36. using System;
  37. using System.Collections.Generic;
  38. using System.Reflection;
  39. using RefDict = System.Collections.Generic.Dictionary<string, System.Collections.Generic.HashSet<string>>;
  40. #if UNITY_5_5_OR_NEWER
  41. using UnityEngine.Profiling;
  42. #endif
  43. namespace MikuLuaProfiler
  44. {
  45. public static class LuaProfiler
  46. {
  47. #region member
  48. private static IntPtr _mainL = IntPtr.Zero;
  49. private static readonly Stack<Sample> beginSampleMemoryStack = new Stack<Sample>();
  50. private static int m_currentFrame = 0;
  51. public static int mainThreadId = -100;
  52. const long MaxB = 1024;
  53. const long MaxK = MaxB * 1024;
  54. const long MaxM = MaxK * 1024;
  55. const long MaxG = MaxM * 1024;
  56. #endregion
  57. #region property
  58. public static bool m_hasL = false;
  59. public static IntPtr mainL
  60. {
  61. get
  62. {
  63. return _mainL;
  64. }
  65. set
  66. {
  67. if (value != IntPtr.Zero)
  68. {
  69. m_hasL = true;
  70. LuaDLL.luaL_initlibs(value);
  71. }
  72. else
  73. {
  74. m_hasL = false;
  75. }
  76. _mainL = value;
  77. }
  78. }
  79. public static bool IsMainThread
  80. {
  81. get
  82. {
  83. return System.Threading.Thread.CurrentThread.ManagedThreadId == mainThreadId;
  84. }
  85. }
  86. #endregion
  87. #region sample
  88. public static void BeginSampleCSharp(string name)
  89. {
  90. BeginSample(_mainL, name);
  91. }
  92. public static void EndSampleCSharp()
  93. {
  94. EndSample(_mainL);
  95. }
  96. public static long getcurrentTime
  97. {
  98. get
  99. {
  100. return System.Diagnostics.Stopwatch.GetTimestamp();
  101. }
  102. }
  103. public static void BeginSample(IntPtr luaState, string name, bool needShow = false)
  104. {
  105. if (!IsMainThread)
  106. {
  107. return;
  108. }
  109. try
  110. {
  111. int frameCount = HookLuaSetup.frameCount;
  112. if (m_currentFrame != frameCount)
  113. {
  114. PopAllSampleWhenLateUpdate(luaState);
  115. m_currentFrame = frameCount;
  116. }
  117. long memoryCount = LuaLib.GetLuaMemory(luaState);
  118. Sample sample = Sample.Create(getcurrentTime, (int)memoryCount, name);
  119. sample.needShow = needShow;
  120. beginSampleMemoryStack.Push(sample);
  121. }
  122. catch
  123. {
  124. }
  125. }
  126. private static List<Sample> popChilds = new List<Sample>();
  127. public static void PopAllSampleWhenLateUpdate(IntPtr luaState)
  128. {
  129. while(beginSampleMemoryStack.Count > 0)
  130. {
  131. var item = beginSampleMemoryStack.Pop();
  132. if (item.fahter == null)
  133. {
  134. if (beginSampleMemoryStack.Count > 0)
  135. {
  136. long mono_gc = 0;
  137. long lua_gc = 0;
  138. long cost_time = 0;
  139. for (int i = 0, imax = item.childs.Count; i < imax; i++)
  140. {
  141. Sample c = item.childs[i];
  142. lua_gc += c.costLuaGC;
  143. mono_gc += c.costMonoGC;
  144. cost_time += c.costTime;
  145. }
  146. item.costLuaGC = (int)Math.Max(lua_gc, 0);
  147. item.costMonoGC = (int)Math.Max(mono_gc, 0);
  148. item.costTime = (int)cost_time;
  149. popChilds.Add(item);
  150. }
  151. else
  152. {
  153. item.costLuaGC = (int)LuaLib.GetLuaMemory(luaState) - item.currentLuaMemory;
  154. item.costTime = (int)(getcurrentTime - item.currentTime);
  155. item.costMonoGC = (int)(GC.GetTotalMemory(false) - item.currentMonoMemory);
  156. item.currentLuaMemory = (int)LuaLib.GetLuaMemory(luaState);
  157. for (int i = 0, imax = popChilds.Count; i < imax; i++)
  158. {
  159. popChilds[i].fahter = item;
  160. }
  161. popChilds.Clear();
  162. NetWorkClient.SendMessage(item);
  163. }
  164. //item.Restore();
  165. }
  166. }
  167. beginSampleMemoryStack.Clear();
  168. }
  169. public static void EndSample(IntPtr luaState)
  170. {
  171. if (!IsMainThread)
  172. {
  173. return;
  174. }
  175. if (beginSampleMemoryStack.Count <= 0)
  176. {
  177. return;
  178. }
  179. long nowMemoryCount = LuaLib.GetLuaMemory(luaState);
  180. long nowMonoCount = GC.GetTotalMemory(false);
  181. Sample sample = beginSampleMemoryStack.Pop();
  182. sample.costTime = (int)(getcurrentTime - sample.currentTime);
  183. var monoGC = nowMonoCount - sample.currentMonoMemory;
  184. var luaGC = nowMemoryCount - sample.currentLuaMemory;
  185. sample.currentLuaMemory = (int)nowMemoryCount;
  186. sample.currentMonoMemory = (int)nowMonoCount;
  187. sample.costLuaGC = (int)luaGC;
  188. sample.costMonoGC = (int)monoGC;
  189. if (sample.childs.Count > 0)
  190. {
  191. long mono_gc = 0;
  192. long lua_gc = 0;
  193. for (int i = 0, imax = sample.childs.Count; i < imax; i++)
  194. {
  195. Sample c = sample.childs[i];
  196. lua_gc += c.costLuaGC;
  197. mono_gc += c.costMonoGC;
  198. }
  199. sample.costLuaGC = (int)Math.Max(lua_gc, luaGC);
  200. sample.costMonoGC = (int)Math.Max(mono_gc, monoGC);
  201. }
  202. if (!sample.CheckSampleValid())
  203. {
  204. sample.Restore();
  205. return;
  206. }
  207. sample.fahter = beginSampleMemoryStack.Count > 0 ? beginSampleMemoryStack.Peek() : null;
  208. //UnityEngine.Debug.Log(sample.name);
  209. if (beginSampleMemoryStack.Count == 0)
  210. {
  211. var setting = LuaDeepProfilerSetting.Instance;
  212. if (setting == null) return;
  213. if (setting != null && setting.isNeedCapture)
  214. {
  215. //迟钝了
  216. if (sample.costTime >= (1 / (float)(setting.captureFrameRate)) * 10000000)
  217. {
  218. sample.captureUrl = Sample.Capture();
  219. }
  220. else if (sample.costLuaGC > setting.captureLuaGC)
  221. {
  222. sample.captureUrl = Sample.Capture();
  223. }
  224. else if (sample.costMonoGC > setting.captureMonoGC)
  225. {
  226. sample.captureUrl = Sample.Capture();
  227. }
  228. else
  229. {
  230. sample.captureUrl = null;
  231. }
  232. }
  233. NetWorkClient.SendMessage(sample);
  234. }
  235. //释放掉被累加的Sample
  236. if (beginSampleMemoryStack.Count != 0 && sample.fahter == null)
  237. {
  238. sample.Restore();
  239. }
  240. }
  241. #endregion
  242. #region ref
  243. private static Dictionary<byte, RefDict> m_refDict = new Dictionary<byte, RefDict>(4);
  244. public static void AddRef(string refName, string refAddr, byte type)
  245. {
  246. RefDict refDict;
  247. if (!m_refDict.TryGetValue(type, out refDict))
  248. {
  249. refDict = new RefDict(2048);
  250. m_refDict.Add(type, refDict);
  251. }
  252. HashSet<string> addrList;
  253. if (!refDict.TryGetValue(refName, out addrList))
  254. {
  255. addrList = new HashSet<string>();
  256. refDict.Add(refName, addrList);
  257. }
  258. if (!addrList.Contains(refAddr))
  259. {
  260. addrList.Add(refAddr);
  261. }
  262. SendAddRef(refName, refAddr, type);
  263. }
  264. public static void SendAddRef(string funName, string funAddr, byte type)
  265. {
  266. LuaRefInfo refInfo = LuaRefInfo.Create(1, funName, funAddr, type);
  267. NetWorkClient.SendMessage(refInfo);
  268. }
  269. public static void RemoveRef(string refName, string refAddr, byte type)
  270. {
  271. if (string.IsNullOrEmpty(refName)) return;
  272. RefDict refDict;
  273. if (!m_refDict.TryGetValue(type, out refDict))
  274. {
  275. return;
  276. }
  277. HashSet<string> addrList;
  278. if (!refDict.TryGetValue(refName, out addrList))
  279. {
  280. return;
  281. }
  282. if (!addrList.Contains(refAddr))
  283. {
  284. return;
  285. }
  286. addrList.Remove(refAddr);
  287. if (addrList.Count == 0)
  288. {
  289. refDict.Remove(refName);
  290. }
  291. SendRemoveRef(refName, refAddr, type);
  292. }
  293. public static void SendRemoveRef(string funName, string funAddr, byte type)
  294. {
  295. LuaRefInfo refInfo = LuaRefInfo.Create(0, funName, funAddr, type);
  296. NetWorkClient.SendMessage(refInfo);
  297. }
  298. public static void SendAllRef()
  299. {
  300. foreach (var dictItem in m_refDict)
  301. {
  302. foreach (var hashList in dictItem.Value)
  303. {
  304. foreach (var item in hashList.Value)
  305. {
  306. SendAddRef(hashList.Key, item, dictItem.Key);
  307. }
  308. }
  309. }
  310. }
  311. #endregion
  312. }
  313. }
  314. #endif