From f00306666a13b7b6c63a7fe11ea81d69dbb98a7b Mon Sep 17 00:00:00 2001 From: "wangzekun.zekin" Date: Thu, 14 May 2026 20:14:54 +0800 Subject: [PATCH] perf(java): bind ipc debug log to config, use sonic for protocol json The Java IPC protocol unconditionally enabled debug logging on the reader and writer, causing each of the ~2.5k messages per parse to trigger a full JSON dump to stderr. Bind SetDebug to the existing JavaParserServer config so debug output is off by default. Switch the protocol layer to sonic for the four Unmarshal sites and one Marshal site. encoding/json was the dominant cost on the Go side (38% of CPU, 2s of unmarshal time on a 2k-class repo); sonic cuts the ReadMessage path by ~75%. Combined effect on travel-business (2153 java files): wall 61.0s -> 53.4s (-12.5%) user 6:37 -> 5:30 Go CPU 8.48% -> 5.83% --- lang/java/ipc/protocol.go | 15 ++++++++------- lang/java/ipc/server.go | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lang/java/ipc/protocol.go b/lang/java/ipc/protocol.go index ea289554..64345794 100644 --- a/lang/java/ipc/protocol.go +++ b/lang/java/ipc/protocol.go @@ -23,6 +23,7 @@ import ( "io" "log" + "github.com/bytedance/sonic" "github.com/cloudwego/abcoder/lang/java/pb" ) @@ -133,7 +134,7 @@ func (pr *ProtocolReader) ReadMessage() (*pb.Message, error) { Payload json.RawMessage `json:"payload,omitempty"` } var raw rawMessage - if err := json.Unmarshal(pr.buf, &raw); err != nil { + if err := sonic.Unmarshal(pr.buf, &raw); err != nil { if pr.debug { log.Printf("[Protocol] <<< Failed to unmarshal: %v", err) } @@ -156,7 +157,7 @@ func (pr *ProtocolReader) ReadMessage() (*pb.Message, error) { Payload json.RawMessage `json:"payload"` } var arRaw rawAnalyzeResponse - if err := json.Unmarshal(raw.Payload, &arRaw); err != nil { + if err := sonic.Unmarshal(raw.Payload, &arRaw); err != nil { return nil, fmt.Errorf("failed to unmarshal analyze_response payload: %w", err) } @@ -183,7 +184,7 @@ func (pr *ProtocolReader) ReadMessage() (*pb.Message, error) { if rm, ok := payload.(json.RawMessage); ok { ar.Payload = rm } else { - if err := json.Unmarshal(arRaw.Payload, payload); err != nil { + if err := sonic.Unmarshal(arRaw.Payload, payload); err != nil { return nil, fmt.Errorf("failed to unmarshal analyze_response inner payload (%s): %w", arRaw.PayloadType, err) } ar.Payload = payload @@ -192,21 +193,21 @@ func (pr *ProtocolReader) ReadMessage() (*pb.Message, error) { case pb.TYPE_ANALYZE_REQUEST: var req pb.AnalyzeRequest - if err := json.Unmarshal(raw.Payload, &req); err != nil { + if err := sonic.Unmarshal(raw.Payload, &req); err != nil { return nil, fmt.Errorf("failed to unmarshal analyze_request payload: %w", err) } msg.Payload = &req case pb.TYPE_STOP_REQUEST: var stop pb.StopRequest - if err := json.Unmarshal(raw.Payload, &stop); err != nil { + if err := sonic.Unmarshal(raw.Payload, &stop); err != nil { return nil, fmt.Errorf("failed to unmarshal stop_request payload: %w", err) } msg.Payload = &stop case pb.TYPE_HEARTBEAT: var hb pb.Heartbeat - if err := json.Unmarshal(raw.Payload, &hb); err != nil { + if err := sonic.Unmarshal(raw.Payload, &hb); err != nil { return nil, fmt.Errorf("failed to unmarshal heartbeat payload: %w", err) } msg.Payload = &hb @@ -247,7 +248,7 @@ func (pw *ProtocolWriter) SetDebug(enabled bool) { // WriteMessage writes a length-prefixed JSON Message. func (pw *ProtocolWriter) WriteMessage(msg *pb.Message) error { - data, err := json.Marshal(msg) + data, err := sonic.Marshal(msg) if err != nil { return fmt.Errorf("failed to marshal JSON message: %w", err) } diff --git a/lang/java/ipc/server.go b/lang/java/ipc/server.go index 16d492e4..04285d53 100644 --- a/lang/java/ipc/server.go +++ b/lang/java/ipc/server.go @@ -245,7 +245,7 @@ func (s *JavaParserServer) sendAnalyzeRequest(repoPath string, config *pb.Analyz } writer := NewProtocolWriter(s.conn) - writer.SetDebug(true) // Enable debug logging for sent messages + writer.SetDebug(s.config.Debug) if err := writer.WriteRequest(request); err != nil { return fmt.Errorf("failed to write analyze request: %w", err) } @@ -261,7 +261,7 @@ func (s *JavaParserServer) readResponses(ctx context.Context, responseChan chan< defer s.cleanup() reader := NewProtocolReader(s.conn) - reader.SetDebug(true) // Enable debug logging for received messages + reader.SetDebug(s.config.Debug) for { select {