Sample.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  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: Sample
  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.IO;
  39. using System.Text;
  40. using UnityEngine;
  41. namespace MikuLuaProfiler
  42. {
  43. public enum LuaTypes
  44. {
  45. LUA_TNONE = -1,
  46. LUA_TNIL = 0,
  47. LUA_TNUMBER = 3,
  48. LUA_TSTRING = 4,
  49. LUA_TBOOLEAN = 1,
  50. LUA_TTABLE = 5,
  51. LUA_TFUNCTION = 6,
  52. LUA_TUSERDATA = 7,
  53. LUA_TTHREAD = 8,
  54. LUA_TLIGHTUSERDATA = 2
  55. }
  56. public abstract class NetBase
  57. {
  58. public abstract void Restore();
  59. }
  60. public class LuaRefInfo : NetBase
  61. {
  62. #region field
  63. public byte cmd; //1添加、0移除
  64. public int frameCount;
  65. public string name;
  66. public string addr;
  67. public byte type; //1 function 2 table
  68. #endregion
  69. #region pool
  70. private static ObjectPool<LuaRefInfo> m_pool = new ObjectPool<LuaRefInfo>(32);
  71. public static LuaRefInfo Create()
  72. {
  73. LuaRefInfo r = m_pool.GetObject();
  74. return r;
  75. }
  76. public static LuaRefInfo Create(byte cmd, string name, string addr, byte type)
  77. {
  78. LuaRefInfo r = m_pool.GetObject();
  79. r.cmd = cmd;
  80. r.name = name;
  81. r.addr = addr;
  82. r.type = type;
  83. return r;
  84. }
  85. public override void Restore()
  86. {
  87. m_pool.Store(this);
  88. }
  89. public LuaRefInfo Clone()
  90. {
  91. LuaRefInfo result = new LuaRefInfo();
  92. result.cmd = this.cmd;
  93. result.frameCount = this.frameCount;
  94. result.name = this.name;
  95. result.addr = this.addr;
  96. result.type = this.type;
  97. return result;
  98. }
  99. #endregion
  100. }
  101. public class LuaDiffInfo : NetBase
  102. {
  103. #region field
  104. public Dictionary<LuaTypes, HashSet<string>> addRef = new Dictionary<LuaTypes, HashSet<string>>();
  105. public Dictionary<string, List<string>> addDetail = new Dictionary<string, List<string>>();
  106. public Dictionary<LuaTypes, HashSet<string>> rmRef = new Dictionary<LuaTypes, HashSet<string>>();
  107. public Dictionary<string, List<string>> rmDetail = new Dictionary<string, List<string>>();
  108. public Dictionary<LuaTypes, HashSet<string>> nullRef = new Dictionary<LuaTypes, HashSet<string>>();
  109. public Dictionary<string, List<string>> nullDetail = new Dictionary<string, List<string>>();
  110. #endregion
  111. #region pool
  112. private static ObjectPool<LuaDiffInfo> m_pool = new ObjectPool<LuaDiffInfo>(32);
  113. public static LuaDiffInfo Create()
  114. {
  115. LuaDiffInfo r = m_pool.GetObject();
  116. r.addRef.Clear();
  117. r.addDetail.Clear();
  118. r.rmRef.Clear();
  119. r.rmDetail.Clear();
  120. r.nullRef.Clear();
  121. return r;
  122. }
  123. public override void Restore()
  124. {
  125. m_pool.Store(this);
  126. }
  127. #endregion
  128. #region api
  129. public void PushAddRef(string addKey, int addType)
  130. {
  131. HashSet<string> list;
  132. LuaTypes t = (LuaTypes)addType;
  133. if (!addRef.TryGetValue(t, out list))
  134. {
  135. list = new HashSet<string>();
  136. addRef.Add(t, list);
  137. }
  138. if (!list.Contains(addKey))
  139. {
  140. list.Add(addKey);
  141. }
  142. }
  143. public void PushAddDetail(string addKey, string value)
  144. {
  145. List<string> list;
  146. if (!addDetail.TryGetValue(addKey, out list))
  147. {
  148. list = new List<string>();
  149. addDetail[addKey] = list;
  150. }
  151. list.Add(value);
  152. }
  153. public void PushRmRef(string addKey, int addType)
  154. {
  155. HashSet<string> list;
  156. LuaTypes t = (LuaTypes)addType;
  157. if (!rmRef.TryGetValue(t, out list))
  158. {
  159. list = new HashSet<string>();
  160. rmRef.Add(t, list);
  161. }
  162. if (!list.Contains(addKey))
  163. {
  164. list.Add(addKey);
  165. }
  166. }
  167. public void PushRmDetail(string key, string value)
  168. {
  169. List<string> list;
  170. if (!rmDetail.TryGetValue(key, out list))
  171. {
  172. list = new List<string>();
  173. rmDetail[key] = list;
  174. }
  175. list.Add(value);
  176. }
  177. public void PushNullRef(string addKey, int addType)
  178. {
  179. HashSet<string> list;
  180. LuaTypes t = (LuaTypes)addType;
  181. if (!nullRef.TryGetValue(t, out list))
  182. {
  183. list = new HashSet<string>();
  184. nullRef.Add(t, list);
  185. }
  186. if (!list.Contains(addKey))
  187. {
  188. list.Add(addKey);
  189. }
  190. }
  191. public void PushNullDetail(string addKey, string value)
  192. {
  193. List<string> list;
  194. if (!nullDetail.TryGetValue(addKey, out list))
  195. {
  196. list = new List<string>();
  197. nullDetail[addKey] = list;
  198. }
  199. list.Add(value);
  200. }
  201. #endregion
  202. }
  203. public class SampleData
  204. {
  205. public static int frameCount;
  206. public static float fps;
  207. public static uint pss;
  208. public static float power;
  209. }
  210. public class Sample : NetBase
  211. {
  212. public int currentLuaMemory;
  213. public int currentMonoMemory;
  214. public long currentTime;
  215. public int calls;
  216. public int frameCount;
  217. public float fps;
  218. public uint pss;
  219. public float power;
  220. public int costLuaGC;
  221. public int costMonoGC;
  222. public string name;
  223. public int costTime;
  224. public Sample _father;
  225. public MList<Sample> childs = new MList<Sample>(16);
  226. public string captureUrl = null;
  227. private string _fullName;
  228. public bool needShow = false;
  229. public bool isCopy = false;
  230. public long copySelfLuaGC = -1;
  231. public long selfLuaGC
  232. {
  233. get
  234. {
  235. if (isCopy) return copySelfLuaGC;
  236. long result = costLuaGC;
  237. for (int i = 0, imax = childs.Count; i < imax; i++)
  238. {
  239. var item = childs[i];
  240. result -= item.costLuaGC;
  241. }
  242. return Math.Max(result, 0);
  243. }
  244. }
  245. public long copySelfMonoGC = -1;
  246. public long selfMonoGC
  247. {
  248. get
  249. {
  250. if (isCopy) return copySelfMonoGC;
  251. long result = costMonoGC;
  252. for (int i = 0, imax = childs.Count; i < imax; i++)
  253. {
  254. var item = childs[i];
  255. result -= item.costMonoGC;
  256. }
  257. return Math.Max(result, 0);
  258. }
  259. }
  260. public int copySelfCostTime = -1;
  261. public int selfCostTime
  262. {
  263. get
  264. {
  265. if (isCopy) return copySelfCostTime;
  266. int result = costTime;
  267. for (int i = 0, imax = childs.Count; i < imax; i++)
  268. {
  269. var item = childs[i];
  270. result -= item.costTime;
  271. }
  272. return Math.Max(result, 0);
  273. }
  274. }
  275. public bool CheckSampleValid()
  276. {
  277. bool result = false;
  278. do
  279. {
  280. if (needShow)
  281. {
  282. result = true;
  283. break;
  284. }
  285. var setting = LuaDeepProfilerSetting.Instance;
  286. if (setting != null && !setting.discardInvalid)
  287. {
  288. result = true;
  289. break;
  290. }
  291. if (costLuaGC != 0)
  292. {
  293. result = true;
  294. break;
  295. }
  296. if (costMonoGC != 0)
  297. {
  298. result = true;
  299. break;
  300. }
  301. if (costTime > 10000)
  302. {
  303. result = true;
  304. break;
  305. }
  306. } while (false);
  307. return result;
  308. }
  309. #region property
  310. public string fullName
  311. {
  312. get
  313. {
  314. if (_father == null) return name;
  315. if (_fullName == null)
  316. {
  317. Dictionary<object, string> childDict;
  318. if (!m_fullNamePool.TryGetValue(_father.fullName, out childDict))
  319. {
  320. childDict = new Dictionary<object, string>();
  321. m_fullNamePool.Add(_father.fullName, childDict);
  322. }
  323. if (!childDict.TryGetValue(name, out _fullName))
  324. {
  325. string value = name;
  326. var f = _father;
  327. while (f != null)
  328. {
  329. value = f.name + value;
  330. f = f.fahter;
  331. }
  332. _fullName = value;
  333. childDict[name] = string.Intern(_fullName);
  334. }
  335. return _fullName;
  336. }
  337. else
  338. {
  339. return _fullName;
  340. }
  341. }
  342. }
  343. public Sample fahter
  344. {
  345. set
  346. {
  347. if (value != null)
  348. {
  349. bool needAdd = true;
  350. var childList = value.childs;
  351. for (int i = 0,imax = childList.Count;i<imax;i++)
  352. {
  353. var item = childList[i];
  354. if ((object)(item.name) == (object)(name))
  355. {
  356. needAdd = false;
  357. item.AddSample(this);
  358. break;
  359. }
  360. }
  361. if (needAdd)
  362. {
  363. childList.Add(this);
  364. _father = value;
  365. }
  366. }
  367. else
  368. {
  369. _father = null;
  370. }
  371. }
  372. get
  373. {
  374. return _father;
  375. }
  376. }
  377. #endregion
  378. #region pool
  379. private static string capturePath = "";
  380. private static Dictionary<object, Dictionary<object, string>> m_fullNamePool = new Dictionary<object, Dictionary<object, string>>();
  381. private static ObjectPool<Sample> samplePool = new ObjectPool<Sample>(4096);
  382. public static Sample Create()
  383. {
  384. Sample s = samplePool.GetObject();
  385. return s;
  386. }
  387. public static Sample Create(long time, int memory, string name)
  388. {
  389. Sample s = samplePool.GetObject();
  390. s.calls = 1;
  391. s.currentTime = time;
  392. s.currentLuaMemory = memory;
  393. s.currentMonoMemory = (int)GC.GetTotalMemory(false);
  394. s.frameCount = SampleData.frameCount;
  395. s.fps = SampleData.fps;
  396. s.pss = SampleData.pss;
  397. s.power = SampleData.power;
  398. s.costLuaGC = 0;
  399. s.costMonoGC = 0;
  400. s.name = name;
  401. s.costTime = 0;
  402. s._father = null;
  403. s.childs.Clear();
  404. s.captureUrl = null;
  405. s._fullName = null;
  406. return s;
  407. }
  408. public override void Restore()
  409. {
  410. lock (this)
  411. {
  412. for (int i = 0, imax = childs.Count; i < imax; i++)
  413. {
  414. childs[i].Restore();
  415. }
  416. _fullName = null;
  417. childs.Clear();
  418. samplePool.Store(this);
  419. }
  420. }
  421. #endregion
  422. #region method
  423. public void AddSample(Sample s)
  424. {
  425. calls += s.calls;
  426. costLuaGC += s.costLuaGC;
  427. costMonoGC += s.costMonoGC;
  428. costTime += s.costTime;
  429. for (int i = s.childs.Count - 1; i >= 0; i--)
  430. {
  431. var item = s.childs[i];
  432. item.fahter = this;
  433. if (item.fahter != s)
  434. {
  435. s.childs.RemoveAt(i);
  436. }
  437. }
  438. }
  439. public static string Capture()
  440. {
  441. if (string.IsNullOrEmpty(capturePath)) capturePath = "capture" + DateTime.Now.Ticks.ToString();
  442. Directory.CreateDirectory(capturePath);
  443. string result = capturePath + "/" + Time.frameCount.ToString() + ".png";
  444. #if UNITY_2017_1_OR_NEWER
  445. ScreenCapture.CaptureScreenshot(result, 0);
  446. #else
  447. Application.CaptureScreenshot(result, 0);
  448. #endif
  449. return result;
  450. }
  451. public Sample Clone()
  452. {
  453. Sample s = new Sample();
  454. s.calls = calls;
  455. s.frameCount = frameCount;
  456. s.fps = fps;
  457. s.pss = pss;
  458. s.power = power;
  459. s.costMonoGC = costMonoGC;
  460. s.costLuaGC = costLuaGC;
  461. s.name = name;
  462. s.costTime = costTime;
  463. int childCount = childs.Count;
  464. for (int i = 0; i < childCount; i++)
  465. {
  466. Sample child = childs[i].Clone();
  467. child.fahter = s;
  468. }
  469. s.currentLuaMemory = currentLuaMemory;
  470. s.currentMonoMemory = currentMonoMemory;
  471. s.currentTime = currentTime;
  472. s.captureUrl = captureUrl;
  473. return s;
  474. }
  475. #endregion
  476. #region 序列化
  477. public static void SerializeList(List<Sample> samples, string path)
  478. {
  479. FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write);
  480. BinaryWriter b = new BinaryWriter(fs);
  481. #if UNITY_EDITOR
  482. UnityEditor.EditorUtility.ClearProgressBar();
  483. #endif
  484. b.Write(samples.Count);
  485. for (int i = 0, imax = samples.Count; i < imax; i++)
  486. {
  487. Sample s = samples[i];
  488. #if UNITY_EDITOR
  489. UnityEditor.EditorUtility.DisplayProgressBar("serialize profiler data", "serialize " + s.name, (float)i / (float)imax);
  490. #endif
  491. byte[] datas = s.Serialize();
  492. b.Write(datas.Length);
  493. b.Write(datas);
  494. }
  495. b.Close();
  496. #if UNITY_EDITOR
  497. UnityEditor.EditorUtility.ClearProgressBar();
  498. #endif
  499. }
  500. public static List<Sample> DeserializeList(string path)
  501. {
  502. FileStream ms = new FileStream(path, FileMode.Open, FileAccess.Read);
  503. BinaryReader b = new BinaryReader(ms);
  504. int count = b.ReadInt32();
  505. List<Sample> result = new List<Sample>(count);
  506. for (int i = 0, imax = count; i < imax; i++)
  507. {
  508. int len = b.ReadInt32();
  509. Sample s = Deserialize(b.ReadBytes(len));
  510. result.Add(s);
  511. }
  512. b.Close();
  513. return result;
  514. }
  515. public byte[] Serialize()
  516. {
  517. byte[] result = null;
  518. MemoryStream ms = new MemoryStream();
  519. BinaryWriter b = new BinaryWriter(ms);
  520. b.Write(calls);
  521. b.Write(frameCount);
  522. b.Write(fps);
  523. b.Write(pss);
  524. b.Write(power);
  525. b.Write(costLuaGC);
  526. b.Write(costMonoGC);
  527. byte[] datas = Encoding.UTF8.GetBytes(name);
  528. b.Write(datas.Length);
  529. b.Write(datas);
  530. b.Write(costTime);
  531. b.Write(childs.Count);
  532. for (int i = 0, imax = childs.Count; i < imax; i++)
  533. {
  534. datas = childs[i].Serialize();
  535. b.Write(datas.Length);
  536. b.Write(datas);
  537. }
  538. if (string.IsNullOrEmpty(captureUrl) || !File.Exists(captureUrl))
  539. {
  540. b.Write(false);
  541. }
  542. else
  543. {
  544. b.Write(true);
  545. datas = Encoding.UTF8.GetBytes(captureUrl);
  546. b.Write(datas.Length);
  547. b.Write(datas);
  548. //写入图片数据
  549. datas = File.ReadAllBytes(captureUrl);
  550. b.Write(datas.Length);
  551. b.Write(datas);
  552. }
  553. b.Write(currentLuaMemory);
  554. b.Write(currentMonoMemory);
  555. result = ms.ToArray();
  556. b.Close();
  557. return result;
  558. }
  559. public static Sample Deserialize(byte[] data)
  560. {
  561. MemoryStream ms = new MemoryStream(data);
  562. BinaryReader b = new BinaryReader(ms);
  563. return Deserialize(b);
  564. }
  565. public static Sample Deserialize(BinaryReader b)
  566. {
  567. Sample s = new Sample();
  568. s.calls = b.ReadInt32();
  569. s.frameCount = b.ReadInt32();
  570. s.fps = b.ReadSingle();
  571. s.pss = b.ReadUInt32();
  572. s.power = b.ReadSingle();
  573. s.costLuaGC = b.ReadInt32();
  574. s.costMonoGC = b.ReadInt32();
  575. int len = b.ReadInt32();
  576. byte[] datas = b.ReadBytes(len);
  577. s.name = Encoding.UTF8.GetString(datas);
  578. s.costTime = b.ReadInt32();
  579. int childCount = b.ReadInt32();
  580. for (int i = 0; i < childCount; i++)
  581. {
  582. len = b.ReadInt32();
  583. datas = b.ReadBytes(len);
  584. Sample child = Deserialize(datas);
  585. child.fahter = s;
  586. }
  587. bool hasCapture = b.ReadBoolean();
  588. if (hasCapture)
  589. {
  590. len = b.ReadInt32();
  591. datas = b.ReadBytes(len);
  592. s.captureUrl = Encoding.UTF8.GetString(datas);
  593. if (!File.Exists(s.captureUrl))
  594. {
  595. string dir = Path.GetDirectoryName(s.captureUrl);
  596. if (!Directory.Exists(dir))
  597. {
  598. Directory.CreateDirectory(dir);
  599. }
  600. len = b.ReadInt32();
  601. datas = b.ReadBytes(len);
  602. //写入图片数据
  603. File.WriteAllBytes(s.captureUrl, datas);
  604. }
  605. }
  606. s.currentLuaMemory = b.ReadInt32();
  607. s.currentMonoMemory = b.ReadInt32();
  608. int lua_gc = 0;
  609. int mono_gc = 0;
  610. for (int i = 0, imax = s.childs.Count; i < imax; i++)
  611. {
  612. var item = s.childs[i];
  613. lua_gc += item.costLuaGC;
  614. mono_gc += item.costMonoGC;
  615. }
  616. s.costLuaGC = Math.Max(lua_gc, s.costLuaGC);
  617. s.costMonoGC = Math.Max(mono_gc, s.costMonoGC);
  618. b.Close();
  619. return s;
  620. }
  621. public static void DeleteFiles(string str)
  622. {
  623. DirectoryInfo fatherFolder = new DirectoryInfo(str);
  624. //删除当前文件夹内文件
  625. FileInfo[] files = fatherFolder.GetFiles();
  626. foreach (FileInfo file in files)
  627. {
  628. string fileName = file.Name;
  629. try
  630. {
  631. File.Delete(file.FullName);
  632. }
  633. catch (Exception ex)
  634. {
  635. Debug.LogError(ex);
  636. }
  637. }
  638. //递归删除子文件夹内文件
  639. foreach (DirectoryInfo childFolder in fatherFolder.GetDirectories())
  640. {
  641. DeleteFiles(childFolder.FullName);
  642. }
  643. Directory.Delete(str, true);
  644. }
  645. #endregion
  646. }
  647. }
  648. #endif