Skip to content

Reuse UTF-8 conversion work across repeated CFFI string access #322

Closed

Description

@dimensionscape

Repeated CFFI val_string calls on the same boxed Unicode string convert and allocate the complete UTF-8 representation every time. The source is unchanged, but each access creates another GC-managed conversion buffer.

Confirmed on fe67557, Windows x64, Haxe 4.3.7, MSVC 19.44, smart strings, default collector:

  • Build one string containing 262,144 copies of U+03BB and box it once as Dynamic.
  • Its UTF-8 representation is 524,288 bytes.
  • Resolve the existing val_string entry through hx_cffi once, outside timing.
  • Call it 256 times on that same boxed object. Check the leading/trailing bytes and terminator after each access.
  • Keep automatic GC enabled and count observed mark-ID changes across individual calls.

Five samples took 94.13, 94.91, 97.43, 99.22 and 97.38 ms. Every sample observed three collections. A full collection ran before each sample. Source construction and boxing are outside timing.

Those 256 accesses request about 128 MiB of temporary UTF-8 output storage according to the allocation path, despite using a single unchanged input. An ASCII string uses its existing byte storage and did not trigger collections in the same access loop. This is a comparison of representation paths, not an application-wide speedup estimate or a claim that Unicode encoding itself can be free.

The path is val_string -> Object::__CStr -> String::utf8_str -> TConvertToUTF8. The wide conversion sizes the output, allocates it and encodes all code units for each access. Boxed StringData currently retains only the original String.

Investigate reuse of UTF-8 views for immutable owned strings, or conversion storage reusable through the CFFI boundary. Any cache must have correct GC marking and moving support, safe concurrent initialization, and bounded lifetime. Preserve raw borrowed-buffer semantics: the native pointer-wrapping String constructor means it is not safe to assume every native String has immutable owned backing. val_dup_string must continue returning an independent writable copy. The goal is to reduce repeated work on normal immutable Haxe strings without requiring compiler or standard-library changes.

Added a local conventional regression before implementation work, test/regression/CffiRepeatedUtf8View. It checks complete UTF-8 contents, repeats accesses on a warmed boxed string, checks conversion-buffer growth, mutates a writable duplicate, and verifies the original after full collection. Current output:

repeated Unicode views contain complete UTF-8: true
repeated views avoid accumulating conversion buffers: false
writable duplicate leaves the original view unchanged: true
boxed string remains usable after collection: true

The allocation-growth check expresses the proposed optimization, not a preexisting pointer-identity guarantee. There are no timing assertions or runtime implementation changes. This is encoding an existing wide string repeatedly, separate from the UTF-8 decoding copy in #196 and the unused numeric-input suffix conversions in #284.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions