Skip to content

[LUM-718] perf: flatten inner view hierarchies (MarkdownSegmentView, AssistantProgressView)#23982

Merged
Jasonnnz merged 4 commits into
mainfrom
devin/LUM-718-1775576262
Apr 8, 2026
Merged

[LUM-718] perf: flatten inner view hierarchies (MarkdownSegmentView, AssistantProgressView)#23982
Jasonnnz merged 4 commits into
mainfrom
devin/LUM-718-1775576262

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Apr 7, 2026

Reduces per-cell layout depth (~6-8 nodes) in chat bubble inner views by removing redundant wrapper views and merging modifier chains across AssistantProgressView, ChatBubbleToolStatusView, and MarkdownSegmentView — targeting the PaddingLayout → PaddingLayout → ZStackLayout nesting hotspots identified in spin dumps. Patterns applied: merge consecutive .padding() into single EdgeInsets, remove unnecessary Group/VStack wrappers, flatten nested VStack > VStack, replace HStack + Spacer with .frame(alignment:), and use pre-shaped .background(RoundedRectangle.fill(color)) instead of .background(color).


@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@devin-ai-integration devin-ai-integration Bot force-pushed the devin/LUM-718-1775576262 branch from bd5f6c4 to 693ee88 Compare April 7, 2026 15:55
@Jasonnnz Jasonnnz marked this pull request as ready for review April 7, 2026 17:17
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 693ee88531

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1039 to 1040
.fill(VColor.surfaceOverlay.opacity(0.6))
.stroke(VColor.borderBase, lineWidth: 0.5)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Replace invalid fill→stroke chain in output block background

The new background builder chains .stroke(...) directly after .fill(...) on RoundedRectangle, but in SwiftUI fill returns some View, so this chain is not valid shape API usage and will fail when compiling the macOS client target. This makes the change a build blocker for environments that build clients/macos; use a separate overlay/background composition instead of fill().stroke().

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a false positive. The project targets macOS 14+ (confirmed by usage of ViewThatFits, onGeometryChange, and other macOS 14+ APIs throughout the codebase). In macOS 14 / iOS 17, Apple added Shape.fill(_:).stroke(_:lineWidth:) as a first-class chaining API — see Apple Developer Documentation: Shape.stroke(_:lineWidth:). The .fill().stroke() chain compiles and works correctly on macOS 14+.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot force-pushed the devin/LUM-718-1775576262 branch from fe6ecd3 to 6a9a0ce Compare April 7, 2026 20:00
devin-ai-integration[bot]

This comment was marked as resolved.

@Jasonnnz
Copy link
Copy Markdown
Contributor

Jasonnnz commented Apr 8, 2026

Spin Dump Comparison: main vs PR devin/LUM-718

_PaddingLayout Nesting Depth (bubbleChrome → inner view)

┌───────────────────────────────────────┬────────────┬───────────┬───────────┐
│ Metric │ main │ PR │ Delta │
├───────────────────────────────────────┼────────────┼───────────┼───────────┤
│ PaddingLayout depth in deepest chain │ 8 │ 3 │ -5 nodes │
├───────────────────────────────────────┼────────────┼───────────┼───────────┤
│ Total layout modifier depth │ 47 │ 20 │ -27 nodes │
├───────────────────────────────────────┼────────────┼───────────┼───────────┤
│ PaddingLayout occurrences (call tree) │ 14 │ 9 │ -5 │
├───────────────────────────────────────┼────────────┼───────────┼───────────┤
│ Total PaddingLayout samples │ 74 │ 18 │ -76% │
├───────────────────────────────────────┼────────────┼───────────┼───────────┤
│ Heaviest single PaddingLayout │ 23 samples │ 3 samples │ -87% │
└───────────────────────────────────────┴────────────┴───────────┴───────────┘

Key Findings

  1. PaddingLayout nesting reduced from 8 to 3 levels — a reduction of 5 nodes in the deepest call chain. This is
    in the expected range (you predicted 6-8 reduction; 5 is close, and the difference may depend on which cell types
    were being measured during the 5-second sample window).
  2. Total layout modifier depth cut by more than half (47 → 20) — this means each cell's layout pass traverses
    significantly fewer SwiftUI layout nodes, reducing CPU time per frame.
  3. 76% fewer PaddingLayout samples overall (74 → 18) — the sampler caught PaddingLayout doing sizing work far
    less frequently on the PR branch, confirming the flattened hierarchy is cheaper to lay out.
  4. Heaviest single PaddingLayout path dropped from 23 to 3 samples — the dominant hot path through PaddingLayout
    is nearly eliminated.

