Skip to content

[Performance]: retire Span recording to eliminate IsMOCtledSpan contention #25839

Description

@LeftHandCold

Summary

MO no longer consumes internal Span records, but the old request path still entered the Span implementation and queried a global controlled-span map protected by a mutex. This issue tracks retiring that unused recording path while preserving the observability data that MO still depends on.

Correction to the original profile conclusion

The flame graphs and the summary image do not prove that "trace consumes 60% CPU" or that trace is the main performance bottleneck.

The reported sync.Mutex.Unlock / IsMOCtledSpan percentages are attribution within a mutex blocking-delay profile. They mean that this lock accounted for a large share of sampled waiting time in those captures; they are not CPU percentages and cannot be added to frontend percentages as total CPU usage.

The supported conclusion is narrower: IsMOCtledSpan was a real, avoidable concurrency hotspot in the tested high-concurrency point-select/read-only/insert workloads. Removing it should reduce contention, but SQL execution, storage reads, compilation/planning, transaction work, syscalls, and GC remain the main workload-dependent costs.

Final decision

Retire the Span recording implementation, not the whole trace/observability subsystem.

Removed by PR #25841:

  • MOTracer, MOSpan, MOHungSpan
  • Span batch processor/exporter and Span-only buffering
  • controlled-span global maps/mutex
  • Span-triggered timers and profile capture
  • Span-specific tests
  • runtime ability to re-enable Span through configuration

Preserved:

  • StatementInfo, statement status/error information, and CU accounting
  • structured/raw log export
  • error export
  • SpanContext, context helpers, and RPC wire layout
  • trace/span ID fields in retained log/error records
  • existing span_info schema/view for upgrade compatibility
  • shared collector lifecycle and graceful flush

StatementInfo does not depend on a recorded MOSpan; it has its own statement, transaction, session, status, error, and CU fields. Therefore it is preserved directly rather than filled with artificial Span values.

Compatibility

  • Code default remains disable-span=true.
  • Explicit disable-span=false is still accepted but cannot re-enable the retired implementation.
  • enable-span-profile, long-span-time, and enable-trace-debug remain accepted compatibility no-ops.
  • CN/TN TraceSpan control calls return span tracing is no longer supported.
  • No new span_info rows are created.
  • No schema migration is required; rollback is a binary rollback.

Evidence

Controlled ABBA test on the same machine/configuration/data/workload:

  • 128 concurrent clients, 10 measured iterations per side
  • baseline: 79,393 QPS
  • Span-disabled candidate: 81,463 QPS
  • delta: +2.61%
  • baseline IsMOCtledSpan mutex-delay attribution: 43.77% / 40.58%
  • candidate exact focus: no samples

This verifies a positive effect for the tested workload, but does not claim a universal 2.61% improvement or identify Span as the main CPU bottleneck.

Final implementation validation on machine 10.222.1.50, commit 62c1c608ba, using an explicit disable-span=false configuration:

  • Statement, raw-log, and error records continued to increase.
  • Successful and failed marker statements retained status, error code, and CU.
  • The injected SQL error appeared in system.error_info.
  • span_info stayed unchanged at 3 -> 3.
  • TraceSpan control calls returned the retired-feature response.
  • A 1,000,000-query, concurrency-128 run completed successfully.
  • Mutex profile exact focus found no IsMOCtledSpan, MOTracer, MOSpan, or MOHungSpan samples.
  • Graceful shutdown flushed retained telemetry successfully.

Full implementation and three validation rounds: #25839 (comment)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions