From 8954e90b72e69ef353eddb1fcfd4765a75b79111 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas <dgq@google.com> Date: Wed, 29 Apr 2015 09:46:33 -0700 Subject: [PATCH] Integration of Systemtap (STAP) for profiling. This commit includes a faulty Makefile to be fixed in a follow commit. --- BUILD | 6 +- Makefile | 60 +++++++++--- build.json | 3 +- src/core/channel/client_channel.c | 4 +- src/core/iomgr/pollset_posix.c | 2 +- src/core/iomgr/tcp_posix.c | 20 ++-- .../profiling/{timers.c => basic_timers.c} | 39 +++++--- src/core/profiling/stap_probes.d | 1 + src/core/profiling/stap_probes.h | 43 ++++++++ src/core/profiling/stap_timers.c | 57 +++++++++++ src/core/profiling/timers.h | 98 ++++++++++++------- src/core/surface/channel_create.c | 4 +- src/core/surface/init.c | 4 +- src/cpp/client/channel.cc | 6 +- src/cpp/common/call.cc | 8 +- src/cpp/server/server.cc | 8 +- templates/Makefile.template | 54 +++++++--- vsprojects/grpc/grpc.vcxproj | 4 +- vsprojects/grpc/grpc.vcxproj.filters | 5 +- .../grpc_unsecure/grpc_unsecure.vcxproj | 4 +- .../grpc_unsecure.vcxproj.filters | 5 +- 21 files changed, 327 insertions(+), 108 deletions(-) rename src/core/profiling/{timers.c => basic_timers.c} (77%) create mode 100644 src/core/profiling/stap_probes.h create mode 100644 src/core/profiling/stap_timers.c diff --git a/BUILD b/BUILD index e862898eaa..d06571e735 100644 --- a/BUILD +++ b/BUILD @@ -299,7 +299,8 @@ cc_library( "src/core/json/json_reader.c", "src/core/json/json_string.c", "src/core/json/json_writer.c", - "src/core/profiling/timers.c", + "src/core/profiling/basic_timers.c", + "src/core/profiling/stap_timers.c", "src/core/statistics/census_init.c", "src/core/statistics/census_log.c", "src/core/statistics/census_rpc_stats.c", @@ -508,7 +509,8 @@ cc_library( "src/core/json/json_reader.c", "src/core/json/json_string.c", "src/core/json/json_writer.c", - "src/core/profiling/timers.c", + "src/core/profiling/basic_timers.c", + "src/core/profiling/stap_timers.c", "src/core/statistics/census_init.c", "src/core/statistics/census_log.c", "src/core/statistics/census_rpc_stats.c", diff --git a/Makefile b/Makefile index 1955e2fa48..f222c8551e 100644 --- a/Makefile +++ b/Makefile @@ -87,14 +87,23 @@ CPPFLAGS_opt = -O2 LDFLAGS_opt = DEFINES_opt = NDEBUG -VALID_CONFIG_latprof = 1 -CC_latprof = $(DEFAULT_CC) -CXX_latprof = $(DEFAULT_CXX) -LD_latprof = $(DEFAULT_CC) -LDXX_latprof = $(DEFAULT_CXX) -CPPFLAGS_latprof = -O2 -DGRPC_LATENCY_PROFILER -LDFLAGS_latprof = -DEFINES_latprof = NDEBUG +VALID_CONFIG_basicprof = 1 +CC_basicprof = $(DEFAULT_CC) +CXX_basicprof = $(DEFAULT_CXX) +LD_basicprof = $(DEFAULT_CC) +LDXX_basicprof = $(DEFAULT_CXX) +CPPFLAGS_basicprof = -O2 -DGRPC_BASIC_PROFILER +LDFLAGS_basicprof = +DEFINES_basicprof = NDEBUG + +VALID_CONFIG_stapprof = 1 +CC_stapprof = $(DEFAULT_CC) +CXX_stapprof = $(DEFAULT_CXX) +LD_stapprof = $(DEFAULT_CC) +LDXX_stapprof = $(DEFAULT_CXX) +CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER +LDFLAGS_stapprof = +DEFINES_stapprof = NDEBUG VALID_CONFIG_dbg = 1 CC_dbg = $(DEFAULT_CC) @@ -394,7 +403,6 @@ HAS_SYSTEMTAP = false ifeq ($(HAS_SYSTEMTAP_HEADERS),true) ifeq ($(HAS_DTRACE),true) HAS_SYSTEMTAP = true -DEFINES += GRPC_STAP_PROFILER endif endif @@ -565,6 +573,17 @@ protoc_dep_message: @echo " make run_dep_checks" @echo +systemtap_dep_error: + @echo + @echo "DEPENDENCY ERROR" + @echo + @echo "Under the '$(CONFIG)' configutation, the target you are trying " + @echo "to build requires systemtap 2.7+ (on Linux) or dtrace (on other " + @echo "platforms such as Solaris and *BSD). " + @echo + @echo "Please consult INSTALL to get more information." + @echo + stop: @false @@ -2795,13 +2814,15 @@ $(GENDIR)/test/proto/test.grpc.pb.cc: test/proto/test.proto $(PROTOBUF_DEP) $(PR endif +ifeq ($(CONFIG), stapprof) ifeq ($(HAS_SYSTEMTAP),true) $(GENDIR)/src/core/profiling/stap_probes.h: src/core/profiling/stap_probes.d $(E) "[DTRACE] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(DTRACE) -C -h -s $< -o $@ - -src/core/profiling/timers.h: $(GENDIR)/src/core/profiling/stap_probes.h +else +$(GENDIR)/src/core/profiling/stap_probes.h: systemtap_dep_error stop +endif endif $(OBJDIR)/$(CONFIG)/%.o : %.c @@ -2824,6 +2845,17 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc $(Q) mkdir -p `dirname $@` $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< +ifeq ($(CONFIG), stapprof) +ifeq ($(HAS_SYSTEMTAP),true) +$(GENDIR)/src/core/profiling/stap_probes.h: src/core/profiling/stap_probes.d + $(E) "[DTRACE] Compiling $<" + $(Q) mkdir -p `dirname $@` + $(Q) $(DTRACE) -C -h -s $< -o $@ +else +$(GENDIR)/src/core/profiling/stap_probes.c: systemtap_dep_error stop +endif +endif + install: install_c install_cxx install-plugins install-certs verify-install @@ -3223,7 +3255,8 @@ LIBGRPC_SRC = \ src/core/json/json_reader.c \ src/core/json/json_string.c \ src/core/json/json_writer.c \ - src/core/profiling/timers.c \ + src/core/profiling/basic_timers.c \ + src/core/profiling/stap_timers.c \ src/core/statistics/census_init.c \ src/core/statistics/census_log.c \ src/core/statistics/census_rpc_stats.c \ @@ -3472,7 +3505,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/json/json_reader.c \ src/core/json/json_string.c \ src/core/json/json_writer.c \ - src/core/profiling/timers.c \ + src/core/profiling/basic_timers.c \ + src/core/profiling/stap_timers.c \ src/core/statistics/census_init.c \ src/core/statistics/census_log.c \ src/core/statistics/census_rpc_stats.c \ diff --git a/build.json b/build.json index e072ed67c3..5408ccc0d6 100644 --- a/build.json +++ b/build.json @@ -234,7 +234,8 @@ "src/core/json/json_reader.c", "src/core/json/json_string.c", "src/core/json/json_writer.c", - "src/core/profiling/timers.c", + "src/core/profiling/basic_timers.c", + "src/core/profiling/stap_timers.c", "src/core/statistics/census_init.c", "src/core/statistics/census_log.c", "src/core/statistics/census_rpc_stats.c", diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index 0c241240e2..7be89e5349 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -129,7 +129,7 @@ static void complete_activate(grpc_call_element *elem, grpc_call_op *op) { static void start_rpc(grpc_call_element *elem, grpc_call_op *op) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; - GRPC_STAP_TIMING_NS_BEGIN(2); + GRPC_TIMER_BEGIN(PTAG_OTHER_BASE + 1, NULL); gpr_mu_lock(&chand->mu); if (calld->state == CALL_CANCELLED) { gpr_mu_unlock(&chand->mu); @@ -175,7 +175,7 @@ static void start_rpc(grpc_call_element *elem, grpc_call_op *op) { grpc_transport_setup_initiate(chand->transport_setup); } } - GRPC_STAP_TIMING_NS_END(2); + GRPC_TIMER_BEGIN(PTAG_OTHER_BASE + 1, NULL); } static void remove_waiting_child(channel_data *chand, call_data *calld) { diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 60d0dad6d8..4985dcf739 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -411,7 +411,7 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, pfd[1].events = grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT, &fd_watcher); r = poll(pfd, GPR_ARRAY_SIZE(pfd), timeout); - GRPC_TIMER_MARK(POLL_FINISHED, r); + GRPC_TIMER_MARK(PTAG_POLL_FINISHED, r); grpc_fd_end_poll(&fd_watcher); diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 86721e9c95..7626a51184 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -327,7 +327,7 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { gpr_slice *final_slices; size_t final_nslices; - GRPC_TIMER_MARK(HANDLE_READ_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_HANDLE_READ, 0); slice_state_init(&read_state, static_read_slices, INLINE_SLICE_BUFFER_SIZE, 0); @@ -350,11 +350,11 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { msg.msg_controllen = 0; msg.msg_flags = 0; - GRPC_TIMER_MARK(RECVMSG_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_RECVMSG, 0); do { read_bytes = recvmsg(tcp->fd, &msg, 0); } while (read_bytes < 0 && errno == EINTR); - GRPC_TIMER_MARK(RECVMSG_END, 0); + GRPC_TIMER_END(PTAG_RECVMSG, 0); if (read_bytes < allocated_bytes) { /* TODO(klempner): Consider a second read first, in hopes of getting a @@ -406,7 +406,7 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { ++iov_size; } } - GRPC_TIMER_MARK(HANDLE_READ_END, 0); + GRPC_TIMER_END(PTAG_HANDLE_READ, 0); } static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, @@ -438,12 +438,12 @@ static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { msg.msg_controllen = 0; msg.msg_flags = 0; - GRPC_TIMER_MARK(SENDMSG_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_SENDMSG, 0); do { /* TODO(klempner): Cork if this is a partial write */ sent_length = sendmsg(tcp->fd, &msg, 0); } while (sent_length < 0 && errno == EINTR); - GRPC_TIMER_MARK(SENDMSG_END, 0); + GRPC_TIMER_END(PTAG_SENDMSG, 0); if (sent_length < 0) { if (errno == EAGAIN) { @@ -479,7 +479,7 @@ static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { return; } - GRPC_TIMER_MARK(CB_WRITE_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_TCP_CB_WRITE, 0); write_status = grpc_tcp_flush(tcp); if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); @@ -495,7 +495,7 @@ static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { cb(tcp->write_user_data, cb_status); grpc_tcp_unref(tcp); } - GRPC_TIMER_MARK(CB_WRITE_END, 0); + GRPC_TIMER_END(PTAG_TCP_CB_WRITE, 0); } static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, @@ -518,7 +518,7 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, } } - GRPC_TIMER_MARK(WRITE_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_TCP_WRITE, 0); GPR_ASSERT(tcp->write_cb == NULL); slice_state_init(&tcp->write_state, slices, nslices, nslices); @@ -532,7 +532,7 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } - GRPC_TIMER_MARK(WRITE_END, 0); + GRPC_TIMER_END(PTAG_TCP_WRITE, 0); return status; } diff --git a/src/core/profiling/timers.c b/src/core/profiling/basic_timers.c similarity index 77% rename from src/core/profiling/timers.c rename to src/core/profiling/basic_timers.c index 7cc79bd22b..b33afa7e8c 100644 --- a/src/core/profiling/timers.c +++ b/src/core/profiling/basic_timers.c @@ -31,7 +31,9 @@ * */ -#ifdef GRPC_LATENCY_PROFILER +#include <grpc/support/port_platform.h> + +#ifdef GRPC_BASIC_PROFILER #include "src/core/profiling/timers.h" #include "src/core/profiling/timers_preciseclock.h" @@ -44,7 +46,7 @@ typedef struct grpc_timer_entry { grpc_precise_clock tm; - const char* tag; + int tag; void* id; const char* file; int line; @@ -61,7 +63,7 @@ struct grpc_timers_log { grpc_timers_log* grpc_timers_log_global = NULL; -grpc_timers_log* grpc_timers_log_create(int capacity_limit, FILE* dump) { +static grpc_timers_log* grpc_timers_log_create(int capacity_limit, FILE* dump) { grpc_timers_log* log = gpr_malloc(sizeof(*log)); /* TODO (vpai): Allow allocation below limit */ @@ -85,7 +87,7 @@ static void log_report_locked(grpc_timers_log* log) { grpc_timer_entry* entry = &(log->log[i]); fprintf(fp, "GRPC_LAT_PROF "); grpc_precise_clock_print(&entry->tm, fp); - fprintf(fp, " %s %p %s %d\n", entry->tag, entry->id, entry->file, + fprintf(fp, " %d %p %s %d\n", entry->tag, entry->id, entry->file, entry->line); } @@ -93,7 +95,7 @@ static void log_report_locked(grpc_timers_log* log) { log->num_entries = 0; } -void grpc_timers_log_destroy(grpc_timers_log* log) { +static void grpc_timers_log_destroy(grpc_timers_log* log) { gpr_mu_lock(&log->mu); log_report_locked(log); gpr_mu_unlock(&log->mu); @@ -104,8 +106,8 @@ void grpc_timers_log_destroy(grpc_timers_log* log) { gpr_free(log); } -void grpc_timers_log_add(grpc_timers_log* log, const char* tag, void* id, - const char* file, int line) { +static void grpc_timers_log_add(grpc_timers_log* log, int tag, void* id, + const char* file, int line) { grpc_timer_entry* entry; /* TODO (vpai) : Improve concurrency */ @@ -125,14 +127,25 @@ void grpc_timers_log_add(grpc_timers_log* log, const char* tag, void* id, gpr_mu_unlock(&log->mu); } -void grpc_timers_log_global_init(void) { +/* Latency profiler API implementation. */ +void grpc_timer_add_mark(int tag, void* id, const char* file, int line) { + grpc_timers_log_add(grpc_timers_log_global, tag, id, file, line); +} + +void grpc_timer_begin(int tag, void* id, const char *file, int line) {} +void grpc_timer_end(int tag, void* id, const char *file, int line) {} + +/* Basic profiler specific API functions. */ +void grpc_timers_global_init(void) { grpc_timers_log_global = grpc_timers_log_create(100000, stdout); } -void grpc_timers_log_global_destroy(void) { +void grpc_timers_global_destroy(void) { grpc_timers_log_destroy(grpc_timers_log_global); } -#else /* !GRPC_LATENCY_PROFILER */ -void grpc_timers_log_global_init(void) {} -void grpc_timers_log_global_destroy(void) {} -#endif /* GRPC_LATENCY_PROFILER */ + + +#else /* !GRPC_BASIC_PROFILER */ +void grpc_timers_global_init(void) {} +void grpc_timers_global_destroy(void) {} +#endif /* GRPC_BASIC_PROFILER */ diff --git a/src/core/profiling/stap_probes.d b/src/core/profiling/stap_probes.d index 04881826d0..374eeedd6c 100644 --- a/src/core/profiling/stap_probes.d +++ b/src/core/profiling/stap_probes.d @@ -1,4 +1,5 @@ provider _stap { + probe add_mark(int tag); probe timing_ns_begin(int tag); probe timing_ns_end(int tag); }; diff --git a/src/core/profiling/stap_probes.h b/src/core/profiling/stap_probes.h new file mode 100644 index 0000000000..ba8020c5a3 --- /dev/null +++ b/src/core/profiling/stap_probes.h @@ -0,0 +1,43 @@ +/* Generated by the Systemtap dtrace wrapper */ + +#define _SDT_HAS_SEMAPHORES 1 + + +#define STAP_HAS_SEMAPHORES 1 /* deprecated */ + + +#include <sys/sdt.h> + +/* _STAP_ADD_MARK ( int tag) */ +#if defined STAP_SDT_V1 +#define _STAP_ADD_MARK_ENABLED() __builtin_expect (add_mark_semaphore, 0) +#define _stap_add_mark_semaphore add_mark_semaphore +#else +#define _STAP_ADD_MARK_ENABLED() __builtin_expect (_stap_add_mark_semaphore, 0) +#endif +__extension__ extern unsigned short _stap_add_mark_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); +#define _STAP_ADD_MARK(arg1) \ +DTRACE_PROBE1(_stap,add_mark,arg1) + +/* _STAP_TIMING_NS_BEGIN ( int tag) */ +#if defined STAP_SDT_V1 +#define _STAP_TIMING_NS_BEGIN_ENABLED() __builtin_expect (timing_ns_begin_semaphore, 0) +#define _stap_timing_ns_begin_semaphore timing_ns_begin_semaphore +#else +#define _STAP_TIMING_NS_BEGIN_ENABLED() __builtin_expect (_stap_timing_ns_begin_semaphore, 0) +#endif +__extension__ extern unsigned short _stap_timing_ns_begin_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); +#define _STAP_TIMING_NS_BEGIN(arg1) \ +DTRACE_PROBE1(_stap,timing_ns_begin,arg1) + +/* _STAP_TIMING_NS_END ( int tag) */ +#if defined STAP_SDT_V1 +#define _STAP_TIMING_NS_END_ENABLED() __builtin_expect (timing_ns_end_semaphore, 0) +#define _stap_timing_ns_end_semaphore timing_ns_end_semaphore +#else +#define _STAP_TIMING_NS_END_ENABLED() __builtin_expect (_stap_timing_ns_end_semaphore, 0) +#endif +__extension__ extern unsigned short _stap_timing_ns_end_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); +#define _STAP_TIMING_NS_END(arg1) \ +DTRACE_PROBE1(_stap,timing_ns_end,arg1) + diff --git a/src/core/profiling/stap_timers.c b/src/core/profiling/stap_timers.c new file mode 100644 index 0000000000..52fb58a279 --- /dev/null +++ b/src/core/profiling/stap_timers.c @@ -0,0 +1,57 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/support/port_platform.h> + +#ifdef GRPC_STAP_PROFILER + +#include "src/core/profiling/timers.h" + +#include <sys/sdt.h> +/* Generated from src/core/profiling/stap_probes.d */ +#include "src/core/profiling/stap_probes.h" + +/* Latency profiler API implementation. */ +void grpc_timer_add_mark(int tag, void* id, const char *file, int line) { + _STAP_ADD_MARK(tag); +} + +void grpc_timer_begin(int tag, void* id, const char *file, int line) { + _STAP_TIMING_NS_BEGIN(tag); +} + +void grpc_timer_end(int tag, void* id, const char *file, int line) { + _STAP_TIMING_NS_END(tag); +} + +#endif /* GRPC_STAP_PROFILER */ diff --git a/src/core/profiling/timers.h b/src/core/profiling/timers.h index 8fe8a8fe99..a78bbea4ec 100644 --- a/src/core/profiling/timers.h +++ b/src/core/profiling/timers.h @@ -34,52 +34,78 @@ #ifndef GRPC_CORE_PROFILING_TIMERS_H #define GRPC_CORE_PROFILING_TIMERS_H -#include <stdio.h> - -#ifdef GRPC_STAP_PROFILER -#include <sys/sdt.h> -/* Generated from src/core/profiling/stap_probes.d */ -#include "src/core/profiling/stap_probes.h" - -#define GRPC_STAP_TIMING_NS_BEGIN(tag) _STAP_TIMING_NS_BEGIN(tag) -#define GRPC_STAP_TIMING_NS_END(tag) _STAP_TIMING_NS_END(tag) - -#else /* !GRPC_STAP_PROFILER */ -#define GRPC_STAP_BEGIN_NS(x, s) \ - do { \ - } while (0) -#define GRPC_STAP_END_NS(x, s) \ - do { \ - } while (0) -#endif /* GRPC_STAP_PROFILER */ - #ifdef __cplusplus extern "C" { #endif -#ifdef GRPC_LATENCY_PROFILER +void grpc_timers_global_init(void); +void grpc_timers_global_destroy(void); -typedef struct grpc_timers_log grpc_timers_log; +void grpc_timer_add_mark(int tag, void* id, const char *file, int line); +void grpc_timer_begin(int tag, void* id, const char *file, int line); +void grpc_timer_end(int tag, void* id, const char *file, int line); -grpc_timers_log* grpc_timers_log_create(int capacity_limit, FILE* dump); -void grpc_timers_log_add(grpc_timers_log*, const char* tag, void* id, - const char* file, int line); -void grpc_timers_log_destroy(grpc_timers_log *); +enum profiling_tags { + /* Re. Protos. */ + PTAG_PROTO_SERIALIZE = 100, + PTAG_PROTO_DESERIALIZE = 101, -extern grpc_timers_log *grpc_timers_log_global; + /* Re. sockets. */ + PTAG_HANDLE_READ = 200, + PTAG_SENDMSG = 201, + PTAG_RECVMSG = 202, + PTAG_POLL_FINISHED = 203, + PTAG_TCP_CB_WRITE = 204, + PTAG_TCP_WRITE = 205, -#define GRPC_TIMER_MARK(x, s) \ - grpc_timers_log_add(grpc_timers_log_global, #x, ((void *)(gpr_intptr)(s)), \ - __FILE__, __LINE__) + /* C++ */ + PTAG_CPP_CALL_CREATED = 300, + PTAG_CPP_PERFORM_OPS = 301, -#else /* !GRPC_LATENCY_PROFILER */ -#define GRPC_TIMER_MARK(x, s) \ - do { \ - } while (0) -#endif /* GRPC_LATENCY_PROFILER */ + /* > 1024 Unassigned reserved. For any miscellaneous use. + * Use addition to generate tags from this base or take advantage of the 10 + * zero'd bits for OR-ing. */ + PTAG_OTHER_BASE = 1024 +}; + +#if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER)) +/* No profiling. No-op all the things. */ +#define GRPC_TIMER_MARK(tag, id) \ + do {} while(0) + +#define GRPC_TIMER_BEGIN(tag, id) \ + do {} while(0) + +#define GRPC_TIMER_END(tag, id) \ + do {} while(0) + +#else /* at least one profiler requested... */ +/* ... hopefully only one. */ +#if defined(GRPC_STAP_PROFILER) && defined(GRPC_BASIC_PROFILER) +#error "GRPC_STAP_PROFILER and GRPC_BASIC_PROFILER are mutually exclusive." +#endif + +/* Generic profiling interface. */ +#define GRPC_TIMER_MARK(tag, id) \ + grpc_timer_add_mark(tag, ((void *)(gpr_intptr)(id)), __FILE__, __LINE__) + +#define GRPC_TIMER_BEGIN(tag, id) \ + grpc_timer_begin(tag, ((void *)(gpr_intptr)(id)), __FILE__, __LINE__) + +#define GRPC_TIMER_END(tag, id) \ + grpc_timer_end(tag, ((void *)(gpr_intptr)(id)), __FILE__, __LINE__) + +#ifdef GRPC_STAP_PROFILER +/* Empty placeholder for now. */ +#endif /* GRPC_STAP_PROFILER */ + +#ifdef GRPC_BASIC_PROFILER +typedef struct grpc_timers_log grpc_timers_log; + +extern grpc_timers_log *grpc_timers_log_global; +#endif /* GRPC_BASIC_PROFILER */ -void grpc_timers_log_global_init(void); -void grpc_timers_log_global_destroy(void); +#endif /* at least one profiler requested. */ #ifdef __cplusplus } diff --git a/src/core/surface/channel_create.c b/src/core/surface/channel_create.c index 73b3670ccc..c44dcce7de 100644 --- a/src/core/surface/channel_create.c +++ b/src/core/surface/channel_create.c @@ -198,7 +198,7 @@ grpc_channel *grpc_channel_create(const char *target, #define MAX_FILTERS 3 const grpc_channel_filter *filters[MAX_FILTERS]; int n = 0; - GRPC_STAP_TIMING_NS_BEGIN(1); + GRPC_TIMER_BEGIN(PTAG_OTHER_BASE + 2, NULL); filters[n++] = &grpc_client_surface_filter; if (grpc_channel_args_is_census_enabled(args)) { filters[n++] = &grpc_client_census_filter; @@ -214,6 +214,6 @@ grpc_channel *grpc_channel_create(const char *target, grpc_client_setup_create_and_attach(grpc_channel_get_channel_stack(channel), args, mdctx, initiate_setup, done_setup, s); - GRPC_STAP_TIMING_NS_END(1); + GRPC_TIMER_END(PTAG_OTHER_BASE + 2, NULL); return channel; } diff --git a/src/core/surface/init.c b/src/core/surface/init.c index 5a119a47cc..bfee28e5fc 100644 --- a/src/core/surface/init.c +++ b/src/core/surface/init.c @@ -64,7 +64,7 @@ void grpc_init(void) { grpc_iomgr_init(); grpc_tracer_init("GRPC_TRACE"); census_init(); - grpc_timers_log_global_init(); + grpc_timers_global_init(); } gpr_mu_unlock(&g_init_mu); } @@ -74,7 +74,7 @@ void grpc_shutdown(void) { if (--g_initializations == 0) { grpc_iomgr_shutdown(); census_shutdown(); - grpc_timers_log_global_destroy(); + grpc_timers_global_destroy(); } gpr_mu_unlock(&g_init_mu); } diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index c541ddfb48..3d9d1307a4 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -70,7 +70,7 @@ Call Channel::CreateCall(const RpcMethod& method, ClientContext* context, ? target_.c_str() : context->authority().c_str(), context->raw_deadline()); - GRPC_TIMER_MARK(CALL_CREATED, c_call); + GRPC_TIMER_MARK(PTAG_CPP_CALL_CREATED, c_call); context->set_call(c_call, shared_from_this()); return Call(c_call, this, cq); } @@ -79,11 +79,11 @@ void Channel::PerformOpsOnCall(CallOpBuffer* buf, Call* call) { static const size_t MAX_OPS = 8; size_t nops = MAX_OPS; grpc_op ops[MAX_OPS]; - GRPC_TIMER_MARK(PERFORM_OPS_BEGIN, call->call()); + GRPC_TIMER_BEGIN(PTAG_CPP_PERFORM_OPS, call->call()); buf->FillOps(ops, &nops); GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), ops, nops, buf)); - GRPC_TIMER_MARK(PERFORM_OPS_END, call->call()); + GRPC_TIMER_END(PTAG_CPP_PERFORM_OPS, call->call()); } void* Channel::RegisterMethod(const char* method) { diff --git a/src/cpp/common/call.cc b/src/cpp/common/call.cc index 9878133331..41d64276e2 100644 --- a/src/cpp/common/call.cc +++ b/src/cpp/common/call.cc @@ -232,13 +232,13 @@ void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) { } if (send_message_ || send_message_buffer_) { if (send_message_) { - GRPC_TIMER_MARK(SER_PROTO_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_PROTO_SERIALIZE, 0); bool success = SerializeProto(*send_message_, &send_buf_); if (!success) { abort(); // TODO handle parse failure } - GRPC_TIMER_MARK(SER_PROTO_END, 0); + GRPC_TIMER_END(PTAG_PROTO_SERIALIZE, 0); } else { send_buf_ = send_message_buffer_->buffer(); } @@ -310,10 +310,10 @@ bool CallOpBuffer::FinalizeResult(void** tag, bool* status) { if (recv_buf_) { got_message = *status; if (recv_message_) { - GRPC_TIMER_MARK(DESER_PROTO_BEGIN, 0); + GRPC_TIMER_BEGIN(PTAG_PROTO_DESERIALIZE, 0); *status = *status && DeserializeProto(recv_buf_, recv_message_); grpc_byte_buffer_destroy(recv_buf_); - GRPC_TIMER_MARK(DESER_PROTO_END, 0); + GRPC_TIMER_END(PTAG_PROTO_DESERIALIZE, 0); } else { recv_message_buffer_->set_buffer(recv_buf_); } diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 1d39378595..c84b9d8d84 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -124,12 +124,12 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag { std::unique_ptr<grpc::protobuf::Message> req; std::unique_ptr<grpc::protobuf::Message> res; if (has_request_payload_) { - GRPC_TIMER_MARK(DESER_PROTO_BEGIN, call_.call()); + GRPC_TIMER_BEGIN(PTAG_PROTO_DESERIALIZE, call_.call()); req.reset(method_->AllocateRequestProto()); if (!DeserializeProto(request_payload_, req.get())) { abort(); // for now } - GRPC_TIMER_MARK(DESER_PROTO_END, call_.call()); + GRPC_TIMER_END(PTAG_PROTO_DESERIALIZE, call_.call()); } if (has_response_payload_) { res.reset(method_->AllocateResponseProto()); @@ -343,9 +343,9 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag { bool orig_status = *status; if (*status && request_) { if (payload_) { - GRPC_TIMER_MARK(DESER_PROTO_BEGIN, call_); + GRPC_TIMER_BEGIN(PTAG_PROTO_DESERIALIZE, call_); *status = DeserializeProto(payload_, request_); - GRPC_TIMER_MARK(DESER_PROTO_END, call_); + GRPC_TIMER_END(PTAG_PROTO_DESERIALIZE, call_); } else { *status = false; } diff --git a/templates/Makefile.template b/templates/Makefile.template index 8fe8854d67..cd5eee6e5c 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -101,14 +101,23 @@ CPPFLAGS_opt = -O2 LDFLAGS_opt = DEFINES_opt = NDEBUG -VALID_CONFIG_latprof = 1 -CC_latprof = $(DEFAULT_CC) -CXX_latprof = $(DEFAULT_CXX) -LD_latprof = $(DEFAULT_CC) -LDXX_latprof = $(DEFAULT_CXX) -CPPFLAGS_latprof = -O2 -DGRPC_LATENCY_PROFILER -LDFLAGS_latprof = -DEFINES_latprof = NDEBUG +VALID_CONFIG_basicprof = 1 +CC_basicprof = $(DEFAULT_CC) +CXX_basicprof = $(DEFAULT_CXX) +LD_basicprof = $(DEFAULT_CC) +LDXX_basicprof = $(DEFAULT_CXX) +CPPFLAGS_basicprof = -O2 -DGRPC_BASIC_PROFILER +LDFLAGS_basicprof = +DEFINES_basicprof = NDEBUG + +VALID_CONFIG_stapprof = 1 +CC_stapprof = $(DEFAULT_CC) +CXX_stapprof = $(DEFAULT_CXX) +LD_stapprof = $(DEFAULT_CC) +LDXX_stapprof = $(DEFAULT_CXX) +CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER +LDFLAGS_stapprof = +DEFINES_stapprof = NDEBUG VALID_CONFIG_dbg = 1 CC_dbg = $(DEFAULT_CC) @@ -408,7 +417,6 @@ HAS_SYSTEMTAP = false ifeq ($(HAS_SYSTEMTAP_HEADERS),true) ifeq ($(HAS_DTRACE),true) HAS_SYSTEMTAP = true -DEFINES += GRPC_STAP_PROFILER endif endif @@ -591,6 +599,17 @@ protoc_dep_message: @echo " make run_dep_checks" @echo +systemtap_dep_error: + @echo + @echo "DEPENDENCY ERROR" + @echo + @echo "Under the '$(CONFIG)' configutation, the target you are trying " + @echo "to build requires systemtap 2.7+ (on Linux) or dtrace (on other " + @echo "platforms such as Solaris and *BSD). " + @echo + @echo "Please consult INSTALL to get more information." + @echo + stop: @false @@ -879,13 +898,15 @@ endif % endfor +ifeq ($(CONFIG), stapprof) ifeq ($(HAS_SYSTEMTAP),true) $(GENDIR)/src/core/profiling/stap_probes.h: src/core/profiling/stap_probes.d $(E) "[DTRACE] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(DTRACE) -C -h -s $< -o $@ - -src/core/profiling/timers.h: $(GENDIR)/src/core/profiling/stap_probes.h +else +$(GENDIR)/src/core/profiling/stap_probes.h: systemtap_dep_error stop +endif endif $(OBJDIR)/$(CONFIG)/%.o : %.c @@ -908,6 +929,17 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc $(Q) mkdir -p `dirname $@` $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< +ifeq ($(CONFIG), stapprof) +ifeq ($(HAS_SYSTEMTAP),true) +$(GENDIR)/src/core/profiling/stap_probes.h: src/core/profiling/stap_probes.d + $(E) "[DTRACE] Compiling $<" + $(Q) mkdir -p `dirname $@` + $(Q) $(DTRACE) -C -h -s $< -o $@ +else +$(GENDIR)/src/core/profiling/stap_probes.c: systemtap_dep_error stop +endif +endif + install: install_c install_cxx install-plugins install-certs verify-install diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index fc7744f2b7..83a44a37f6 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -341,7 +341,9 @@ </ClCompile> <ClCompile Include="..\..\src\core\json\json_writer.c"> </ClCompile> - <ClCompile Include="..\..\src\core\profiling\timers.c"> + <ClCompile Include="..\..\src\core\profiling\basic_timers.c"> + </ClCompile> + <ClCompile Include="..\..\src\core\profiling\stap_timers.c"> </ClCompile> <ClCompile Include="..\..\src\core\statistics\census_init.c"> </ClCompile> diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters index 1dfca58cb5..c29355f6b1 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -217,7 +217,10 @@ <ClCompile Include="..\..\src\core\json\json_writer.c"> <Filter>src\core\json</Filter> </ClCompile> - <ClCompile Include="..\..\src\core\profiling\timers.c"> + <ClCompile Include="..\..\src\core\profiling\basic_timers.c"> + <Filter>src\core\profiling</Filter> + </ClCompile> + <ClCompile Include="..\..\src\core\profiling\stap_timers.c"> <Filter>src\core\profiling</Filter> </ClCompile> <ClCompile Include="..\..\src\core\statistics\census_init.c"> diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj index 670b109e6f..07debcccba 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -286,7 +286,9 @@ </ClCompile> <ClCompile Include="..\..\src\core\json\json_writer.c"> </ClCompile> - <ClCompile Include="..\..\src\core\profiling\timers.c"> + <ClCompile Include="..\..\src\core\profiling\basic_timers.c"> + </ClCompile> + <ClCompile Include="..\..\src\core\profiling\stap_timers.c"> </ClCompile> <ClCompile Include="..\..\src\core\statistics\census_init.c"> </ClCompile> diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters index 7c94d4d51e..c886f87c88 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -160,7 +160,10 @@ <ClCompile Include="..\..\src\core\json\json_writer.c"> <Filter>src\core\json</Filter> </ClCompile> - <ClCompile Include="..\..\src\core\profiling\timers.c"> + <ClCompile Include="..\..\src\core\profiling\basic_timers.c"> + <Filter>src\core\profiling</Filter> + </ClCompile> + <ClCompile Include="..\..\src\core\profiling\stap_timers.c"> <Filter>src\core\profiling</Filter> </ClCompile> <ClCompile Include="..\..\src\core\statistics\census_init.c"> -- GitLab