devin-ai-integration Bot and others added 4 commits April 8, 2026 17:26
Reduce per-cell layout depth by flattening redundant modifier chains and
view wrappers in chat bubble inner views:

- Remove unnecessary Group wrappers around switch statements in
  CompactPermissionChip and ChatBubbleToolStatusView.compactPermissionChip
  (ViewBuilder handles switches natively since Swift 5.3)
- Remove single-child VStack wrapper around stepTitle Text in StepDetailRow
- Flatten nested VStack > VStack in stepDetailContent technical details
  (both had identical spacing: VSpacing.xs)
- Combine .background() + .clipShape() + .overlay() into single
  .background {} with fill+stroke in outputBlock
- Replace VStack > HStack > Spacer with HStack + .frame(alignment:) in
  ChatBubbleToolStatusView trailing status
- Merge two .padding() calls into single EdgeInsets in CodeBlockView header

Estimated depth reduction: ~8-10 layout nodes per cell.

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>
… corners

The .clipShape(RoundedRectangle) is needed to clip scrollable content
(e.g., 500+ line outputs in the ScrollView) to the rounded background.
Without it, text near corners visually bleeds past the rounded border.

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>
The stroke was inside .background {} which gets clipped by .clipShape(),
halving the visible border width (0.25pt instead of 0.5pt). Move the
stroke to .overlay() after .clipShape() so the full border is drawn on
top, matching the existing pattern at line 758-762.

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>
…copy buttons

Pre-existing issue: VCopyButton instances used .opacity(isHovered ? 1 : 0)
without .allowsHitTesting or .accessibilityHidden guards. When opacity is 0,
the button was still tappable and visible to VoiceOver. Added both guards
to the two VCopyButton instances in CodeBlockView (language header and
no-language overlay).

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>
@devin-ai-integration devin-ai-integration Bot force-pushed the devin/LUM-718-1775576262 branch from d76ad62 to 19cee44 Compare April 8, 2026 17:27
@Jasonnnz
Copy link
Copy Markdown
Contributor

Jasonnnz commented Apr 8, 2026

@codex review

@Jasonnnz
Copy link
Copy Markdown
Contributor

Jasonnnz commented Apr 8, 2026

@devin review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Jasonnnz Jasonnnz merged commit 91272fe into main Apr 8, 2026
6 checks passed
@Jasonnnz Jasonnnz deleted the devin/LUM-718-1775576262 branch April 8, 2026 17:46
noanflaherty pushed a commit that referenced this pull request Apr 8, 2026
…AssistantProgressView) (#23982)

* [LUM-718] perf: flatten inner view hierarchies to reduce layout depth

Reduce per-cell layout depth by flattening redundant modifier chains and
view wrappers in chat bubble inner views:

- Remove unnecessary Group wrappers around switch statements in
  CompactPermissionChip and ChatBubbleToolStatusView.compactPermissionChip
  (ViewBuilder handles switches natively since Swift 5.3)
- Remove single-child VStack wrapper around stepTitle Text in StepDetailRow
- Flatten nested VStack > VStack in stepDetailContent technical details
  (both had identical spacing: VSpacing.xs)
- Combine .background() + .clipShape() + .overlay() into single
  .background {} with fill+stroke in outputBlock
- Replace VStack > HStack > Spacer with HStack + .frame(alignment:) in
  ChatBubbleToolStatusView trailing status
- Merge two .padding() calls into single EdgeInsets in CodeBlockView header

Estimated depth reduction: ~8-10 layout nodes per cell.

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>

* [LUM-718] Restore .clipShape() to prevent content overflow at rounded corners

The .clipShape(RoundedRectangle) is needed to clip scrollable content
(e.g., 500+ line outputs in the ScrollView) to the rounded background.
Without it, text near corners visually bleeds past the rounded border.

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>

* [LUM-718] Separate stroke into overlay to prevent clipping

The stroke was inside .background {} which gets clipped by .clipShape(),
halving the visible border width (0.25pt instead of 0.5pt). Move the
stroke to .overlay() after .clipShape() so the full border is drawn on
top, matching the existing pattern at line 758-762.

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>

* [LUM-718] Add hit testing and accessibility guards to opacity-hidden copy buttons

Pre-existing issue: VCopyButton instances used .opacity(isHovered ? 1 : 0)
without .allowsHitTesting or .accessibilityHidden guards. When opacity is 0,
the button was still tappable and visible to VoiceOver. Added both guards
to the two VCopyButton instances in CodeBlockView (language header and
no-language overlay).

Co-Authored-By: Jason Zhou <jasonczhou3@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Jason Zhou <jasonczhou3@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant