diff options
author | 2015-04-30 13:25:11 -0700 | |
---|---|---|
committer | 2015-04-30 13:25:11 -0700 | |
commit | 48373dfab0422f9f07dc0a6a7b9ff8c73ec4b3e3 (patch) | |
tree | 77b67e28507661e3812a092ce4c0257eeada06ae | |
parent | 94d7f8542c704bc3ab4cb46e817513aa0ced9f99 (diff) | |
parent | f2791ab02b0100c890fce8a2dbcd322d84595936 (diff) |
Merge github.com:grpc/grpc into delete-the-old-api
26 files changed, 782 insertions, 110 deletions
diff --git a/.travis.yml b/.travis.yml index 82d8316dda..1f96c6fc00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,13 +18,12 @@ env: - NUGET="mono nuget.exe" matrix: - CONFIG=opt TEST=sanity - - CONFIG=dbg TEST="c c++" + - CONFIG=gcov TEST="c c++" - CONFIG=opt TEST="c c++" - CONFIG=opt TEST=node - CONFIG=opt TEST=ruby - CONFIG=opt TEST=python - CONFIG=opt TEST=csharp - - CONFIG=gcov TEST="c c++" - USE_GCC=4.4 CONFIG=opt TEST=build - USE_GCC=4.5 CONFIG=opt TEST=build script: @@ -296,7 +296,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", @@ -503,7 +504,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", @@ -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) @@ -174,7 +183,7 @@ LD_gcov = gcc LDXX_gcov = g++ CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -DEFINES_gcov = NDEBUG +DEFINES_gcov = _DEBUG DEBUG # General settings. @@ -183,6 +192,7 @@ DEFINES_gcov = NDEBUG prefix ?= /usr/local PROTOC = protoc +DTRACE = dtrace CONFIG ?= opt CC = $(CC_$(CONFIG)) CXX = $(CXX_$(CONFIG)) @@ -350,6 +360,8 @@ PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perfto PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS) PROTOC_CHECK_CMD = which protoc > /dev/null PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 +DTRACE_CHECK_CMD = which dtrace > /dev/null +SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) ifeq ($(OPENSSL_REQUIRES_DL),true) OPENSSL_ALPN_CHECK_CMD += -ldl @@ -382,6 +394,18 @@ else HAS_VALID_PROTOC = false endif +# Check for Systemtap (https://sourceware.org/systemtap/), first by making sure <sys/sdt.h> is present +# in the system and secondly by checking for the "dtrace" binary (on Linux, this is part of the Systemtap +# distribution. It's part of the base system on BSD/Solaris machines). +HAS_SYSTEMTAP_HEADERS = $(shell $(SYSTEMTAP_HEADERS_CHECK_CMD) 2> /dev/null && echo true || echo false) +HAS_DTRACE = $(shell $(DTRACE_CHECK_CMD) 2> /dev/null && echo true || echo false) +HAS_SYSTEMTAP = false +ifeq ($(HAS_SYSTEMTAP_HEADERS),true) +ifeq ($(HAS_DTRACE),true) +HAS_SYSTEMTAP = true +endif +endif + ifeq ($(wildcard third_party/openssl/ssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else @@ -549,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 @@ -1916,6 +1951,18 @@ $(GENDIR)/test/proto/test.grpc.pb.cc: test/proto/test.proto $(PROTOBUF_DEP) $(PR endif +ifeq ($(CONFIG),stapprof) +src/core/profiling/stap_timers.c: $(GENDIR)/src/core/profiling/stap_probes.h +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.h: systemtap_dep_error stop +endif +endif + $(OBJDIR)/$(CONFIG)/%.o : %.c $(E) "[C] Compiling $<" $(Q) mkdir -p `dirname $@` @@ -1936,7 +1983,6 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc $(Q) mkdir -p `dirname $@` $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< - install: install_c install_cxx install-plugins install-certs verify-install install_c: install-headers_c install-static_c install-shared_c @@ -2333,7 +2379,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 \ @@ -2581,7 +2628,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 e36074246b..c74fe945e8 100644 --- a/build.json +++ b/build.json @@ -231,7 +231,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/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 60d0dad6d8..4d1bcad9e2 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(GRPC_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..40897fb8f8 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(GRPC_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(GRPC_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(GRPC_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(GRPC_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(GRPC_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(GRPC_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(GRPC_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(GRPC_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(GRPC_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(GRPC_PTAG_TCP_WRITE, 0); return status; } diff --git a/src/core/profiling/timers.c b/src/core/profiling/basic_timers.c index bd1700ffd8..d89bba7b87 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" @@ -46,7 +48,7 @@ typedef struct grpc_timer_entry { grpc_precise_clock tm; gpr_thd_id thd; - const char* tag; + int tag; void* id; const char* file; int line; @@ -63,7 +65,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 */ @@ -87,15 +89,15 @@ 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, " %p %s %p %s %d\n", (void*)(gpr_intptr)entry->thd, entry->tag, entry->id, entry->file, - entry->line); + fprintf(fp, " %p %d %p %s %d\n", (void*)(gpr_intptr)entry->thd, entry->tag, + entry->id, entry->file, entry->line); } /* Now clear out the 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); @@ -106,8 +108,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 */ @@ -128,14 +130,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 new file mode 100644 index 0000000000..374eeedd6c --- /dev/null +++ b/src/core/profiling/stap_probes.d @@ -0,0 +1,6 @@ +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_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 1a6b9ffac9..d0b8286c03 100644 --- a/src/core/profiling/timers.h +++ b/src/core/profiling/timers.h @@ -34,35 +34,87 @@ #ifndef GRPC_CORE_PROFILING_TIMERS_H #define GRPC_CORE_PROFILING_TIMERS_H -#include <stdio.h> - #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 grpc_profiling_tags { + /* Any GRPC_PTAG_* >= than the threshold won't generate any profiling mark. */ + GRPC_PTAG_IGNORE_THRESHOLD = 1000000, -extern grpc_timers_log *grpc_timers_log_global; + /* Re. Protos. */ + GRPC_PTAG_PROTO_SERIALIZE = 100 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_PROTO_DESERIALIZE = 101 + GRPC_PTAG_IGNORE_THRESHOLD, + + /* Re. sockets. */ + GRPC_PTAG_HANDLE_READ = 200 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_SENDMSG = 201 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_RECVMSG = 202 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_POLL_FINISHED = 203 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_TCP_CB_WRITE = 204 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_TCP_WRITE = 205 + GRPC_PTAG_IGNORE_THRESHOLD, + + /* C++ */ + GRPC_PTAG_CPP_CALL_CREATED = 300 + GRPC_PTAG_IGNORE_THRESHOLD, + GRPC_PTAG_CPP_PERFORM_OPS = 301 + GRPC_PTAG_IGNORE_THRESHOLD, -#define GRPC_TIMER_MARK(x, s) \ - grpc_timers_log_add(grpc_timers_log_global, #x, ((void *)(gpr_intptr)(s)), \ - __FILE__, __LINE__) + /* > 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. */ + GRPC_PTAG_OTHER_BASE = 1024 +}; -#else /* !GRPC_LATENCY_PROFILER */ -#define GRPC_TIMER_MARK(x, s) \ - do { \ - } while (0) -#endif /* GRPC_LATENCY_PROFILER */ +#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) \ + if (tag < GRPC_PTAG_IGNORE_THRESHOLD) { \ + grpc_timer_add_mark(tag, ((void *)(gpr_intptr)(id)), __FILE__, __LINE__); \ + } + +#define GRPC_TIMER_BEGIN(tag, id) \ + if (tag < GRPC_PTAG_IGNORE_THRESHOLD) { \ + grpc_timer_begin(tag, ((void *)(gpr_intptr)(id)), __FILE__, __LINE__); \ + } + +#define GRPC_TIMER_END(tag, id) \ + if (tag < GRPC_PTAG_IGNORE_THRESHOLD) { \ + 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/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..475a20d883 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(GRPC_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(GRPC_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(GRPC_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..a60282316a 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(GRPC_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(GRPC_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(GRPC_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(GRPC_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 4694a3a7ff..34aac4c584 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(GRPC_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(GRPC_PTAG_PROTO_DESERIALIZE, call_.call()); } if (has_response_payload_) { res.reset(method_->AllocateResponseProto()); @@ -346,9 +346,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(GRPC_PTAG_PROTO_DESERIALIZE, call_); *status = DeserializeProto(payload_, request_); - GRPC_TIMER_MARK(DESER_PROTO_END, call_); + GRPC_TIMER_END(GRPC_PTAG_PROTO_DESERIALIZE, call_); } else { *status = false; } diff --git a/src/php/composer.json b/src/php/composer.json index 3c0cb37231..ba7a1302f2 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -5,7 +5,8 @@ "homepage": "http://grpc.io", "license": "BSD-3-Clause", "require": { - "php": ">=5.5.0" + "php": ">=5.5.0", + "google/auth": "dev-master" }, "autoload": { "psr-4": { diff --git a/src/php/composer.lock b/src/php/composer.lock index 47fc70fd2d..c2d723def4 100644 --- a/src/php/composer.lock +++ b/src/php/composer.lock @@ -4,12 +4,308 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "65467a098f5fd8b8fe5f7f6e10226f8a", - "packages": [], + "hash": "bb81ea5f72ddea2f594a172ff0f3b44d", + "packages": [ + { + "name": "firebase/php-jwt", + "version": "2.0.0", + "target-dir": "Firebase/PHP-JWT", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "ffcfd888ce1e4f2d70cac2dc9b7301038332fe57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/ffcfd888ce1e4f2d70cac2dc9b7301038332fe57", + "reference": "ffcfd888ce1e4f2d70cac2dc9b7301038332fe57", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "Authentication/", + "Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "time": "2015-04-01 18:46:38" + }, + { + "name": "google/auth", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/google/google-auth-library-php.git", + "reference": "35f87159b327fa6416266948c1747c585a4ae3ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/google/google-auth-library-php/zipball/35f87159b327fa6416266948c1747c585a4ae3ad", + "reference": "35f87159b327fa6416266948c1747c585a4ae3ad", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "2.0.0", + "guzzlehttp/guzzle": "5.2.*", + "php": ">=5.4" + }, + "require-dev": { + "phplint/phplint": "0.0.1", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ], + "psr-4": { + "Google\\Auth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Google Auth Library for PHP", + "homepage": "http://github.com/google/google-auth-library-php", + "keywords": [ + "Authentication", + "google", + "oauth2" + ], + "time": "2015-04-30 11:57:19" + }, + { + "name": "guzzlehttp/guzzle", + "version": "5.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "475b29ccd411f2fa8a408e64576418728c032cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/475b29ccd411f2fa8a408e64576418728c032cfa", + "reference": "475b29ccd411f2fa8a408e64576418728c032cfa", + "shasum": "" + }, + "require": { + "guzzlehttp/ringphp": "~1.0", + "php": ">=5.4.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0", + "psr/log": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2015-01-28 01:03:29" + }, + { + "name": "guzzlehttp/ringphp", + "version": "1.0.7", + "source": { + "type": "git", + "url": "https://github.com/guzzle/RingPHP.git", + "reference": "52d868f13570a9a56e5fce6614e0ec75d0f13ac2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/52d868f13570a9a56e5fce6614e0ec75d0f13ac2", + "reference": "52d868f13570a9a56e5fce6614e0ec75d0f13ac2", + "shasum": "" + }, + "require": { + "guzzlehttp/streams": "~3.0", + "php": ">=5.4.0", + "react/promise": "~2.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Guzzle will use specific adapters if cURL is present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Ring\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "time": "2015-03-30 01:43:20" + }, + { + "name": "guzzlehttp/streams", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/streams.git", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple abstraction over streams of data", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "stream" + ], + "time": "2014-10-12 19:18:40" + }, + { + "name": "react/promise", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/365fcee430dfa4ace1fbc75737ca60ceea7eeeef", + "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@googlemail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "time": "2014-12-30 13:32:42" + } + ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "google/auth": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index 6f81bfa6cd..22f85aa322 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -38,6 +38,7 @@ require 'empty.php'; require 'message_set.php'; require 'messages.php'; require 'test.php'; + /** * Assertion function that always exits with an error code if the assertion is * falsy @@ -45,7 +46,7 @@ require 'test.php'; * @param $error_message Message to display if the assertion is false */ function hardAssert($value, $error_message) { - if(!$value) { + if (!$value) { echo $error_message . "\n"; exit(1); } @@ -53,7 +54,7 @@ function hardAssert($value, $error_message) { /** * Run the empty_unary test. - * Currently not tested against any server as of 2014-12-04 + * Passes when run against the Node server as of 2015-04-30 * @param $stub Stub object that has service methods */ function emptyUnary($stub) { @@ -64,11 +65,20 @@ function emptyUnary($stub) { /** * Run the large_unary test. - * Passes when run against the C++ server as of 2014-12-04 - * Not tested against any other server as of 2014-12-04 + * Passes when run against the C++/Node server as of 2015-04-30 * @param $stub Stub object that has service methods */ function largeUnary($stub) { + performLargeUnary($stub); +} + +/** + * Shared code between large unary test and auth test + * @param $stub Stub object that has service methods + * @param $fillUsername boolean whether to fill result with username + * @param $fillOauthScope boolean whether to fill result with oauth scope + */ +function performLargeUnary($stub, $fillUsername = false, $fillOauthScope = false) { $request_len = 271828; $response_len = 314159; @@ -79,6 +89,8 @@ function largeUnary($stub) { $payload->setType(grpc\testing\PayloadType::COMPRESSABLE); $payload->setBody(str_repeat("\0", $request_len)); $request->setPayload($payload); + $request->setFillUsername($fillUsername); + $request->setFillOauthScope($fillOauthScope); list($result, $status) = $stub->UnaryCall($request)->wait(); hardAssert($status->code === Grpc\STATUS_OK, 'Call did not complete successfully'); @@ -90,11 +102,32 @@ function largeUnary($stub) { 'Payload had the wrong length'); hardAssert($payload->getBody() === str_repeat("\0", $response_len), 'Payload had the wrong content'); + return $result; +} + +/** + * Run the service account credentials auth test. + * Passes when run against the cloud server as of 2015-04-30 + * @param $stub Stub object that has service methods + * @param $args array command line args + */ +function serviceAccountCreds($stub, $args) { + if (!array_key_exists('oauth_scope', $args)) { + throw new Exception('Missing oauth scope'); + } + $jsonKey = json_decode( + file_get_contents(getenv(Google\Auth\CredentialsLoader::ENV_VAR)), + true); + $result = performLargeUnary($stub, $fillUsername=true, $fillOauthScope=true); + hardAssert($result->getUsername() == $jsonKey['client_email'], + 'invalid email returned'); + hardAssert(strpos($args['oauth_scope'], $result->getOauthScope()) !== false, + 'invalid oauth scope returned'); } /** * Run the client_streaming test. - * Not tested against any server as of 2014-12-04. + * Passes when run against the Node server as of 2015-04-30 * @param $stub Stub object that has service methods */ function clientStreaming($stub) { @@ -117,7 +150,7 @@ function clientStreaming($stub) { /** * Run the server_streaming test. - * Not tested against any server as of 2014-12-04. + * Passes when run against the Node server as of 2015-04-30 * @param $stub Stub object that has service methods. */ function serverStreaming($stub) { @@ -148,7 +181,7 @@ function serverStreaming($stub) { /** * Run the ping_pong test. - * Not tested against any server as of 2014-12-04. + * Passes when run against the Node server as of 2015-04-30 * @param $stub Stub object that has service methods. */ function pingPong($stub) { @@ -182,6 +215,11 @@ function pingPong($stub) { 'Call did not complete successfully'); } +/** + * Run the cancel_after_first_response test. + * Passes when run against the Node server as of 2015-04-30 + * @param $stub Stub object that has service methods. + */ function cancelAfterFirstResponse($stub) { $call = $stub->FullDuplexCall(); $request = new grpc\testing\StreamingOutputCallRequest(); @@ -201,7 +239,8 @@ function cancelAfterFirstResponse($stub) { 'Call status was not CANCELLED'); } -$args = getopt('', array('server_host:', 'server_port:', 'test_case:')); +$args = getopt('', array('server_host:', 'server_port:', 'test_case:', + 'server_host_override:', 'oauth_scope:')); if (!array_key_exists('server_host', $args) || !array_key_exists('server_port', $args) || !array_key_exists('test_case', $args)) { @@ -210,20 +249,37 @@ if (!array_key_exists('server_host', $args) || $server_address = $args['server_host'] . ':' . $args['server_port']; -$credentials = Grpc\Credentials::createSsl( - file_get_contents(dirname(__FILE__) . '/../data/ca.pem')); +if (!array_key_exists('server_host_override', $args)) { + $args['server_host_override'] = 'foo.test.google.fr'; +} + +$ssl_cert_file = getenv('SSL_CERT_FILE'); +if (!$ssl_cert_file) { + $ssl_cert_file = dirname(__FILE__) . '/../data/ca.pem'; +} + +$credentials = Grpc\Credentials::createSsl(file_get_contents($ssl_cert_file)); + +$opts = [ + 'grpc.ssl_target_name_override' => $args['server_host_override'], + 'credentials' => $credentials, + ]; + +if (array_key_exists('oauth_scope', $args)) { + $auth = Google\Auth\ApplicationDefaultCredentials::getCredentials( + $args['oauth_scope']); + $opts['update_metadata'] = $auth->getUpdateMetadataFunc(); +} + $stub = new grpc\testing\TestServiceClient( new Grpc\BaseStub( $server_address, - [ - 'grpc.ssl_target_name_override' => 'foo.test.google.fr', - 'credentials' => $credentials - ])); + $opts)); echo "Connecting to $server_address\n"; echo "Running test case $args[test_case]\n"; -switch($args['test_case']) { +switch ($args['test_case']) { case 'empty_unary': emptyUnary($stub); break; @@ -242,6 +298,9 @@ switch($args['test_case']) { case 'cancel_after_first_response': cancelAfterFirstResponse($stub); break; + case 'service_account_creds': + serviceAccountCreds($stub, $args); + break; default: exit(1); } diff --git a/src/python/src/setup.py b/src/python/src/setup.py index 7149a9eb85..7675049677 100644 --- a/src/python/src/setup.py +++ b/src/python/src/setup.py @@ -86,7 +86,7 @@ _PACKAGE_DIRECTORIES = { setuptools.setup( name='grpcio', - version='0.5.0a0', + version='0.5.0a1', ext_modules=[_EXTENSION_MODULE], packages=list(_PACKAGES), package_dir=_PACKAGE_DIRECTORIES, diff --git a/templates/Makefile.template b/templates/Makefile.template index fe455d1c20..1e7a2a49bd 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) @@ -188,7 +197,7 @@ LD_gcov = gcc LDXX_gcov = g++ CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -DEFINES_gcov = NDEBUG +DEFINES_gcov = _DEBUG DEBUG # General settings. @@ -197,6 +206,7 @@ DEFINES_gcov = NDEBUG prefix ?= /usr/local PROTOC = protoc +DTRACE = dtrace CONFIG ?= opt CC = $(CC_$(CONFIG)) CXX = $(CXX_$(CONFIG)) @@ -364,6 +374,8 @@ PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perfto PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS) PROTOC_CHECK_CMD = which protoc > /dev/null PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 +DTRACE_CHECK_CMD = which dtrace > /dev/null +SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) ifeq ($(OPENSSL_REQUIRES_DL),true) OPENSSL_ALPN_CHECK_CMD += -ldl @@ -396,6 +408,18 @@ else HAS_VALID_PROTOC = false endif +# Check for Systemtap (https://sourceware.org/systemtap/), first by making sure <sys/sdt.h> is present +# in the system and secondly by checking for the "dtrace" binary (on Linux, this is part of the Systemtap +# distribution. It's part of the base system on BSD/Solaris machines). +HAS_SYSTEMTAP_HEADERS = $(shell $(SYSTEMTAP_HEADERS_CHECK_CMD) 2> /dev/null && echo true || echo false) +HAS_DTRACE = $(shell $(DTRACE_CHECK_CMD) 2> /dev/null && echo true || echo false) +HAS_SYSTEMTAP = false +ifeq ($(HAS_SYSTEMTAP_HEADERS),true) +ifeq ($(HAS_DTRACE),true) +HAS_SYSTEMTAP = true +endif +endif + ifeq ($(wildcard third_party/openssl/ssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else @@ -575,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 @@ -863,6 +898,18 @@ endif % endfor +ifeq ($(CONFIG),stapprof) +src/core/profiling/stap_timers.c: $(GENDIR)/src/core/profiling/stap_probes.h +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.h: systemtap_dep_error stop +endif +endif + $(OBJDIR)/$(CONFIG)/%.o : %.c $(E) "[C] Compiling $<" $(Q) mkdir -p `dirname $@` @@ -883,7 +930,6 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc $(Q) mkdir -p `dirname $@` $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< - install: install_c install_cxx install-plugins install-certs verify-install install_c: install-headers_c install-static_c install-shared_c diff --git a/test/build/systemtap.c b/test/build/systemtap.c new file mode 100644 index 0000000000..66ff38ebd6 --- /dev/null +++ b/test/build/systemtap.c @@ -0,0 +1,42 @@ +/* + * + * 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 <sys/sdt.h> + +#ifndef _SYS_SDT_H +#error "_SYS_SDT_H not defined, despite <sys/sdt.h> being present." +#endif + +int main() { + return 0; +} diff --git a/test/core/profiling/mark_timings.stp b/test/core/profiling/mark_timings.stp new file mode 100644 index 0000000000..0c0a417faf --- /dev/null +++ b/test/core/profiling/mark_timings.stp @@ -0,0 +1,40 @@ +/* This script requires a command line argument, to be used in the "process" + * probe definition. + * + * For a statically build binary, that'd be the name of the binary itself. + * For dinamically built ones, point to the location of the libgprc.so being + * used. */ + +global starts, times, times_per_tag + +probe process(@1).mark("timing_ns_begin") { + starts[$arg1, tid()] = gettimeofday_ns(); +} + +probe process(@1).mark("timing_ns_end") { + tag = $arg1 + t = gettimeofday_ns(); + if (s = starts[tag, tid()]) { + times[tag, tid()] <<< t-s; + delete starts[tag, tid()]; + } +} + +probe end { + printf("%15s %9s %10s %10s %10s %10s\n", "tag", "tid", "count", + "min(ns)", "avg(ns)", "max(ns)"); + foreach ([tag+, tid] in times) { + printf("%15X %9d %10d %10d %10d %10d\n", tag, tid, @count(times[tag, tid]), + @min(times[tag, tid]), @avg(times[tag, tid]), @max(times[tag, tid])); + } + + printf("Per tag average of averages\n"); + foreach ([tag+, tid] in times) { + times_per_tag[tag] <<< @avg(times[tag, tid]); + } + printf("%15s %10s %10s\n", "tag", "count", "avg(ns)"); + foreach ([tag+] in times_per_tag) { + printf("%15X %10d %10d\n", tag, @count(times_per_tag[tag]), + @avg(times_per_tag[tag])); + } +} diff --git a/test/core/profiling/timers_test.c b/test/core/profiling/timers_test.c index 55e59c969e..12b08c115e 100644 --- a/test/core/profiling/timers_test.c +++ b/test/core/profiling/timers_test.c @@ -76,8 +76,8 @@ void test_log_events(int num_seqs) { int main(int argc, char **argv) { grpc_test_init(argc, argv); - grpc_timers_log_global_init(); + grpc_timers_global_init(); test_log_events(1000000); - grpc_timers_log_global_destroy(); + grpc_timers_global_destroy(); return 0; } diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index 38920bb15e..0007f49422 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -399,7 +399,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 edce8d9652..bd467e06c8 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -211,7 +211,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 d129105107..c1572259ab 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -344,7 +344,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 daca2c0c5a..0bee095da3 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -154,7 +154,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"> |