Token导航 LogoToken导航

Agent Skill · 前端设计

makepad-2.0-performance(makepad 2 0 性能)

makepad-2.0-performance 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

makepad-2.0-performance 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,暂无第三方扫描结果,按安装量在前端设计类的 10,216 个 Skill 里排第 8,294。

总安装 297周安装 12GitHub Stars 737下载 93核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:makepad-2.0-performance(makepad 2 0 性能)
来源仓库:https://github.com/zhanghandong/makepad-skills
仓库路径:skills/makepad-2.0-performance
安装命令:
npx skills add https://github.com/zhanghandong/makepad-skills --skill makepad-2.0-performance
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/zhanghandong/makepad-skills --skill makepad-2.0-performance

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

用于处理 GitHub 仓库与协作信息,支持性能相关 Issue 和 PR 管理。适合在开发环境中围绕代码变更和协作事项进行整理。需确认仓库访问权限和维护状态,避免触发敏感操作。建议在操作前核对权限范围,防止误删或覆盖重要代码。

makepad-2.0-performance 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/makepad-2.0-performance

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/zhanghandong/makepad-skills --skill makepad-2.…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

makepad-2.0-performance 怎么安装?

在终端执行 npx skills add https://github.com/zhanghandong/makepad-skills --skill makepad-2.0-performa…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

makepad-2.0-performance 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

makepad-2.0-performance 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

makepad-2.0-performance 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

makepad-2.0-performance 用的人多吗?

公开数据是累计安装 297 次,近一周安装 12 次,下载 93 次,GitHub 737 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

makepad-2.0-performance 安全吗?

没有查到第三方扫描结果,安全性无法从公开资料判断,安装前请自行审查源码、依赖和命令行为。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 没有第三方扫描结果,安全性只能靠自己读源码判断。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 要求有安全扫描结论才肯安装的团队。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
makepad-2.0-performance

makepad 2 0 性能 · 本页

297737需要联网未明确未收录

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Makepad 2.0 Performance & Debugging Skill

1. Overview

Makepad 2.0 uses a unique rendering pipeline combined with the Splash script VM. Performance depends on understanding three critical subsystems:

  1. Draw Batching - How Makepad groups GPU draw calls and why new_batch: true matters
  2. Garbage Collection - The Splash VM's mark-sweep GC with per-type-bucket thresholds
  3. Render Triggers - The on_render / .render() system that controls when sub-trees rebuild

Unlike traditional retained-mode UI frameworks, Makepad uses an immediate-mode-inspired draw pipeline where widgets emit draw commands into a sorted batch list. Understanding this pipeline is essential for diagnosing invisible text, flickering, and performance regressions.


2. Draw Batching System

How It Works

Makepad automatically batches consecutive draw calls that use the same shader into a single GPU draw call. This is a major performance optimization, but it has a critical side effect: draw order can be surprising.

Draw pipeline (simplified):

Widget tree:          GPU batches (default):

  View (bg shader)      Batch 1: all bg shaders
    Label (text)   -->  Batch 2: all text shaders
  View (bg shader)
    Label (text)        Result: ALL backgrounds draw first,
                                then ALL text draws second

When a View has show_bg: true AND contains text children, the text can end up behind the background because both text draws get batched together into a single draw call that executes before (or after) the background draw calls.

new_batch: true

Setting new_batch: true on a View forces Makepad to start a new draw batch at that point. This creates a ViewOptimize::DrawList internally, which ensures proper draw ordering within that View's subtree.

// PROBLEM: Label text is invisible - batched behind the background
RoundedView{
    width: Fill height: Fit
    draw_bg.color: #1e1e2e
    Label{text: "This text is INVISIBLE"}
}

// FIX: new_batch ensures background draws before text
RoundedView{
    width: Fill height: Fit
    new_batch: true
    draw_bg.color: #1e1e2e
    Label{text: "This text is VISIBLE"}
}

When new_batch: true Is Required

ScenarioRequired?Why
View with show_bg: true containing LabelsYESText batches behind background
View with hover animator + text childrenYESHover bg covers text on activation
Container of repeated items with backgroundsYESEach item and the container need it
Transparent View (no show_bg) with LabelsNONo background to overlap
View with only non-text children (e.g., icons)NOSame shader type - no overlap issue
Deeply nested Views each with backgroundsYES on eachEach background layer needs its own batch

Hover Effects and new_batch

This is the number one mistake with hoverable list items. When a View has show_bg: true with a hover animator that transitions from transparent (#0000) to opaque on hover, the text disappears on hover because the newly-opaque background covers the batched text.

// CORRECT: Hoverable item with new_batch
let HoverItem = View{
    width: Fill height: Fit
    new_batch: true
    show_bg: true
    draw_bg +: {
        color: uniform(#0000)
        color_hover: uniform(#fff2)
        hover: instance(0.0)
    }
    animator: Animator{
        hover: {
            default: {
                from: {all: Forward{duration: 0.1}}
                apply: {draw_bg: {hover: 0.0}}
            }
            on: {
                from: {all: Forward{duration: 0.1}}
                apply: {draw_bg: {hover: 1.0}}
            }
        }
    }
    label := Label{text: "item" draw_text.color: #fff}
}

// Parent container of hover items also needs new_batch
RoundedView{
    flow: Down height: Fit new_batch: true
    draw_bg.color: #2a2a3d
    draw_bg.border_radius: 8.0
    HoverItem{label.text: "First item"}
    HoverItem{label.text: "Second item"}
}

ViewOptimize Internals

The new_batch and texture_caching properties map to a ViewOptimize enum:

ViewOptimize::None      - Default. No special draw ordering.
ViewOptimize::DrawList  - Created by new_batch: true. Starts a new DrawList2d.
ViewOptimize::Texture   - Created by texture_caching: true. Renders to offscreen texture.

Priority: texture_caching takes precedence over new_batch if both are set.


3. Texture Caching

How It Works

Setting texture_caching: true on a View renders its entire child sub-tree to an offscreen GPU texture. On subsequent frames, if nothing in the sub-tree has changed, Makepad can skip re-rendering the children and just blit the cached texture.

// Cache a complex but rarely-changing sidebar
sidebar := View{
    width: 280 height: Fill
    texture_caching: true
    flow: Down spacing: 4
    // ... many child widgets ...
}

Pre-Built Cached Views

Makepad provides pre-styled cached views:

WidgetDescription
CachedViewTexture-cached rectangle container
CachedRoundedViewTexture-cached rounded rectangle

When to Use Texture Caching

Good candidates:

  • Complex static sidebars or toolbars that rarely change
  • Large widget sub-trees with many nested backgrounds and text
  • Decorative panels with shader effects

Bad candidates:

  • Frequently updating views (e.g., animation targets, live data)
  • Small simple views (overhead exceeds benefit)
  • Views that contain scrolling content (CachedView wraps the whole content, not the viewport)

Trade-offs

BenefitCost
Reduces per-frame draw call countUses GPU memory for cached texture
Avoids re-traversing large sub-treesTexture must be invalidated on change
Can eliminate batching issues (the texture resolves draw order)DPI factor affects texture resolution

4. Garbage Collection (mod.gc)

Architecture

The Splash VM uses a mark-and-sweep garbage collector with isolated heaps for different value types:

Heap Layout:
  +-- Objects (ScriptObject)    -- Primary allocation type
  +-- Arrays  (ScriptArray)     -- Typed arrays and value arrays
  +-- Strings (ScriptString)    -- Interned strings
  +-- Pods    (ScriptPod)       -- Pod values (vec2, vec3, vec4, etc.)
  +-- Handles (ScriptHandle)    -- Native Rust handles
  +-- Regexes (ScriptRegex)     -- Interned regex patterns

Automatic GC Triggering

The GC uses a growth-based heuristic similar to Lua and V8:

  • Growth Factor: 2x - GC triggers when any heap category doubles since last GC
  • Minimum Thresholds (to avoid thrashing on small heaps):
CategoryMinimum Before GC Can Trigger
Objects1,024
Strings256
Arrays128
Pods128
Handles64

GC triggers when: current_count >= MIN_THRESHOLD AND current_count >= last_gc_count * 2

Script API

mod.gc.run() - Force a GC cycle immediately. Silent (no log output).

mod.gc.run_status() - Force a GC cycle and print detailed statistics:

GC 142us: obj[S:1200 A:340 R:89] arr[S:45 A:12 R:3] str[S:890 A:120 R:15] ...

Where S=static (permanent), A=alive (survived), R=removed (freed).

mod.gc.set_static(value) - Mark a value and its entire reachable object graph as static. Static objects:

  • Are never collected by GC (permanent)
  • Are skipped during GC mark phase (faster GC traversal)
  • Cannot be un-marked (irreversible within the VM lifetime)

mod.gc.dump_tag(value) - Debug tool. Prints internal tag information for an object: type index, static flag, proto chain.

Best Practices

Pattern: Static UI Trees

For large, stable UI tree definitions (like a Dock with many tabs), mark them as static immediately after definition. This is the standard pattern used in the Studio and UIZoo examples:

// Define a large widget tree
let AppDock = Dock{
    // ... tabs, splitters, content templates ...
    TabEditor := TabEditor{}
    TabFileTree := TabFileTree{}
    TabSettings := TabSettings{}
}

// Mark the entire tree as static - it will never be GC'd
mod.gc.set_static(AppDock)

// Run GC immediately to clean up any temporaries from tree construction
mod.gc.run()

// Now start the app
startup() do #(App::script_component(vm)){
    ui: Root{
        main_window := Window{
            body +: {
                // ... use AppDock here ...
            }
        }
    }
}

Pattern: Dynamic Content

For dynamic content (lists, user-generated items, chat messages), let the automatic GC handle cleanup:

// Dynamic data - no need to call mod.gc manually
var todos = []

fn add_todo(text) {
    todos.push({text: text done: false})
    ui.main_view.render()
    // Automatic GC will clean up old unreachable objects
}

fn delete_todo(index) {
    todos.splice(index, 1)
    ui.main_view.render()
    // Old todo object becomes unreachable, will be collected automatically
}

Pattern: Periodic Manual GC for Long-Running Apps

For apps that create and destroy many objects (e.g., chat applications with streaming responses):

var message_count = 0

fn on_new_message(msg) {
    messages.push(msg)
    message_count += 1

    // Every 100 messages, run GC to reclaim temporary parsing objects
    if message_count % 100 == 0 {
        mod.gc.run()
    }

    ui.message_list.render()
}

GC Mark Phase Details

The mark phase traverses from roots:

  1. Type check prototypes
  2. Type defaults objects
  3. Pod type defaults and objects
  4. Root objects (held by Rust via ScriptObjectRef)
  5. Root arrays (held by Rust via ScriptArrayRef)
  6. Root handles (held by Rust via ScriptHandleRef)
  7. Thread stacks (all live values on VM execution stacks)
  8. Thread scopes
  9. Method call contexts
  10. Loop source values
  11. Trap error/return/bail values
  12. Script body scopes and tokenizer string literals
  13. Native type table objects

Static objects are skipped during traversal since they only reference other static values.


5. Render Optimization

The on_render / .render() System

Makepad 2.0 uses a pull-based rendering model for dynamic content. The on_render callback on a View only executes when .render() is called on that View.

// Define a reactive view
counter_view := View{
    on_render: || {
        Label{
            text: "Count: " + state.counter
            draw_text.color: #fff
        }
    }
}

// In event handler - only re-render what changed
fn increment() {
    state.counter += 1
    ui.counter_view.render()   // Only this view re-renders
}

Rules for Efficient Rendering

  1. NEVER call .render() unnecessarily - Each call completely rebuilds that sub-tree's widget output.
  2. Render only affected sub-trees - If only a list changed, render only the list view, not the entire UI.
  3. Avoid rendering in tight loops - Batch state changes, then render once:
// BAD: renders 100 times
for i in 0..100 {
    items[i].value = compute(i)
    ui.item_list.render()    // WASTEFUL - rebuilds list 100 times
}

// GOOD: render once after all changes
for i in 0..100 {
    items[i].value = compute(i)
}
ui.item_list.render()        // Render once with all changes applied
  1. Use on_startup for initial render - Trigger the first render when the app starts:
ui: Root{
    on_startup: || {
        ui.main_view.render()
    }
    main_window := Window{
        body +: {
            main_view := View{
                on_render: || {
                    // ... dynamic content ...
                }
            }
        }
    }
}

Render Scope

When .render() is called on a View, only that View's on_render callback executes. Child Views with their own on_render callbacks will NOT automatically re-render unless their .render() is also called (or they are reconstructed by the parent's on_render).


6. Debug Logging

Rust-Side Logging

Use the log! macro from Makepad's error log system:

use makepad_widgets::*;

// In Rust code
log!("Button clicked, counter = {}", self.counter);
log!("Widget action: {:?}", action);

Script-Side Logging

In Splash scripts, you can use log() or string interpolation for debugging:

fn handle_click() {
    let value = compute_something()
    // Log values during development
    log("computed value: " + value)
}

GC Status Logging

Use mod.gc.run_status() to get a detailed breakdown of GC activity:

// Output example:
// GC 142us: obj[S:1200 A:340 R:89] arr[S:45 A:12 R:3] str[S:890 A:120 R:15]
//           hdl[S:8 A:2 R:0] pod[S:200 A:45 R:10] rex[S:3 A:0 R:0]

Fields:

  • Time (142us) - GC cycle duration in microseconds
  • S (Static) - Objects permanently marked, never collected
  • A (Alive) - Objects that survived this GC cycle
  • R (Removed) - Objects freed in this cycle

Tag Debugging

For deep debugging of specific objects, use mod.gc.dump_tag(value):

let my_widget = View{...}
mod.gc.dump_tag(my_widget)
// Output: obj 4523 type_index=Some(12) is_static=false proto=Some(89) ...

7. Common Performance Issues & Fixes

IssueCauseFix
Text invisibleMissing new_batchAdd new_batch: true to parent View with show_bg: true
Text disappears on hoverBatch overlap during hover animationAdd new_batch: true to the hoverable View
UI freezes / stuttersExcessive .render() callsBatch state changes, render only changed sub-trees
Memory growing unboundedGC not running or large static leaksUse mod.gc.set_static() for stable trees, let auto GC handle dynamic content
Slow initial loadLarge script evaluation at startupSplit into modules, use lazy loading patterns
Scroll stutteringToo many items renderingUse PortalList for virtualized rendering
Hover not respondingView missing show_bg: trueViews need show_bg: true to receive mouse events for hover
Widget not found at runtimeWrong naming operatorUse := (not :) for named/addressable children
Style overrides not applyingMissing merge operatorUse +: to merge properties, not : which replaces entirely
Layout collapsed to zeroMissing height: FitAll containers need explicit height: Fit or a fixed height

8. PortalList for Large Lists

Why PortalList

PortalList virtualizes rendering -- only items visible in the viewport are drawn. This is mandatory for lists with 100+ items. Without it, all items are drawn every frame regardless of visibility.

Script-Side PortalList (with on_render)

For Splash-driven lists, define the PortalList with templates and use on_render:

list := PortalList{
    width: Fill height: Fill
    flow: Down spacing: 4
    scroll_bar: ScrollBar{}
    Item := View{
        width: Fill height: Fit
        padding: 8
        new_batch: true
        draw_bg.color: #2a2a3d
        label := Label{text: "" draw_text.color: #ddd}
    }
}

Rust-Side PortalList (with Widget trait)

For Rust-driven rendering, implement the Widget trait:

impl Widget for MyList {
    fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
        while let Some(item) = self.view.draw_walk(cx, scope, walk).step() {
            if let Some(mut list) = item.borrow_mut::<PortalList>() {
                list.set_item_range(cx, 0, self.items.len());

                while let Some(item_id) = list.next_visible_item(cx) {
                    let template = id!(Item);
                    let item = list.item(cx, item_id, template);
                    item.label(ids!(label)).set_text(cx, &self.items[item_id].text);
                    item.draw_all(cx, &mut Scope::empty());
                }
            }
        }
        DrawStep::done()
    }
}

FlatList vs PortalList

FeatureFlatListPortalList
VirtualizationNoYes
Suitable for< 100 itemsAny number of items
Memory usageAll items in memoryOnly visible items
Scroll performanceDegrades with countConstant

9. ViewOptimize Options Summary

PropertyViewOptimize ValueEffect
(default)NoneStandard batched drawing
new_batch: trueDrawListNew draw batch, proper draw ordering
texture_caching: trueTextureRender children to offscreen texture
visible: falseN/ASkip rendering entirely

Priority: If both texture_caching and new_batch are set, texture_caching wins (becomes ViewOptimize::Texture).


10. Debugging Checklist

UI Not Showing

  • Check height: Fit on all containers (default height: Fill inside a Fit parent = 0 height)
  • Check width: Fill on root container (never use fixed pixel width on outermost element)
  • Verify use mod.prelude.widgets.* is at the top of the script

Text Invisible

  • Add new_batch: true to any View with show_bg: true that contains text
  • Check draw_text.color is not transparent or same as background
  • Verify the Label is a direct or properly-batched child

Text Disappears on Hover

  • Add new_batch: true to the hoverable View
  • Ensure the container of hoverable items also has new_batch: true

Clicks Not Working

  • Check := vs : -- use := for named/dynamic children you reference
  • Verify show_bg: true is set for Views that need mouse events
  • Check grab_key_focus if keyboard events are needed

Widget Not Found

  • Verify #(WidgetName::register_widget(vm)) registration in script_mod
  • Check that crate::makepad_widgets::script_mod(vm) is called before custom registrations
  • Verify widget crate is a dependency in Cargo.toml

Script Errors

  • Use log() to debug values during execution
  • Use mod.gc.run_status() to check heap statistics
  • Use mod.gc.dump_tag(value) to inspect object internals

Style Not Applying

  • Use +: merge operator for extending existing styles: draw_bg +: {color: #fff}
  • Use : only when you want to fully replace a property
  • Check dot-path syntax: draw_bg.color: #fff is shorthand for draw_bg +: {color: #fff}

11. Profiling with Studio

Makepad Studio includes a built-in profiler for monitoring application performance.

Studio Remote Protocol

Studio can connect to running applications and provide:

  • Screenshots - Capture current frame state
  • Widget Tree Dumps - Inspect the live widget hierarchy
  • Widget Queries - Find specific widgets by ID
  • Performance Monitoring - Frame times, draw call counts

Using Studio for Performance Debugging

  1. Start Studio remote:
cargo run -p cargo-makepad --release -- studio --studio=127.0.0.1:8001
  1. Run your app through Studio:
{"Run":{"mount":"makepad","process":"makepad-example-myapp","args":[]}}
  1. Capture widget tree to identify render structure:
{"WidgetTreeDump":{"build_id":BUILD_ID}}
  1. Take screenshots to verify visual state:
{"Screenshot":{"build_id":BUILD_ID}}

Identifying Hot Render Paths

  • Use WidgetTreeDump to see how many widgets are in the tree
  • Look for deeply nested View hierarchies that could benefit from texture_caching
  • Identify repeated items that should use PortalList instead of manual loops
  • Check for Views with new_batch: true that might not need it (each new batch = new draw list)

12. Quick Reference Card

Performance Properties on View

// Force new GPU draw batch (fixes text-behind-background)
new_batch: true

// Cache children to GPU texture (reduces draw calls for stable subtrees)
texture_caching: true

// Hide without removing from tree (skip rendering entirely)
visible: false

GC API

mod.gc.set_static(value)    // Mark value tree as permanent
mod.gc.run()                // Force GC cycle (silent)
mod.gc.run_status()         // Force GC cycle with log output
mod.gc.dump_tag(value)      // Debug: print object tag info

Render API

ui.widget_name.render()     // Trigger on_render for specific widget

GC Thresholds (Automatic Trigger)

Objects:  >= 1024 AND >= 2x since last GC
Strings:  >= 256  AND >= 2x since last GC
Arrays:   >= 128  AND >= 2x since last GC
Pods:     >= 128  AND >= 2x since last GC
Handles:  >= 64   AND >= 2x since last GC

平台分布

Codex

33.92%
按下载量换算32

Claude

29.37%
按下载量换算27

Cursor

19.4%
按下载量换算18

Gemini CLI

10.12%
按下载量换算9

安全审计

暂无安全审计结果可展示。

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills