@Override int sizeOfValue(Span span) {
      int sizeOfSpan = TRACE_ID.sizeInBytes(span.traceId());
      sizeOfSpan += PARENT_ID.sizeInBytes(span.parentId());
      sizeOfSpan += ID.sizeInBytes(span.id());
      sizeOfSpan += KIND.sizeInBytes(span.kind() != null ? 1 : 0);
      sizeOfSpan += NAME.sizeInBytes(span.name());
      sizeOfSpan += TIMESTAMP.sizeInBytes(span.timestampAsLong());
      sizeOfSpan += DURATION.sizeInBytes(span.durationAsLong());
      sizeOfSpan += LOCAL_ENDPOINT.sizeInBytes(span.localEndpoint());
      sizeOfSpan += REMOTE_ENDPOINT.sizeInBytes(span.remoteEndpoint());

      List<Annotation> annotations = span.annotations();
      for (Annotation annotation : annotations) {
        sizeOfSpan += ANNOTATION.sizeInBytes(annotation);
      }

      Map<String, String> tags = span.tags();
      int tagCount = tags.size();
      if (tagCount > 0) { // avoid allocating an iterator when empty
        for (Map.Entry<String, String> entry : tags.entrySet()) {
          sizeOfSpan += TAG.sizeInBytes(entry);
        }
      }

      sizeOfSpan += DEBUG.sizeInBytes(Boolean.TRUE.equals(span.debug()));
      sizeOfSpan += SHARED.sizeInBytes(Boolean.TRUE.equals(span.shared()));
      return sizeOfSpan;
    }
Contributes to a builder as opposed to reading values directly. Avoids allocation.
zipkin/src/main/java/zipkin2/internal/Proto3ZipkinFields.java