You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by li...@apache.org on 2023/03/20 09:24:46 UTC

[skywalking-rover] branch main updated: Improve the performance of getting the goid in the Golang (#82)

This is an automated email from the ASF dual-hosted git repository.

liuhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-rover.git


The following commit(s) were added to refs/heads/main by this push:
     new de4c613  Improve the performance of getting the goid in the Golang (#82)
de4c613 is described below

commit de4c6132ba0afe4d033652a4367d890382610d36
Author: mrproliu <74...@qq.com>
AuthorDate: Mon Mar 20 17:24:39 2023 +0800

    Improve the performance of getting the goid in the Golang (#82)
---
 CHANGES.md                                         |  1 +
 bpf/include/api.h                                  | 10 +++++
 bpf/include/{goid.c => goid.h}                     | 49 ++++++++--------------
 bpf/include/symbol_offsets.h                       |  4 --
 bpf/profiling/continuous/go_tls.c                  |  2 +-
 bpf/profiling/network/go_tls.c                     |  2 +-
 bpf/profiling/offcpu.h                             |  7 +---
 .../continuous/checker/bpf/network/ssl.go          |  2 +-
 pkg/profiling/task/network/ssl.go                  |  2 +-
 pkg/tools/ssl/gotls.go                             | 11 +----
 10 files changed, 34 insertions(+), 56 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 6955adb..82cc739 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,7 @@ Release Notes.
 * Support OpenSSL 3.0.x.
 * Optimized the data structure in BPF.
 * Support continuous profiling.
+* Improve the performance when getting `goid` in eBPF.
 
 #### Bug Fixes
 * Fix HTTP method name in protocol analyzer
diff --git a/bpf/include/api.h b/bpf/include/api.h
index aac5cca..fa4aa16 100644
--- a/bpf/include/api.h
+++ b/bpf/include/api.h
@@ -45,4 +45,14 @@ typedef enum
 {
     true=1, false=0
 } bool;
+
+struct thread_struct {
+	long unsigned int fsbase;
+}   __attribute__((preserve_access_index));
+
+struct task_struct {
+	__u32 pid;
+    __u32 tgid;
+    struct thread_struct thread;
+}  __attribute__((preserve_access_index));
 #endif
\ No newline at end of file
diff --git a/bpf/include/goid.c b/bpf/include/goid.h
similarity index 55%
rename from bpf/include/goid.c
rename to bpf/include/goid.h
index 80c0813..92f0598 100644
--- a/bpf/include/goid.c
+++ b/bpf/include/goid.h
@@ -15,6 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#pragma once
+
+#include "api.h"
 #include "symbol_offsets.h"
 
 struct {
@@ -24,47 +27,29 @@ struct {
 	__type(value, __u64);
 } go_tgid_goid_map SEC(".maps");
 static __inline __u64 get_goid(__u64 id) {
-    __u64 *val;
-    val = bpf_map_lookup_elem(&go_tgid_goid_map, &id);
-    return !val ? 0 : *val;
-}
-static __inline void set_goid(__u64 id, __u64 goid) {
-    bpf_map_update_elem(&go_tgid_goid_map, &id, &goid, 0);
-}
-
-SEC("uprobe/casgstatus")
-int go_casgstatus(struct pt_regs* ctx) {
-    const void* sp = (const void*)PT_REGS_SP(ctx);
-    __u64* regs = go_regabi_regs(ctx);
-    if (regs == NULL) {
-       return 0;
-    }
-
-    __u64 id = bpf_get_current_pid_tgid();
     __u32 tgid = id >> 32;
     struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
     if (symaddrs == NULL) {
        return 0;
     }
 
-    // get runtime.g
-    void* gptr = NULL;
-    assign_go_tls_arg(&gptr, sizeof(gptr), symaddrs->casg_status_gp_loc, sp, regs);
-    if (gptr == NULL) {
+    // Get fsbase from `struct task_struct`.
+    const struct task_struct* task_ptr = (struct task_struct*)bpf_get_current_task();
+    if (!task_ptr) {
         return 0;
     }
 
-    // get goid in runtime.g
-    int64_t goid;
-    bpf_probe_read(&goid, sizeof(goid), gptr + symaddrs->gid_offset);
+    // thread local storage
+    const void* fs_base;
+    bpf_probe_read_kernel(&fs_base, sizeof(fs_base), &(task_ptr->thread.fsbase));
 
-    // newval in runtime.g
-    __u32 status;
-    assign_go_tls_arg(&status, sizeof(status), symaddrs->casg_status_new_val_loc, sp, regs);
+    __u64 g_addr;
+    // struct g location
+    int32_t g_addr_offset = -8;
+    bpf_probe_read_user(&g_addr, sizeof(void*), (void*)(fs_base + g_addr_offset));
 
-    // check the status is running
-    if (status == 2) {
-        set_goid(id, goid);
-    }
-    return 0;
+    // goid in struct g
+    __u64 goid;
+    bpf_probe_read_user(&goid, sizeof(void*), (void*)(g_addr + symaddrs->gid_offset));
+    return goid;
 }
\ No newline at end of file
diff --git a/bpf/include/symbol_offsets.h b/bpf/include/symbol_offsets.h
index 33b19ef..798b40c 100644
--- a/bpf/include/symbol_offsets.h
+++ b/bpf/include/symbol_offsets.h
@@ -84,10 +84,6 @@ struct go_tls_args_symaddr_t {
     __u64 tcp_conn_offset;
     __u64 is_client_offset;
 
-    // casg
-    struct go_tls_arg_location_t casg_status_gp_loc;
-    struct go_tls_arg_location_t casg_status_new_val_loc;
-
     // read
     struct go_tls_arg_location_t read_connection_loc;
     struct go_tls_arg_location_t read_buffer_loc;
diff --git a/bpf/profiling/continuous/go_tls.c b/bpf/profiling/continuous/go_tls.c
index 60ed538..87325ac 100644
--- a/bpf/profiling/continuous/go_tls.c
+++ b/bpf/profiling/continuous/go_tls.c
@@ -16,7 +16,7 @@
 // under the License.
 
 #include "go_tls.h"
-#include "goid.c"
+#include "goid.h"
 
 SEC("uprobe/go_tls_write")
 int go_tls_write(struct pt_regs* ctx) {
diff --git a/bpf/profiling/network/go_tls.c b/bpf/profiling/network/go_tls.c
index 3fde4a5..5dbaa59 100644
--- a/bpf/profiling/network/go_tls.c
+++ b/bpf/profiling/network/go_tls.c
@@ -16,7 +16,7 @@
 // under the License.
 
 #include "go_tls.h"
-#include "goid.c"
+#include "goid.h"
 
 SEC("uprobe/go_tls_write")
 int go_tls_write(struct pt_regs* ctx) {
diff --git a/bpf/profiling/offcpu.h b/bpf/profiling/offcpu.h
index cc5a73b..95332c1 100644
--- a/bpf/profiling/offcpu.h
+++ b/bpf/profiling/offcpu.h
@@ -44,9 +44,4 @@ struct {
 	__type(key, struct key_t);
 	__type(value, struct value_t);
 	__uint(max_entries, 10000);
-} counts SEC(".maps");
-
-struct task_struct {
-	__u32 pid;
-    __u32 tgid;
-}  __attribute__((preserve_access_index));
\ No newline at end of file
+} counts SEC(".maps");
\ No newline at end of file
diff --git a/pkg/profiling/continuous/checker/bpf/network/ssl.go b/pkg/profiling/continuous/checker/bpf/network/ssl.go
index 50261f4..747a95a 100644
--- a/pkg/profiling/continuous/checker/bpf/network/ssl.go
+++ b/pkg/profiling/continuous/checker/bpf/network/ssl.go
@@ -29,7 +29,7 @@ func addSSLProcess(pid int, linker *btf.Linker, bpf *bpfObjects) error {
 
 	register.Envoy(bpf.EnvoyTlsArgsSymaddrMap, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet)
 
-	register.GoTLS(bpf.GoTlsArgsSymaddrMap, bpf.GoCasgstatus, bpf.GoTlsWrite, bpf.GoTlsWriteRet, bpf.GoTlsRead, bpf.GoTlsReadRet)
+	register.GoTLS(bpf.GoTlsArgsSymaddrMap, bpf.GoTlsWrite, bpf.GoTlsWriteRet, bpf.GoTlsRead, bpf.GoTlsReadRet)
 
 	register.Node(bpf.OpensslSymaddrMap, nil, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet,
 		nil, nil, nil)
diff --git a/pkg/profiling/task/network/ssl.go b/pkg/profiling/task/network/ssl.go
index d3fd33e..0e23e7e 100644
--- a/pkg/profiling/task/network/ssl.go
+++ b/pkg/profiling/task/network/ssl.go
@@ -29,7 +29,7 @@ func addSSLProcess(pid int, loader *bpf.Loader) error {
 
 	register.Envoy(nil, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet)
 
-	register.GoTLS(loader.GoTlsArgsSymaddrMap, loader.GoCasgstatus, loader.GoTlsWrite, loader.GoTlsWriteRet, loader.GoTlsRead, loader.GoTlsReadRet)
+	register.GoTLS(loader.GoTlsArgsSymaddrMap, loader.GoTlsWrite, loader.GoTlsWriteRet, loader.GoTlsRead, loader.GoTlsReadRet)
 
 	register.Node(nil, loader.NodeTlsSymaddrMap, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet,
 		loader.NodeTlsRetSsl, loader.NodeTlsWrap, loader.NodeTlsWrapRet)
diff --git a/pkg/tools/ssl/gotls.go b/pkg/tools/ssl/gotls.go
index 2a88498..8a52ba8 100644
--- a/pkg/tools/ssl/gotls.go
+++ b/pkg/tools/ssl/gotls.go
@@ -62,10 +62,6 @@ type GoTLSSymbolAddress struct {
 	TCPConnOffset  uint64
 	IsClientOffset uint64
 
-	// casgstatus(goroutine status change) function relate locations
-	CasgStatusGPLoc     GoSymbolLocation
-	CasgStatusNEWValLoc GoSymbolLocation
-
 	// write function relate locations
 	WriteConnectionLoc GoSymbolLocation
 	WriteBufferLoc     GoSymbolLocation
@@ -79,7 +75,7 @@ type GoTLSSymbolAddress struct {
 	ReadRet1Loc       GoSymbolLocation
 }
 
-func (r *Register) GoTLS(symbolAddrMap *ebpf.Map, goIDChange, write, writeRet, read, readRet *ebpf.Program) {
+func (r *Register) GoTLS(symbolAddrMap *ebpf.Map, write, writeRet, read, readRet *ebpf.Program) {
 	r.addHandler("goTLS", func() (bool, error) {
 		buildVersionSymbol := r.searchSymbolInModules(r.modules, func(a, b string) bool {
 			return a == b
@@ -113,7 +109,6 @@ func (r *Register) GoTLS(symbolAddrMap *ebpf.Map, goIDChange, write, writeRet, r
 		}
 
 		exeFile := r.linker.OpenUProbeExeFile(pidExeFile)
-		exeFile.AddLinkWithType("runtime.casgstatus", true, goIDChange)
 		exeFile.AddGoLink(goTLSWriteSymbol, write, writeRet, elfFile)
 		exeFile.AddGoLink(goTLSReadSymbol, read, readRet, elfFile)
 		if e := r.linker.HasError(); e != nil {
@@ -201,10 +196,6 @@ func (r *Register) generateGOTLSSymbolOffsets(register *Register, elfFile *elf.F
 	assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSRuntimeG, "goid", &symbolAddresses.GIDOffset)
 	assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSConnSymbol, "isClient", &symbolAddresses.IsClientOffset)
 
-	// gid status change
-	assignError = r.assignGoTLSArgsLocation(assignError, gidStatusFunction, "gp", &symbolAddresses.CasgStatusGPLoc)
-	assignError = r.assignGoTLSArgsLocation(assignError, gidStatusFunction, "newval", &symbolAddresses.CasgStatusNEWValLoc)
-
 	// write
 	assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, "c", &symbolAddresses.WriteConnectionLoc)
 	assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, "b", &symbolAddresses.WriteBufferLoc)