Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: third_party/grpc/src/core/profiling/basic_timers.c

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34 #include <grpc/support/port_platform.h>
35
36 #ifdef GRPC_BASIC_PROFILER
37
38 #include "src/core/profiling/timers.h"
39
40 #include <grpc/support/alloc.h>
41 #include <grpc/support/log.h>
42 #include <grpc/support/time.h>
43 #include <grpc/support/sync.h>
44 #include <grpc/support/thd.h>
45 #include <stdio.h>
46
47 typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
48
49 typedef struct gpr_timer_entry {
50 gpr_timespec tm;
51 const char *tagstr;
52 const char *file;
53 short line;
54 char type;
55 uint8_t important;
56 int thd;
57 } gpr_timer_entry;
58
59 #define MAX_COUNT 1000000
60
61 typedef struct gpr_timer_log {
62 size_t num_entries;
63 struct gpr_timer_log *next;
64 struct gpr_timer_log *prev;
65 gpr_timer_entry log[MAX_COUNT];
66 } gpr_timer_log;
67
68 typedef struct gpr_timer_log_list {
69 gpr_timer_log *head;
70 /* valid iff head!=NULL */
71 gpr_timer_log *tail;
72 } gpr_timer_log_list;
73
74 static __thread gpr_timer_log *g_thread_log;
75 static gpr_once g_once_init = GPR_ONCE_INIT;
76 static FILE *output_file;
77 static const char *output_filename = "latency_trace.txt";
78 static pthread_mutex_t g_mu;
79 static pthread_cond_t g_cv;
80 static gpr_timer_log_list g_in_progress_logs;
81 static gpr_timer_log_list g_done_logs;
82 static int g_shutdown;
83 static gpr_thd_id g_writing_thread;
84 static __thread int g_thread_id;
85 static int g_next_thread_id;
86
87 static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) {
88 if (list->head == NULL) {
89 list->head = list->tail = log;
90 log->next = log->prev = NULL;
91 return 1;
92 } else {
93 log->prev = list->tail;
94 log->next = NULL;
95 list->tail->next = log;
96 list->tail = log;
97 return 0;
98 }
99 }
100
101 static gpr_timer_log *timer_log_pop_front(gpr_timer_log_list *list) {
102 gpr_timer_log *out = list->head;
103 if (out != NULL) {
104 list->head = out->next;
105 if (list->head != NULL) {
106 list->head->prev = NULL;
107 } else {
108 list->tail = NULL;
109 }
110 }
111 return out;
112 }
113
114 static void timer_log_remove(gpr_timer_log_list *list, gpr_timer_log *log) {
115 if (log->prev == NULL) {
116 list->head = log->next;
117 if (list->head != NULL) {
118 list->head->prev = NULL;
119 }
120 } else {
121 log->prev->next = log->next;
122 }
123 if (log->next == NULL) {
124 list->tail = log->prev;
125 if (list->tail != NULL) {
126 list->tail->next = NULL;
127 }
128 } else {
129 log->next->prev = log->prev;
130 }
131 }
132
133 static void write_log(gpr_timer_log *log) {
134 size_t i;
135 if (output_file == NULL) {
136 output_file = fopen(output_filename, "w");
137 }
138 for (i = 0; i < log->num_entries; i++) {
139 gpr_timer_entry *entry = &(log->log[i]);
140 if (gpr_time_cmp(entry->tm, gpr_time_0(entry->tm.clock_type)) < 0) {
141 entry->tm = gpr_time_0(entry->tm.clock_type);
142 }
143 fprintf(output_file,
144 "{\"t\": %lld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
145 "\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n",
146 (long long)entry->tm.tv_sec, (int)entry->tm.tv_nsec, entry->thd,
147 entry->type, entry->tagstr, entry->file, entry->line,
148 entry->important);
149 }
150 }
151
152 static void writing_thread(void *unused) {
153 gpr_timer_log *log;
154 pthread_mutex_lock(&g_mu);
155 for (;;) {
156 while ((log = timer_log_pop_front(&g_done_logs)) == NULL && !g_shutdown) {
157 pthread_cond_wait(&g_cv, &g_mu);
158 }
159 if (log != NULL) {
160 pthread_mutex_unlock(&g_mu);
161 write_log(log);
162 free(log);
163 pthread_mutex_lock(&g_mu);
164 }
165 if (g_shutdown) {
166 pthread_mutex_unlock(&g_mu);
167 return;
168 }
169 }
170 }
171
172 static void flush_logs(gpr_timer_log_list *list) {
173 gpr_timer_log *log;
174 while ((log = timer_log_pop_front(list)) != NULL) {
175 write_log(log);
176 free(log);
177 }
178 }
179
180 static void finish_writing() {
181 pthread_mutex_lock(&g_mu);
182 g_shutdown = 1;
183 pthread_cond_signal(&g_cv);
184 pthread_mutex_unlock(&g_mu);
185 gpr_thd_join(g_writing_thread);
186
187 gpr_log(GPR_INFO, "flushing logs");
188
189 pthread_mutex_lock(&g_mu);
190 flush_logs(&g_done_logs);
191 flush_logs(&g_in_progress_logs);
192 pthread_mutex_unlock(&g_mu);
193
194 if (output_file) {
195 fclose(output_file);
196 }
197 }
198
199 void gpr_timers_set_log_filename(const char *filename) {
200 output_filename = filename;
201 }
202
203 static void init_output() {
204 gpr_thd_options options = gpr_thd_options_default();
205 gpr_thd_options_set_joinable(&options);
206 gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options);
207 atexit(finish_writing);
208 }
209
210 static void rotate_log() {
211 gpr_timer_log *new = malloc(sizeof(*new));
212 gpr_once_init(&g_once_init, init_output);
213 new->num_entries = 0;
214 pthread_mutex_lock(&g_mu);
215 if (g_thread_log != NULL) {
216 timer_log_remove(&g_in_progress_logs, g_thread_log);
217 if (timer_log_push_back(&g_done_logs, g_thread_log)) {
218 pthread_cond_signal(&g_cv);
219 }
220 } else {
221 g_thread_id = g_next_thread_id++;
222 }
223 timer_log_push_back(&g_in_progress_logs, new);
224 pthread_mutex_unlock(&g_mu);
225 g_thread_log = new;
226 }
227
228 static void gpr_timers_log_add(const char *tagstr, marker_type type,
229 int important, const char *file, int line) {
230 gpr_timer_entry *entry;
231
232 if (g_thread_log == NULL || g_thread_log->num_entries == MAX_COUNT) {
233 rotate_log();
234 }
235
236 entry = &g_thread_log->log[g_thread_log->num_entries++];
237
238 entry->tm = gpr_now(GPR_CLOCK_PRECISE);
239 entry->tagstr = tagstr;
240 entry->type = type;
241 entry->file = file;
242 entry->line = (short)line;
243 entry->important = important != 0;
244 entry->thd = g_thread_id;
245 }
246
247 /* Latency profiler API implementation. */
248 void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
249 int line) {
250 gpr_timers_log_add(tagstr, MARK, important, file, line);
251 }
252
253 void gpr_timer_begin(const char *tagstr, int important, const char *file,
254 int line) {
255 gpr_timers_log_add(tagstr, BEGIN, important, file, line);
256 }
257
258 void gpr_timer_end(const char *tagstr, int important, const char *file,
259 int line) {
260 gpr_timers_log_add(tagstr, END, important, file, line);
261 }
262
263 /* Basic profiler specific API functions. */
264 void gpr_timers_global_init(void) {}
265
266 void gpr_timers_global_destroy(void) {}
267
268 #else /* !GRPC_BASIC_PROFILER */
269 void gpr_timers_global_init(void) {}
270
271 void gpr_timers_global_destroy(void) {}
272
273 void gpr_timers_set_log_filename(const char *filename) {}
274 #endif /* GRPC_BASIC_PROFILER */
OLDNEW
« no previous file with comments | « third_party/grpc/src/core/json/json_writer.c ('k') | third_party/grpc/src/core/profiling/stap_probes.d » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698