Repository: open-telemetry/opentelemetry-java
File: sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkSpanBuilder.java (Java)

Code before:
    startEpochNanos = unit.toNanos(startTimestamp);
    return this;
  }

  @Override
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Span startSpan() {
    Context parentContext = parent == null ? Context.current() : parent;
    Span parentSpan = Span.fromContext(parentContext);
    SpanContext parentSpanContext = parentSpan.getSpanContext();
    String traceId;
    boolean isTraceIdRandom;
    IdGenerator idGenerator = tracerSharedState.getIdGenerator();
    String spanId = idGenerator.generateSpanId();

    Context parentContextForSampler = parentContext;
    if (!parentSpanContext.isValid()) {
      // New root span.
      traceId = idGenerator.generateTraceId();
      if (idGenerator.generatesRandomTraceIds()) {
        isTraceIdRandom = true;
        // Replace parentContext for sampling with a temporary one with RANDOM_TRACE_ID bit set
        parentContextForSampler =
            preparePrimordialContext(
                parentContext,
                TraceFlags.getDefault().withRandomTraceIdBit(),
                TraceState.getDefault());
      } else {
        isTraceIdRandom = false;
      }
    } else {
      // New child span.
      traceId = parentSpanContext.getTraceId();
      isTraceIdRandom = parentSpanContext.getTraceFlags().isTraceIdRandom();
    }
    List<LinkData> currentLinks = links;
    List<LinkData> immutableLinks =
        currentLinks == null ? Collections.emptyList() : Collections.unmodifiableList(currentLinks);
    // Avoid any possibility to modify the links list by adding links to the Builder after the
    // startSpan is called. If that happens all the links will be added in a new list.
    links = null;
    Attributes immutableAttributes = attributes == null ? Attributes.empty() : attributes;
    SamplingResult samplingResult =
        tracerSharedState
            .getSampler()
            .shouldSample(
                parentContextForSampler,
                traceId,
                spanName,
                spanKind,
                immutableAttributes,

Review comment (performance):
Similar to [this comment](https://github.com/open-telemetry/opentelemetry-java/pull/8012/changes#r2733216232), we should use singletons here to avoid allocations on the hot path.

Ideally the entire primordial `Span` / `SpanContext` would be singletons. 

Code after:

  @Override
  public <T> SpanBuilder setAttribute(AttributeKey<T> key, T value) {
    if (key == null || key.getKey().isEmpty() || value == null) {
      return this;
    }
    attributes().put(key, value);
    return this;
  }

  @Override
  public SpanBuilder setStartTimestamp(long startTimestamp, TimeUnit unit) {
    if (startTimestamp < 0 || unit == null) {
      return this;
    }
    startEpochNanos = unit.toNanos(startTimestamp);
    return this;
  }

  @Override
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Span startSpan() {
    Context parentContext = parent == null ? Context.current() : parent;
    Span parentSpan = Span.fromContext(parentContext);
    SpanContext parentSpanContext = parentSpan.getSpanContext();
    String traceId;
    boolean isTraceIdRandom;
    IdGenerator idGenerator = tracerSharedState.getIdGenerator();
    String spanId = idGenerator.generateSpanId();

    Context parentContextForSampler = parentContext;
    if (!parentSpanContext.isValid()) {
      // New root span.
      traceId = idGenerator.generateTraceId();
      if (idGenerator.generatesRandomTraceIds()) {
        isTraceIdRandom = true;
        // Replace parentContext for sampling with one with RANDOM_TRACE_ID bit set
        parentContextForSampler = ROOT_CONTEXT_WITH_RANDOM_TRACE_ID_BIT;
      } else {
        isTraceIdRandom = false;
      }
    } else {
      // New child span.
      traceId = parentSpanContext.getTraceId();
      isTraceIdRandom = parentSpanContext.getTraceFlags().isTraceIdRandom();
    }
    List<LinkData> currentLinks = links;
    List<LinkData> immutableLinks =
        currentLinks == null ? Collections.emptyList() : Collections.unmodifiableList(currentLinks);
    // Avoid any possibility to modify the links list by adding links to the Builder after the
    // startSpan is called. If that happens all the links will be added in a new list.