You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
12 KiB

  1. /*
  2. * Copyright 2011-2014 Formal Methods and Tools, University of Twente
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <errno.h> // for errno
  17. #include <string.h> // memset
  18. #include <stats.h>
  19. #include <sys/mman.h>
  20. #include <inttypes.h>
  21. #include <sylvan.h> // for nodes table
  22. #if SYLVAN_STATS
  23. #ifdef __ELF__
  24. __thread sylvan_stats_t sylvan_stats;
  25. #else
  26. pthread_key_t sylvan_stats_key;
  27. #endif
  28. #ifndef USE_HWLOC
  29. #define USE_HWLOC 0
  30. #endif
  31. #if USE_HWLOC
  32. #include <hwloc.h>
  33. static hwloc_topology_t topo;
  34. #endif
  35. VOID_TASK_0(sylvan_stats_reset_perthread)
  36. {
  37. #ifdef __ELF__
  38. for (int i=0; i<SYLVAN_COUNTER_COUNTER; i++) {
  39. sylvan_stats.counters[i] = 0;
  40. }
  41. for (int i=0; i<SYLVAN_TIMER_COUNTER; i++) {
  42. sylvan_stats.timers[i] = 0;
  43. }
  44. #else
  45. sylvan_stats_t *sylvan_stats = pthread_getspecific(sylvan_stats_key);
  46. if (sylvan_stats == NULL) {
  47. sylvan_stats = mmap(0, sizeof(sylvan_stats_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  48. if (sylvan_stats == (sylvan_stats_t *)-1) {
  49. fprintf(stderr, "sylvan_stats: Unable to allocate memory: %s!\n", strerror(errno));
  50. exit(1);
  51. }
  52. #if USE_HWLOC
  53. // Ensure the stats object is on our pu
  54. hwloc_obj_t pu = hwloc_get_obj_by_type(topo, HWLOC_OBJ_PU, LACE_WORKER_PU);
  55. hwloc_set_area_membind(topo, sylvan_stats, sizeof(sylvan_stats_t), pu->cpuset, HWLOC_MEMBIND_BIND, 0);
  56. #endif
  57. pthread_setspecific(sylvan_stats_key, sylvan_stats);
  58. }
  59. for (int i=0; i<SYLVAN_COUNTER_COUNTER; i++) {
  60. sylvan_stats->counters[i] = 0;
  61. }
  62. for (int i=0; i<SYLVAN_TIMER_COUNTER; i++) {
  63. sylvan_stats->timers[i] = 0;
  64. }
  65. #endif
  66. }
  67. VOID_TASK_IMPL_0(sylvan_stats_init)
  68. {
  69. #ifndef __ELF__
  70. pthread_key_create(&sylvan_stats_key, NULL);
  71. #endif
  72. #if USE_HWLOC
  73. hwloc_topology_init(&topo);
  74. hwloc_topology_load(topo);
  75. #endif
  76. TOGETHER(sylvan_stats_reset_perthread);
  77. }
  78. /**
  79. * Reset all counters (for statistics)
  80. */
  81. VOID_TASK_IMPL_0(sylvan_stats_reset)
  82. {
  83. TOGETHER(sylvan_stats_reset_perthread);
  84. }
  85. #define BLACK "\33[22;30m"
  86. #define GRAY "\33[01;30m"
  87. #define RED "\33[22;31m"
  88. #define LRED "\33[01;31m"
  89. #define GREEN "\33[22;32m"
  90. #define LGREEN "\33[01;32m"
  91. #define BLUE "\33[22;34m"
  92. #define LBLUE "\33[01;34m"
  93. #define BROWN "\33[22;33m"
  94. #define YELLOW "\33[01;33m"
  95. #define CYAN "\33[22;36m"
  96. #define LCYAN "\33[22;36m"
  97. #define MAGENTA "\33[22;35m"
  98. #define LMAGENTA "\33[01;35m"
  99. #define NC "\33[0m"
  100. #define BOLD "\33[1m"
  101. #define ULINE "\33[4m" //underline
  102. #define BLINK "\33[5m"
  103. #define INVERT "\33[7m"
  104. VOID_TASK_1(sylvan_stats_sum, sylvan_stats_t*, target)
  105. {
  106. #ifdef __ELF__
  107. for (int i=0; i<SYLVAN_COUNTER_COUNTER; i++) {
  108. __sync_fetch_and_add(&target->counters[i], sylvan_stats.counters[i]);
  109. }
  110. for (int i=0; i<SYLVAN_TIMER_COUNTER; i++) {
  111. __sync_fetch_and_add(&target->timers[i], sylvan_stats.timers[i]);
  112. }
  113. #else
  114. sylvan_stats_t *sylvan_stats = pthread_getspecific(sylvan_stats_key);
  115. if (sylvan_stats != NULL) {
  116. for (int i=0; i<SYLVAN_COUNTER_COUNTER; i++) {
  117. __sync_fetch_and_add(&target->counters[i], sylvan_stats->counters[i]);
  118. }
  119. for (int i=0; i<SYLVAN_TIMER_COUNTER; i++) {
  120. __sync_fetch_and_add(&target->timers[i], sylvan_stats->timers[i]);
  121. }
  122. }
  123. #endif
  124. }
  125. void
  126. sylvan_stats_report(FILE *target, int color)
  127. {
  128. #if !SYLVAN_STATS
  129. (void)target;
  130. (void)color;
  131. return;
  132. #else
  133. (void)color;
  134. sylvan_stats_t totals;
  135. memset(&totals, 0, sizeof(sylvan_stats_t));
  136. LACE_ME;
  137. TOGETHER(sylvan_stats_sum, &totals);
  138. // fix timers for MACH
  139. #ifdef __MACH__
  140. mach_timebase_info_data_t timebase;
  141. mach_timebase_info(&timebase);
  142. uint64_t c = timebase.numer/timebase.denom;
  143. for (int i=0;i<SYLVAN_TIMER_COUNTER;i++) totals.timers[i]*=c;
  144. #endif
  145. if (color) fprintf(target, LRED "*** " BOLD "Sylvan stats" NC LRED " ***" NC);
  146. else fprintf(target, "*** Sylvan stats ***");
  147. if (totals.counters[BDD_NODES_CREATED]) {
  148. if (color) fprintf(target, ULINE LBLUE);
  149. fprintf(target, "\nBDD operations count (cache reuse, cache put)\n");
  150. if (color) fprintf(target, NC);
  151. if (totals.counters[BDD_ITE]) fprintf(target, "ITE: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_ITE], totals.counters[BDD_ITE_CACHED], totals.counters[BDD_ITE_CACHEDPUT]);
  152. if (totals.counters[BDD_AND]) fprintf(target, "AND: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_AND], totals.counters[BDD_AND_CACHED], totals.counters[BDD_AND_CACHEDPUT]);
  153. if (totals.counters[BDD_XOR]) fprintf(target, "XOR: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_XOR], totals.counters[BDD_XOR_CACHED], totals.counters[BDD_XOR_CACHEDPUT]);
  154. if (totals.counters[BDD_EXISTS]) fprintf(target, "Exists: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_EXISTS], totals.counters[BDD_EXISTS_CACHED], totals.counters[BDD_EXISTS_CACHEDPUT]);
  155. if (totals.counters[BDD_AND_EXISTS]) fprintf(target, "AndExists: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_AND_EXISTS], totals.counters[BDD_AND_EXISTS_CACHED], totals.counters[BDD_AND_EXISTS_CACHEDPUT]);
  156. if (totals.counters[BDD_RELNEXT]) fprintf(target, "RelNext: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_RELNEXT], totals.counters[BDD_RELNEXT_CACHED], totals.counters[BDD_RELNEXT_CACHEDPUT]);
  157. if (totals.counters[BDD_RELPREV]) fprintf(target, "RelPrev: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_RELPREV], totals.counters[BDD_RELPREV_CACHED], totals.counters[BDD_RELPREV_CACHEDPUT]);
  158. if (totals.counters[BDD_CLOSURE]) fprintf(target, "Closure: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_CLOSURE], totals.counters[BDD_CLOSURE_CACHED], totals.counters[BDD_CLOSURE_CACHEDPUT]);
  159. if (totals.counters[BDD_COMPOSE]) fprintf(target, "Compose: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_COMPOSE], totals.counters[BDD_COMPOSE_CACHED], totals.counters[BDD_COMPOSE_CACHEDPUT]);
  160. if (totals.counters[BDD_RESTRICT]) fprintf(target, "Restrict: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_RESTRICT], totals.counters[BDD_RESTRICT_CACHED], totals.counters[BDD_RESTRICT_CACHEDPUT]);
  161. if (totals.counters[BDD_CONSTRAIN]) fprintf(target, "Constrain: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_CONSTRAIN], totals.counters[BDD_CONSTRAIN_CACHED], totals.counters[BDD_CONSTRAIN_CACHEDPUT]);
  162. if (totals.counters[BDD_SUPPORT]) fprintf(target, "Support: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_SUPPORT], totals.counters[BDD_SUPPORT_CACHED], totals.counters[BDD_SUPPORT_CACHEDPUT]);
  163. if (totals.counters[BDD_SATCOUNT]) fprintf(target, "SatCount: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_SATCOUNT], totals.counters[BDD_SATCOUNT_CACHED], totals.counters[BDD_SATCOUNT_CACHEDPUT]);
  164. if (totals.counters[BDD_PATHCOUNT]) fprintf(target, "PathCount: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_PATHCOUNT], totals.counters[BDD_PATHCOUNT_CACHED], totals.counters[BDD_PATHCOUNT_CACHEDPUT]);
  165. if (totals.counters[BDD_ISBDD]) fprintf(target, "IsBDD: %'"PRIu64 " (%'"PRIu64", %'"PRIu64 ")\n", totals.counters[BDD_ISBDD], totals.counters[BDD_ISBDD_CACHED], totals.counters[BDD_ISBDD_CACHEDPUT]);
  166. fprintf(target, "BDD Nodes created: %'"PRIu64"\n", totals.counters[BDD_NODES_CREATED]);
  167. fprintf(target, "BDD Nodes reused: %'"PRIu64"\n", totals.counters[BDD_NODES_REUSED]);
  168. }
  169. if (totals.counters[LDD_NODES_CREATED]) {
  170. if (color) fprintf(target, ULINE LBLUE);
  171. fprintf(target, "\nLDD operations count (cache reuse, cache put)\n");
  172. if (color) fprintf(target, NC);
  173. if (totals.counters[LDD_UNION]) fprintf(target, "Union: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_UNION], totals.counters[LDD_UNION_CACHED], totals.counters[LDD_UNION_CACHEDPUT]);
  174. if (totals.counters[LDD_MINUS]) fprintf(target, "Minus: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_MINUS], totals.counters[LDD_MINUS_CACHED], totals.counters[LDD_MINUS_CACHEDPUT]);
  175. if (totals.counters[LDD_INTERSECT]) fprintf(target, "Intersect: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_INTERSECT], totals.counters[LDD_INTERSECT_CACHED], totals.counters[LDD_INTERSECT_CACHEDPUT]);
  176. if (totals.counters[LDD_RELPROD]) fprintf(target, "RelProd: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_RELPROD], totals.counters[LDD_RELPROD_CACHED], totals.counters[LDD_RELPROD_CACHEDPUT]);
  177. if (totals.counters[LDD_RELPREV]) fprintf(target, "RelPrev: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_RELPREV], totals.counters[LDD_RELPREV_CACHED], totals.counters[LDD_RELPREV_CACHEDPUT]);
  178. if (totals.counters[LDD_PROJECT]) fprintf(target, "Project: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_PROJECT], totals.counters[LDD_PROJECT_CACHED], totals.counters[LDD_PROJECT_CACHEDPUT]);
  179. if (totals.counters[LDD_JOIN]) fprintf(target, "Join: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_JOIN], totals.counters[LDD_JOIN_CACHED], totals.counters[LDD_JOIN_CACHEDPUT]);
  180. if (totals.counters[LDD_MATCH]) fprintf(target, "Match: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_MATCH], totals.counters[LDD_MATCH_CACHED], totals.counters[LDD_MATCH_CACHEDPUT]);
  181. if (totals.counters[LDD_SATCOUNT]) fprintf(target, "SatCount: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_SATCOUNT], totals.counters[LDD_SATCOUNT_CACHED], totals.counters[LDD_SATCOUNT_CACHEDPUT]);
  182. if (totals.counters[LDD_SATCOUNTL]) fprintf(target, "SatCountL: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_SATCOUNTL], totals.counters[LDD_SATCOUNTL_CACHED], totals.counters[LDD_SATCOUNTL_CACHEDPUT]);
  183. if (totals.counters[LDD_ZIP]) fprintf(target, "Zip: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_ZIP], totals.counters[LDD_ZIP_CACHED], totals.counters[LDD_ZIP_CACHEDPUT]);
  184. if (totals.counters[LDD_RELPROD_UNION]) fprintf(target, "RelProdUnion: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_RELPROD_UNION], totals.counters[LDD_RELPROD_UNION_CACHED], totals.counters[LDD_RELPROD_UNION_CACHEDPUT]);
  185. if (totals.counters[LDD_PROJECT_MINUS]) fprintf(target, "ProjectMinus: %'"PRIu64 " (%'"PRIu64", %"PRIu64")\n", totals.counters[LDD_PROJECT_MINUS], totals.counters[LDD_PROJECT_MINUS_CACHED], totals.counters[LDD_PROJECT_MINUS_CACHEDPUT]);
  186. fprintf(target, "LDD Nodes created: %'"PRIu64"\n", totals.counters[LDD_NODES_CREATED]);
  187. fprintf(target, "LDD Nodes reused: %'"PRIu64"\n", totals.counters[LDD_NODES_REUSED]);
  188. }
  189. if (color) fprintf(target, ULINE LBLUE);
  190. fprintf(target, "\nGarbage collection\n");
  191. if (color) fprintf(target, NC);
  192. fprintf(target, "Number of GC executions: %'"PRIu64"\n", totals.counters[SYLVAN_GC_COUNT]);
  193. fprintf(target, "Total time spent: %'.6Lf sec.\n", (long double)totals.timers[SYLVAN_GC]/1000000000);
  194. if (color) fprintf(target, ULINE LBLUE);
  195. fprintf(target, "\nTables\n");
  196. if (color) fprintf(target, NC);
  197. fprintf(target, "Unique nodes table: %'zu of %'zu buckets filled.\n", llmsset_count_marked(nodes), llmsset_get_size(nodes));
  198. fprintf(target, "Operation cache: %'zu of %'zu buckets filled.\n", cache_getused(), cache_getsize());
  199. if (color) fprintf(target, ULINE LBLUE);
  200. fprintf(target, "\nUnique table\n");
  201. if (color) fprintf(target, NC);
  202. fprintf(target, "Number of lookup iterations: %'"PRIu64"\n", totals.counters[LLMSSET_LOOKUP]);
  203. #endif
  204. }
  205. #else
  206. VOID_TASK_IMPL_0(sylvan_stats_init)
  207. {
  208. }
  209. VOID_TASK_IMPL_0(sylvan_stats_reset)
  210. {
  211. }
  212. void
  213. sylvan_stats_report(FILE* target, int color)
  214. {
  215. (void)target;
  216. (void)color;
  217. }
  218. #endif