UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
syms_dev.c
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#ifndef SYMS_DEV_C
4#define SYMS_DEV_C
5
7// NOTE(allen): Dev String Functions
8
9#if SYMS_ENABLE_DEV_STRING
10
13 // TODO(allen): optimize with initial guess allocation technique
15 va_copy(args2, args);
16 SYMS_U32 needed_bytes = vsnprintf(0, 0, fmt, args) + 1;
17 SYMS_String8 result = {0};
18 result.str = syms_push_array(arena, SYMS_U8, needed_bytes);
19 result.size = vsnprintf((char*)result.str, needed_bytes, fmt, args2);
20 result.str[result.size] = 0;
22 return(result);
23}
24
26syms_push_stringf__dev(SYMS_Arena *arena, char *fmt, ...){
28 va_start(args, fmt);
29 SYMS_String8 result = syms_push_stringfv__dev(arena, fmt, args);
30 va_end(args);
31 return(result);
32}
33
34SYMS_API void
36 SYMS_String8 string = syms_push_stringfv__dev(arena, fmt, args);
37 syms_string_list_push(arena, list, string);
38}
39
40SYMS_API void
43 va_start(args, fmt);
45 va_end(args);
46}
47
48#endif
49
51// NOTE(allen): Dev Logging Functions
52
53#if SYMS_ENABLE_DEV_LOG
54
57
58SYMS_API void
62}
63
64
65// states: 0 = not opened; 1 = opened disabled; 2 = opened enabled
66// transition table: (0/2,enabled) -> 2; (0/2,disabled) -> 1; (1,*) -> 1
67// new states are treated as a stack and are "popped" by close
69
73 SYMS_B32 new_is_enabled = (enabled && prev_state != 1);
76 return(prev_state);
77}
78
79SYMS_API void
82}
83
86 SYMS_B32 result = (syms_log_state__dev == 2);
87 return(result);
88}
89
94 SYMS_B32 enable = ((filter_features == 0 || (filter_features & features) != 0) &&
95 (uid == 0 || filter_uid == 0 || uid == filter_uid));
98 if (is_enabled){
100
101 //- features
103 for (SYMS_U32 i = 0; i < 1; i += 1){
104 SYMS_U32 bit = (1 << i);
105 if ((features & bit) != 0){
107 switch (bit){
108 case SYMS_LogFeature_LineTable: feature_str = syms_str8_lit("line_table"); break;
109 case SYMS_LogFeature_DwarfUnitRanges: feature_str = syms_str8_lit("dwarf_unit_ranges"); break;
110 case SYMS_LogFeature_DwarfTags: feature_str = syms_str8_lit("dwarf_tags"); break;
111 case SYMS_LogFeature_DwarfUnwind: feature_str = syms_str8_lit("dwarf_unwind"); break;
112 case SYMS_LogFeature_DwarfCFILookup: feature_str = syms_str8_lit("dwarf_cfi_lookup"); break;
113 case SYMS_LogFeature_DwarfCFIDecode: feature_str = syms_str8_lit("dwarf_cfi_decode"); break;
114 case SYMS_LogFeature_DwarfCFIApply: feature_str = syms_str8_lit("dwarf_cfi_apply"); break;
115 case SYMS_LogFeature_PEEpilog: feature_str = syms_str8_lit("pe_epilog"); break;
116 }
118 }
119 }
120 SYMS_String8 features = syms_str8_lit("misc");
121 if (features_list.first != 0){
122 SYMS_StringJoin join = {0};
123 join.sep = syms_str8_lit(" ");
124 features = syms_string_list_join(scratch.arena, &features_list, &join);
125 }
126
127 //- append block
128 SYMS_String8 string = syms_push_stringf__dev(scratch.arena, "logging [%.*s %" SYMS_PRIu64 "]\n",
129 syms_expand_string(features), uid);
130 SYMS_LOG_RAW_APPEND(string);
132 }
133 return(result);
134}
135
136SYMS_API void
137syms_logfv__dev(char *fmt, va_list args){
139 if (is_enabled){
141 SYMS_String8 string = syms_push_stringfv__dev(scratch.arena, fmt, args);
142 SYMS_LOG_RAW_APPEND(string);
144 }
145}
146
147SYMS_API void
148syms_logf__dev(char *fmt, ...){
150 va_start(args, fmt);
151 syms_logfv__dev(fmt, args);
152 va_end(args);
153}
154
155#else
156
157#define syms_log_set_filter__dev(...)
158#define syms_log_open__dev(...)
159#define syms_log_is_enabled__dev(...) syms_false
160#define syms_log_open_annotated__dev(...) 0
161#define syms_logfv__dev(...)
162#define syms_logf__dev(...)
163
164#endif
165
167// NOTE(allen): Dev Profiling Functions
168
169#if SYMS_ENABLE_DEV_PROFILE
170
172
173SYMS_API void
177}
178
179SYMS_API void
183}
184
185SYMS_API void
188}
189
192 // check for an equipped profiler state
193 SYMS_LOCAL SYMS_U64 dummy[2];
194 SYMS_U64 *result = dummy;
196 if (prof_state != 0){
197
198 // check the current chain; extend if necessary
199 SYMS_ProfChain *chain = prof_state->current;
200 if (chain == 0 || chain->ptr + 16 > (SYMS_U8*)chain + SYMS_PROF_BLOCK_SIZE){
201 chain = prof_state->free;
202 if (chain != 0){
204 }
205 else{
207 }
208 SYMS_QueuePush(prof_state->first, prof_state->current, chain);
209 chain->ptr = (SYMS_U8*)(chain + 1);
210 }
211
212 // get result pointer and increment
213 result = (SYMS_U64*)chain->ptr;
214 chain->ptr += 16;
215 }
216 return(result);
217}
218
219SYMS_API void
222 if (prof_state != 0 && sub_state != 0){
223 if (sub_state->first != 0){
224 if (prof_state->current == 0){
225 prof_state->first = sub_state->first;
226 }
227 else{
228 prof_state->current->next = sub_state->first;
229 }
230 prof_state->current = sub_state->current;
231 }
232 if (sub_state->free != 0){
233 if (prof_state->free != 0){
235 for (; last_chain->next != 0; last_chain = last_chain->next);
236 last_chain->next = prof_state->free;
237 }
238 prof_state->free = sub_state->free;
239 }
241 }
242}
243
248 if (result.state != 0){
250 for (SYMS_ProfChain *chain = result.state->first;
251 chain != 0;
252 chain = chain->next, chain_count += 1);
253
255 SYMS_U8 *str = syms_push_array(arena, SYMS_U8, size);
256 SYMS_U8 *ptr = str;
257 for (SYMS_ProfChain *chain = result.state->first;
258 chain != 0;
259 chain = chain->next){
260 SYMS_U64 chain_size = (SYMS_U64)(chain->ptr - (SYMS_U8*)(chain + 1));
261 syms_memmove(ptr, (chain + 1), chain_size);
262 ptr += chain_size;
263 }
264 result.data = syms_str8_range(str, ptr);
265 }
266 return(result);
267}
268
269SYMS_API void
271 if (lock.state != 0){
272 if (lock.state->current != 0){
273 lock.state->current->next = lock.state->free;
274 lock.state->free = lock.state->first;
275 }
276 lock.state->first = 0;
277 lock.state->current = 0;
278 }
279}
280
281SYMS_API void
284}
285
288 SYMS_ProfTree result = {0};
289
290 if (data.size > 0){
291 // bucket setup
292 result.bucket_count = 16381;
294
295 // setup root
296 result.root = syms_push_array_zero(arena, SYMS_ProfTreeNode, 1);
297 {
298 SYMS_String8 key = syms_str8_lit("<root>");
299 SYMS_U64 hash = syms_hash_djb2(key);
300 SYMS_U64 index = hash%result.bucket_count;
301 SYMS_StackPush(result.buckets[index], result.root);
302 result.count += 1;
303 result.root->hash = hash;
304 result.root->key = key;
305 }
306
307 // tree walk
309 SYMS_U64 depth = 1;
310 result.height = 1;
311
312 // parse loop
313 SYMS_U64 rounded_size = data.size&~15;
314 SYMS_U64 *ptr = (SYMS_U64*)data.str;
315 SYMS_U64 *opl = ptr + (rounded_size/8);
316 for (;ptr < opl; ptr += 2){
317 if (*ptr != 0){
318 // read begin values
319 char *label = (char*)(ptr[0]);
320 SYMS_U64 time_min = ptr[1];
321
322 // parse key
326 SYMS_U64 index = hash%result.bucket_count;
327
328 // existing tree node?
330 for (SYMS_ProfTreeNode *bucket_node = result.buckets[index];
331 bucket_node != 0;
332 bucket_node = bucket_node->next){
333 if (bucket_node->hash == hash &&
334 syms_string_match(bucket_node->key, key, 0) &&
335 bucket_node->tree_parent == tree_walk_ptr){
337 break;
338 }
339 }
340
341 // new tree node?
342 if (tree_node == 0){
344
345 // insert in hash table
346 SYMS_StackPush(result.buckets[index], tree_node);
347 result.count += 1;
348 tree_node->hash = hash;
349 tree_node->key = key;
350
351 // insert in tree
352 SYMS_QueuePush_N(tree_walk_ptr->tree_first, tree_walk_ptr->tree_last, tree_node, tree_next);
353 tree_node->tree_parent = tree_walk_ptr;
354 }
355
356 // save time_min
357 SYMS_ASSERT(tree_node->time_min == 0);
358 tree_node->time_min = time_min;
359
360 // push stack
362 depth += 1;
363 result.height = SYMS_MAX(depth, result.height);
364
365 // track key max
366 result.max_key_size = SYMS_MAX(result.max_key_size, key.size);
367 }
368 else{
369 // never "handle" the parent!
370 if (tree_walk_ptr->tree_parent == 0){
371 tree_walk_ptr = 0;
372 break;
373 }
374
375 // read end values
376 SYMS_U64 time_max = ptr[1];
377
378 // update tree node
379 tree_walk_ptr->count += 1;
380 tree_walk_ptr->total_time += time_max - tree_walk_ptr->time_min;
381 tree_walk_ptr->time_min = 0;
382
383 // pop the stack
384 tree_walk_ptr = tree_walk_ptr->tree_parent;
385 depth -= 1;
386 }
387 }
388
389 // (stack == 0) -> extra SYMS_ProfEnd
390 // (stack != 0 && stack != result.root) -> unclosed SYMS_ProfBegin
391 SYMS_ASSERT(tree_walk_ptr == result.root);
392 }
393
394 return(result);
395}
396
397SYMS_API void
399 // sort this layer
400 if (root->tree_first != 0){
402
403 // count children
404 SYMS_U64 count = 0;
405 for (SYMS_ProfTreeNode *node = root->tree_first;
406 node != 0;
407 node = node->tree_next, count += 1);
408
409 // allocate sortable buffer
411 {
412 SYMS_ProfTreeNode **ptr = array;
413 for (SYMS_ProfTreeNode *node = root->tree_first;
414 node != 0;
415 node = node->tree_next, ptr += 1){
416 *ptr = node;
417 }
418 }
419
420 // sort the array
422
423 // reconstruct the linked list
424 {
425 SYMS_ProfTreeNode **ptr = array;
426 root->tree_first = *ptr;
427 for (SYMS_U64 i = 1; i < count; i += 1, ptr += 1){
428 ptr[0]->tree_next = ptr[1];
429 }
430 ptr[0]->tree_next = 0;
431 root->tree_last = *ptr;
432 }
433
435 }
436
437 // recurse
438 for (SYMS_ProfTreeNode *node = root->tree_first;
439 node != 0;
440 node = node->tree_next){
442 }
443}
444
445SYMS_API void
447 if (count > 1){
448 SYMS_U64 last = count - 1;
449
450 // swap
451 SYMS_U64 mid = count/2;
453
454 // partition
455 SYMS_U64 key = array[last]->total_time;
456 SYMS_U64 j = 0;
457 for (SYMS_U64 i = 0; i < last; i += 1){
458 if (array[i]->total_time > key){
459 if (j != i){
461 }
462 j += 1;
463 }
464 }
465
467
468 // recurse
469 SYMS_U64 pivot = j;
472 }
473}
474
475SYMS_API void
477 SYMS_U64 align = tree->max_key_size + tree->height;
478 syms_prof_stringize_tree__rec__dev(arena, tree->root, out, align, 0);
479}
480
481#if SYMS_ENABLE_DEV_STRING
482
483SYMS_API void
486 SYMS_LOCAL const char spaces[] = " ";
487 syms_string_list_pushf__dev(arena, out, "%.*s%-*.*s %12lluus [%8llu]\n",
488 (int)indent, spaces,
489 (int)(align - indent), syms_expand_string(node->key),
490 node->total_time, node->count);
491 for (SYMS_ProfTreeNode *child = node->tree_first;
492 child != 0;
493 child = child->tree_next){
495 }
496}
497
498SYMS_API void
505}
506
507#endif //SYMS_ENABLE_DEV_STRING
508
509#else
510
511#define syms_prof_equip_thread__dev(...)
512#define syms_prof_equip_thread_auto__dev(...)
513#define syms_prof_unequip_thread__dev(...)
514#define syms_prof_push__dev(...)
515#define syms_prof_paste__dev(...)
516
517#define syms_prof_lock__dev(...) {}
518#define syms_prof_clear__dev(...)
519#define syms_prof_unlock__dev(l) ((void)l)
520
521#define syms_prof_tree__dev(...)
522#define syms_prof_tree_sort_in_place__dev(...)
523#define syms_prof_tree_sort_pointer_array__dev(...)
524
525#if SYMS_ENABLE_DEV_STRING
526# define syms_prof_stringize_tree__dev(...)
527# define syms_prof_stringize_tree__rec__dev(...)
528# define syms_prof_stringize_basic__dev(...)
529#endif
530
531#endif //SYMS_ENABLE_DEV_PROFILE
532
533#endif //SYMS_DEV_C
OODEFFUNC typedef const char int const char * fmt
Definition oodle2.h:678
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
int bit(int a, int b)
Definition DebugDraw.cpp:33
args
Definition TestServer.py:519
Definition syms_base.h:402
Definition syms_dev.h:39
SYMS_U8 * ptr
Definition syms_dev.h:41
struct SYMS_ProfChain * next
Definition syms_dev.h:40
Definition syms_dev.h:50
SYMS_String8 data
Definition syms_dev.h:52
SYMS_ProfState * state
Definition syms_dev.h:51
Definition syms_dev.h:44
SYMS_ProfChain * first
Definition syms_dev.h:45
Definition syms_dev.h:55
SYMS_String8 key
Definition syms_dev.h:59
struct SYMS_ProfTreeNode * tree_next
Definition syms_dev.h:68
struct SYMS_ProfTreeNode * tree_first
Definition syms_dev.h:66
SYMS_U64 hash
Definition syms_dev.h:58
struct SYMS_ProfTreeNode * tree_last
Definition syms_dev.h:67
SYMS_U64 total_time
Definition syms_dev.h:63
SYMS_U64 count
Definition syms_dev.h:62
Definition syms_dev.h:75
SYMS_U64 max_key_size
Definition syms_dev.h:80
SYMS_ProfTreeNode ** buckets
Definition syms_dev.h:77
SYMS_U64 count
Definition syms_dev.h:79
SYMS_ProfTreeNode * root
Definition syms_dev.h:83
SYMS_U64 height
Definition syms_dev.h:84
SYMS_U64 bucket_count
Definition syms_dev.h:78
Definition syms_base.h:306
Definition syms_base.h:296
SYMS_U8 * str
Definition syms_base.h:297
SYMS_U64 size
Definition syms_base.h:298
Definition syms_base.h:325
SYMS_String8 sep
Definition syms_base.h:327
SYMS_API SYMS_String8 syms_string_list_join(SYMS_Arena *arena, SYMS_String8List *list, SYMS_StringJoin *join_ptr)
Definition syms_base.c:315
SYMS_API SYMS_String8 syms_str8_range(SYMS_U8 *first, SYMS_U8 *opl)
Definition syms_base.c:184
SYMS_API SYMS_U64 syms_hash_djb2_continue(SYMS_String8 string, SYMS_U64 intermediate_hash)
Definition syms_base.c:46
SYMS_API SYMS_ArenaTemp syms_get_scratch(SYMS_Arena **conflicts, SYMS_U64 conflict_count)
Definition syms_base.c:694
SYMS_API SYMS_String8 syms_str8_cstring(char *str)
Definition syms_base.c:175
SYMS_API SYMS_B32 syms_string_match(SYMS_String8 a, SYMS_String8 b, SYMS_StringMatchFlags flags)
Definition syms_base.c:210
SYMS_API SYMS_U64 syms_hash_djb2(SYMS_String8 string)
Definition syms_base.c:40
SYMS_API void syms_string_list_push(SYMS_Arena *arena, SYMS_String8List *list, SYMS_String8 string)
Definition syms_base.c:282
#define SYMS_QueuePush_N(f, l, n, next)
Definition syms_base.h:210
#define SYMS_Swap(T, a, b)
Definition syms_base.h:190
#define SYMS_StackPush(f, n)
Definition syms_base.h:227
#define syms_push_array(a, T, c)
Definition syms_base.h:561
#define syms_memzero_struct(s)
Definition syms_base.h:161
#define SYMS_LOCAL
Definition syms_base.h:43
#define syms_expand_string(s)
Definition syms_base.h:484
#define SYMS_API
Definition syms_base.h:29
#define SYMS_ASSERT(x)
Definition syms_base.h:125
SYMS_S32 SYMS_B32
Definition syms_base.h:99
#define SYMS_StackPop(f)
Definition syms_base.h:228
#define syms_push_array_zero(a, T, c)
Definition syms_base.h:564
#define SYMS_MAX(a, b)
Definition syms_base.h:180
#define syms_str8_lit(s)
Definition syms_base.h:483
#define SYMS_QueuePush(f, l, n)
Definition syms_base.h:220
#define syms_release_scratch
Definition syms_base.h:567
#define SYMS_GLOBAL
Definition syms_base.h:42
uint32_t SYMS_U32
Definition syms_crt_overrides.h:38
#define SYMS_PRIu64
Definition syms_crt_overrides.h:41
uint64_t SYMS_U64
Definition syms_crt_overrides.h:39
#define syms_memmove
Definition syms_crt_overrides.h:65
#define SYMS_U64
Definition syms_crt_overrides.h:54
uint8_t SYMS_U8
Definition syms_crt_overrides.h:36
#define SYMS_Arena
Definition syms_default_arena.h:61
#define syms_log_set_filter__dev(...)
Definition syms_dev.c:157
#define syms_log_open_annotated__dev(...)
Definition syms_dev.c:160
#define syms_prof_tree_sort_in_place__dev(...)
Definition syms_dev.c:522
#define syms_prof_lock__dev(...)
Definition syms_dev.c:517
#define syms_prof_paste__dev(...)
Definition syms_dev.c:515
#define syms_prof_tree_sort_pointer_array__dev(...)
Definition syms_dev.c:523
#define syms_prof_equip_thread__dev(...)
Definition syms_dev.c:511
#define syms_prof_unlock__dev(l)
Definition syms_dev.c:519
#define syms_prof_unequip_thread__dev(...)
Definition syms_dev.c:513
#define syms_log_open__dev(...)
Definition syms_dev.c:158
#define syms_prof_tree__dev(...)
Definition syms_dev.c:521
#define syms_prof_equip_thread_auto__dev(...)
Definition syms_dev.c:512
#define syms_log_is_enabled__dev(...)
Definition syms_dev.c:159
#define syms_logfv__dev(...)
Definition syms_dev.c:161
#define syms_prof_clear__dev(...)
Definition syms_dev.c:518
#define syms_logf__dev(...)
Definition syms_dev.c:162
#define syms_prof_push__dev(...)
Definition syms_dev.c:514
SYMS_U32 SYMS_LogFeatures
Definition syms_dev.h:18
@ SYMS_LogFeature_DwarfCFIApply
Definition syms_dev.h:26
@ SYMS_LogFeature_DwarfTags
Definition syms_dev.h:22
@ SYMS_LogFeature_PEEpilog
Definition syms_dev.h:27
@ SYMS_LogFeature_LineTable
Definition syms_dev.h:20
@ SYMS_LogFeature_DwarfUnwind
Definition syms_dev.h:23
@ SYMS_LogFeature_DwarfCFILookup
Definition syms_dev.h:24
@ SYMS_LogFeature_DwarfCFIDecode
Definition syms_dev.h:25
@ SYMS_LogFeature_DwarfUnitRanges
Definition syms_dev.h:21