Improving string builder growth and host allocator tracing. (#14557)

Differentiated tracing makes it easier to track reallocs and it
highlighted some inefficient growth. String building should never be on
a critical path in a real app but it's still better to avoid the silly
reallocs.
diff --git a/runtime/src/iree/base/allocator.c b/runtime/src/iree/base/allocator.c
index df537bb..c162dd2 100644
--- a/runtime/src/iree/base/allocator.c
+++ b/runtime/src/iree/base/allocator.c
@@ -78,9 +78,22 @@
                             "allocations must be >0 bytes");
   }
 
-  IREE_TRACE_ZONE_BEGIN(z0);
-
   void* existing_ptr = *inout_ptr;
+
+  IREE_TRACE(iree_zone_id_t z0 = 0);
+  IREE_TRACE({
+    if (existing_ptr && command == IREE_ALLOCATOR_COMMAND_REALLOC) {
+      IREE_TRACE_ZONE_BEGIN_NAMED(z0_named, "iree_allocator_system_realloc");
+      z0 = z0_named;
+    } else if (command == IREE_ALLOCATOR_COMMAND_CALLOC) {
+      IREE_TRACE_ZONE_BEGIN_NAMED(z0_named, "iree_allocator_system_calloc");
+      z0 = z0_named;
+    } else {
+      IREE_TRACE_ZONE_BEGIN_NAMED(z0_named, "iree_allocator_system_malloc");
+      z0 = z0_named;
+    }
+  });
+
   void* new_ptr = NULL;
   if (existing_ptr && command == IREE_ALLOCATOR_COMMAND_REALLOC) {
     new_ptr = realloc(existing_ptr, byte_length);
@@ -103,7 +116,7 @@
   IREE_TRACE_ALLOC(new_ptr, byte_length);
 
   *inout_ptr = new_ptr;
-  IREE_TRACE_ZONE_END(z0);
+  IREE_TRACE(IREE_TRACE_ZONE_END(z0));
   return iree_ok_status();
 }
 
diff --git a/runtime/src/iree/base/string_builder.c b/runtime/src/iree/base/string_builder.c
index 2aa6994..3056ae4 100644
--- a/runtime/src/iree/base/string_builder.c
+++ b/runtime/src/iree/base/string_builder.c
@@ -79,23 +79,24 @@
 
 IREE_API_EXPORT iree_status_t iree_string_builder_reserve(
     iree_string_builder_t* builder, iree_host_size_t minimum_capacity) {
-  iree_host_size_t new_capacity = builder->capacity;
-  if (builder->capacity < minimum_capacity) {
-    new_capacity =
-        iree_host_align(minimum_capacity, IREE_STRING_BUILDER_ALIGNMENT);
-  }
-  if (builder->capacity >= new_capacity) {
+  if (IREE_LIKELY(builder->capacity >= minimum_capacity)) {
     // Already at/above the requested minimum capacity.
     return iree_ok_status();
-  } else if (iree_allocator_is_null(builder->allocator)) {
-    // No allocator provided and the builder cannot grow.
+  }
+
+  // If no allocator was provided the builder cannot grow.
+  if (iree_allocator_is_null(builder->allocator)) {
     return iree_make_status(
         IREE_STATUS_RESOURCE_EXHAUSTED,
         "non-growable builder capacity exceeded (capacity=%" PRIhsz
-        "; requested=%" PRIhsz ", adjusted=%" PRIhsz ")",
-        builder->capacity, minimum_capacity, new_capacity);
+        "; requested>=%" PRIhsz ")",
+        builder->capacity, minimum_capacity);
   }
 
+  // Grow by 2x. Note that the current capacity may be zero.
+  iree_host_size_t new_capacity = iree_max(
+      builder->capacity * 2,
+      iree_host_align(minimum_capacity, IREE_STRING_BUILDER_ALIGNMENT));
   IREE_RETURN_IF_ERROR(iree_allocator_realloc(builder->allocator, new_capacity,
                                               (void**)&builder->buffer));
   builder->buffer[builder->size] = 0;