avevo bisogno di qualcosa di simile per un caso in cui non ho avuto alcun attrezzo di profilazione, ma volevo contare quanti thread si trovavano all'interno di un particolare blocco di codice e la quantità di tempo (tick) spesi in quel blocco di codice da ciascun thread, in questo caso ogni blocco aveva bisogno di una variabile statica univoca accessibile a tutti i thread, e avevo bisogno di riferirmi in seguito a tale variabile su incr (ho usato un'API di registrazione piuttosto che printf nel codice reale, ma funziona anche così). In un primo momento ho pensato che era molto intelligente nel modo seguente:
#define PROF_START { \
static volatile int entry_count##___FUNCTION__##__LINE__ = 0; int *ptc = &entry_count##___FUNCTION__##__LINE__; \
clock_t start, end; \
start = times(0); \
(*ptc)++;
Ma poi ho capito che questo è solo stupido e il compilatore C si limiterà a fare questo per voi, a patto che ogni dichiarazione "statico" è il suo blocco:
#include <stdio.h>
#include <sys/times.h>
#define PROF_START { \
static int entry_count = 0; \
clock_t start, end; \
start = times(0); \
entry_count++;
#define PROF_END \
end = times(0); \
printf("[%s:%d] TIMER: %ld:%d\n" , __FUNCTION__, __LINE__, end-start, entry_count); \
entry_count--; \
}
Nota le parentesi aperta/chiusa in ciascuna macro. Questo non è strettamente thread-safe, ma per i miei scopi di profilazione potrei supporre che le operazioni di incr e decr fossero atomiche. Ecco un esempio di ricorsione che utilizza le macro
#define ITEM_COUNT 5
struct node {
int data;
struct node *next;
};
revsort(struct node **head)
{
struct node *current = *head;
struct node *next_item;
while (current->next)
{
PROF_START
next_item = current->next;
current->next = next_item->next;
next_item->next = *head;
*head = next_item;
PROF_END
}
}
rrevsort(struct node **head)
{
struct node *current = *head;
struct node *next_item = current->next;
PROF_START
current->next = 0;
if (next_item)
{
*head = next_item;
rrevsort(head);
next_item->next = current;
}
PROF_END
}
printnode(struct node *head)
{
if (head)
{
printf("%d ", head->data);
printnode(head->next);
}
else
printf("\n");
}
main()
{
struct node node_list[ITEM_COUNT];
struct node *head = &node_list[0];
int i;
for (i=0; i < ITEM_COUNT - 1; i++)
{
PROF_START
node_list[i].data = i;
node_list[i].next = &node_list[i+1];
PROF_END
}
node_list[i].data = i;
node_list[i].next = 0;
printf("before\n");
printnode(head);
revsort(&head);
printf("after\n");
printnode(head);
rrevsort(&head);
printf("before\n");
printnode(head);
}
suggerimento Extra, il programma di cui sopra è una domanda comune intervista. Estratto da "nm -A":
macro:0804a034 b entry_count.1715
macro:0804a030 b entry_count.1739
macro:0804a028 b entry_count.1768
macro:0804a02c b entry_count.1775
fonte
2012-05-03 02:35:18
Sicuramente vuoi dire nomi di variabili univoci, piuttosto che casuali? –
Sono un po 'confuso su come sarebbe utile. Il programmatore può quindi utilizzare in seguito i riferimenti my_variable_ *? getCurrentTime() ha qualche effetto collaterale utile? – SingleNegationElimination