Frontend Development 18 min read

GaiaX Layout Solution: Flexbox and Stretch Engine Analysis

GaiaX, Alibaba Entertainment’s cross‑platform dynamic UI framework, adopts Flexbox implemented with the Rust‑based Stretch engine to deliver millisecond‑level layout latency on phones, tablets, OTT, Macs and IoT devices, while fixing iOS 32‑bit crashes, redefining aspect‑ratio logic, adding thread‑safe wrappers and extensive tests, and open‑sourcing the extended library.

Youku Technology
Youku Technology
Youku Technology
GaiaX Layout Solution: Flexbox and Stretch Engine Analysis

GaiaX (盖亚) is a native dynamic layout framework extensively used within Alibaba Entertainment. It aims to provide high‑performance, stable, and easy‑to‑use UI rendering across a wide range of devices, including phones, tablets, OTT, Macs, car‑head units, and other screen‑enabled IoT devices.

The framework adopts Flexbox as its core layout technique because Flexbox already solves responsive layout challenges in browsers. Extensive performance tests comparing single‑layer and multi‑layer nesting demonstrated that Flexbox meets GaiaX’s latency requirements (measured in milliseconds), leading the team to select Flexbox as the primary layout solution.

To implement Flexbox, the open‑source Rust library Stretch was chosen. Stretch offers a small binary size, multi‑threaded computation, and cross‑platform support (iOS, Android, JavaScript, etc.). Its Rust implementation provides memory safety, high runtime performance without a garbage collector, and native multithreading.

Key technical analyses and solutions:

iOS 32‑bit crash: The crash originated from the Rust macro _modsi3 performing a modulo operation with a zero divisor. The fix involved renaming the offending symbols in the static library and adding extensive unit tests.

Aspect‑ratio handling: The original Stretch logic tied aspect‑ratio calculations to the container’s main axis, causing confusion. The team redefined aspect‑ratio as a simple width/height ratio, independent of layout direction, and updated the calculation functions accordingly.

Thread safety: Stretch’s internal data structures (nodes, forest) were not thread‑safe, leading to crashes during concurrent modifications. A singleton wrapper with locking was introduced, and all node operations were serialized.

Representative code snippets are shown below.

if growing {
for target in &mut unfrozen {
let child: &mut FlexItem = target;
if free_space.is_normal() && sum_flex_grow > 0.0 {
let grow_after = child.flex_basis + free_space * (self.nodes[child.node].style.flex_grow / sum_flex_grow);
child.target_size.set_main(dir, grow_after);
}
}
}
if shrinking && sum_flex_shrink > 0.0 {
let sum_scaled_shrink_factor: f32 = unfrozen
        .iter()
        .map(|child: &&mut FlexItem| {
let child_style: Style = self.nodes[child.node].style;
child.inner_flex_basis * child_style.flex_shrink
})
        .sum();
for target in &mut unfrozen {
let child: &mut FlexItem = target;
let scaled_shrink_factor = child.inner_flex_basis * self.nodes[child.node].style.flex_shrink;
if free_space.is_normal() && sum_scaled_shrink_factor > 0.0 {
let shrink_after = child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor);
child.target_size.set_main(dir, shrink_after)
}
}
}
// fix: aspect_ratio_both_dimensions_defined_column
fn get_aspect_ratio_size(child_style: &Style, target_size: Size<Number>) -> Size<Number> {
return Size {
width: Forest::get_aspect_ratio_width(child_style, target_size),
height: Forest::get_aspect_ratio_height(child_style, target_size),
};
}
// fix: aspect_ratio_both_dimensions_defined_column
fn get_aspect_ratio_height(child_style: &Style, target_size: Size<Number>) -> Number {
if target_size.width.is_defined() && child_style.aspect_ratio.is_defined() {
let width = target_size.width.or_else(0.0);
let aspect_ratio = child_style.aspect_ratio.or_else(0.0);
return Number::Defined(width / aspect_ratio);
}
return target_size.height;
}
fn get_aspect_ratio_width(child_style: &Style, target_size: Size<Number>) -> Number {
if !target_size.width.is_defined() && target_size.height.is_defined() && child_style.aspect_ratio.is_defined() {
let height = target_size.height.or_else(0.0);
let aspect_ratio = child_style.aspect_ratio.or_else(0.0);
return Number::Defined(height * aspect_ratio);
}
return target_size.width;
}

Thread‑safety wrappers were added to the Stretch API, for example:

// GXStretch singleton
+ (instancetype)stretch{
static GXStretch *stretch = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (nil == stretch) {
stretch = [[GXStretch alloc] init];
}
});
return stretch;
}
// add child with lock
- (void)addChild:(void *)child forNode:(void *)node{
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
stretch_node_add_child(_stretchptr, node, child);
dispatch_semaphore_signal(_semaphore);
}

Extensive unit tests were written to verify the correctness of the new aspect‑ratio logic, thread‑safe operations, and performance characteristics. An example test for aspect‑ratio correctness:

#[test]
fn aspect_ratio_cross_defined() {
let mut stretch = Stretch::new();
let root = stretch.new_node(Style {
size: Size { width: Dimension::Points(100.0), height: Dimension::Points(100.0) },
..Default::default()
}, &[]).unwrap();
let root_child0 = stretch.new_node(Style {
size: Size { width: Dimension::Points(50.0), ..Default::default() },
aspect_ratio: Number::Defined(1.0),
..Default::default()
}, &[]).unwrap();
stretch.add_child(root, root_child0).unwrap();
stretch.compute_layout(root, Size { width: Number::Defined(375.0), height: Number::Defined(1000.0) }).unwrap();
assert_eq!(stretch.layout(root_child0).unwrap().size.width, 50.0);
assert_eq!(stretch.layout(root_child0).unwrap().size.height, 50.0);
}

In summary, the GaiaX team forked and extended Stretch, added many new features, and deepened their expertise in Rust. The open‑source effort continues, inviting developers to contribute and benefit from a robust cross‑platform dynamic UI solution.

The article concludes with a brief team introduction, links to the GaiaX GitHub repository, and a preview of the upcoming series of technical deep‑dives.

performancerustFlexboxlayout engineGaiaX
Youku Technology
Written by

Youku Technology

Discover top-tier entertainment technology here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.