MCP HubMCP Hub
SKILL·5F1DBA

optimize-shiny-performance

pjt222
업데이트됨 1 month ago
11 조회
26
3
26
GitHub에서 보기
기타general

정보

이 Claude Skill은 profvis, 캐싱(bindCache/memoise), 비동기 작업, 디바운싱과 같은 도구를 활용하여 Shiny 앱의 성능을 분석하고 최적화하도록 개발자를 지원합니다. 반응 속도가 느리게 느껴지거나, 부하 상황에서 리소스 사용량이 높거나, 많은 동시 사용자를 수용할 수 있도록 프로덕션 배포를 준비해야 하는 앱에 적합합니다. 본 스킬은 병목 현상을 식별하고 성능 개선을 실행 가능한 지침으로 제공합니다.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/optimize-shiny-performance

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서


name: optimize-shiny-performance description: > 使用 profvis、bindCache、memoise、async/promises、debounce/throttle 和 ExtendedTask 分析并优化 Shiny 应用性能。适用于应用在用户交互时感觉缓慢或 无响应、并发负载下服务器资源耗尽、特定操作形成瓶颈,或为具有大量并发用户 的生产部署准备应用。 license: MIT allowed-tools: Read Write Edit Bash Grep Glob metadata: author: Philipp Thoss version: "1.0" domain: shiny complexity: advanced language: R tags: shiny, performance, profiling, caching, async, promises, optimization locale: zh-CN source_locale: en source_commit: 6f65f316 translator: claude-opus-4-6 translation_date: 2026-03-16

优化 Shiny 性能

通过缓存、异步操作和响应式图优化对 Shiny 应用性能进行分析、诊断和优化。

适用场景

  • Shiny 应用在用户交互时感觉缓慢或无响应
  • 并发用户负载下服务器资源耗尽
  • 特定操作(数据加载、绘图、计算)形成瓶颈
  • 为有大量用户的生产部署准备应用

输入

  • 必需:Shiny 应用路径
  • 必需:性能问题描述(加载慢、交互卡顿、内存占用高)
  • 可选:预期并发用户数
  • 可选:可用服务器资源(RAM、CPU 核心数)
  • 可选:应用是否使用数据库或外部 API

步骤

第 1 步:分析应用性能

# Profile with profvis
profvis::profvis({
  shiny::runApp("path/to/app", display.mode = "normal")
})

# Or profile specific operations
profvis::profvis({
  result <- expensive_computation(data)
})

识别主要瓶颈:

  1. 数据加载:初始数据获取需要多长时间?
  2. 响应式重算:哪些响应式触发最频繁?
  3. 渲染:哪些输出渲染时间最长?
  4. 外部调用:数据库查询、API 请求、文件 I/O?

使用响应式日志进行响应式图分析:

# Enable reactive logging
options(shiny.reactlog = TRUE)
shiny::runApp("path/to/app")
# Press Ctrl+F3 in the browser to view the reactive graph

预期结果: 明确识别出 2-3 个最大瓶颈。

失败处理: 如果 profvis 未显示有用细节,用 profvis::profvis() 包裹特定代码段。如果 reactlog 信息过多,每次专注于一个交互。

第 2 步:优化响应式图

减少不必要的响应式失效:

# BAD: Recomputes on ANY input change
output$plot <- renderPlot({
  data <- load_data()  # Runs every time
  filtered <- data[data$category == input$category, ]
  plot(filtered)
})

# GOOD: Isolate data loading from filtering
raw_data <- reactive({
  load_data()
}) |> bindCache()  # Cache the expensive part

filtered_data <- reactive({
  raw_data()[raw_data()$category == input$category, ]
})

output$plot <- renderPlot({
  plot(filtered_data())
})

使用 isolate() 防止不必要的失效:

# Only recompute when the button is clicked, not on every input change
output$result <- renderText({
  input$compute  # Take dependency on button
  isolate({
    paste("N =", input$n, "Mean =", mean(rnorm(input$n)))
  })
})

对高频输入使用 debounce()throttle()

# Debounce text input — wait 500ms after user stops typing
search_text <- reactive(input$search) |> debounce(500)

# Throttle slider — update at most every 250ms
slider_value <- reactive(input$slider) |> throttle(250)

预期结果: 响应式图只触发必要的重算。

失败处理: 如果移除某个依赖项破坏了功能,使用 req() 添加显式守卫,而非依赖隐式响应式依赖。

第 3 步:实现缓存

对 Shiny 输出使用 bindCache

output$plot <- renderPlot({
  create_expensive_plot(filtered_data())
}) |> bindCache(input$category, input$date_range)

output$table <- renderDT({
  expensive_query(input$filters)
}) |> bindCache(input$filters)

bindCache 使用输入值作为缓存键。当相同输入再次出现时,立即返回缓存结果。

对函数使用 memoise

# Cache expensive function results
load_reference_data <- memoise::memoise(
  function(dataset_name) {
    readr::read_csv(paste0("data/", dataset_name, ".csv"))
  },
  cache = cachem::cache_disk("cache/", max_age = 3600)
)

应用级数据预计算

# In global.R or outside server function — computed once at app startup
reference_data <- readr::read_csv("data/reference.csv")
model <- readRDS("models/trained_model.rds")

server <- function(input, output, session) {
  # reference_data and model are available to all sessions
  # without reloading
}

预期结果: 重复操作使用缓存结果;响应时间显著下降。

失败处理: 如果缓存增长过大,设置 max_agemax_size 限制。如果缓存值过期,减少 max_age 或添加清除缓存按钮。如果 bindCache 导致错误,确保缓存键输入可序列化。

第 4 步:为长时操作添加异步

使用 ExtendedTask(Shiny >= 1.8.1)处理长时运行计算:

server <- function(input, output, session) {
  # Define the extended task
  analysis_task <- ExtendedTask$new(function(data, params) {
    promises::future_promise({
      # This runs in a background process
      run_heavy_analysis(data, params)
    })
  }) |> bind_task_button("run_analysis")

  # Trigger the task
  observeEvent(input$run_analysis, {
    analysis_task$invoke(dataset(), input$params)
  })

  # Use the result
  output$result <- renderTable({
    analysis_task$result()
  })
}

对于 Shiny < 1.8.1 的应用,直接使用 promises:

library(promises)
library(future)
plan(multisession, workers = 4)

server <- function(input, output, session) {
  result <- eventReactive(input$compute, {
    future_promise({
      Sys.sleep(5)  # Simulate long computation
      expensive_analysis(isolate(input$params))
    })
  })

  output$table <- renderTable({
    result()
  })
}

预期结果: 长时操作不阻塞 UI;计算运行期间其他用户可以继续交互。

失败处理: 如果 future_promise 报错,检查是否设置了 plan(multisession)。如果变量在 future 中不可用,显式传递它们——future 在单独的 R 进程中运行。

第 5 步:优化渲染

减少渲染开销:

# Use plotly for interactive plots instead of re-rendering
output$plot <- plotly::renderPlotly({
  plotly::plot_ly(filtered_data(), x = ~x, y = ~y, type = "scatter")
})

# Use server-side DT for large tables
output$table <- DT::renderDataTable({
  DT::datatable(large_data(), server = TRUE, options = list(
    pageLength = 25,
    processing = TRUE
  ))
})

# Conditional UI to avoid rendering hidden elements
output$details <- renderUI({
  req(input$show_details)
  expensive_details_ui()
})

预期结果: 渲染操作更快且不阻塞 UI。

失败处理: 如果 plotly 在大数据集上较慢,使用 toWebGL() 进行 WebGL 渲染,或在绘图前对数据降采样。

第 6 步:验证性能改进

# Before/after benchmarking
system.time({
  shiny::testServer(myModuleServer, args = list(...), {
    session$setInputs(category = "A")
    session$flushReact()
  })
})

# Load testing with shinyloadtest
shinyloadtest::record_session("http://localhost:3838")
shinyloadtest::shinycannon(
  "recording.log",
  "http://localhost:3838",
  workers = 10,
  loaded_duration_minutes = 5
)
shinyloadtest::shinyloadtest_report("recording.log")

预期结果: 响应时间和/或并发用户容量有可测量的改善。

失败处理: 如果性能未改善,重新分析以找到下一个瓶颈。性能优化是迭代过程——先修复最大瓶颈,再重新测量。

验证清单

  • 分析识别出具体瓶颈(而非猜测)
  • 响应式图没有不必要的失效链
  • 昂贵操作使用缓存(bindCache 或 memoise)
  • 长时运行计算使用异步(ExtendedTask 或 promises)
  • 高频输入使用 debounce/throttle
  • 大数据集使用服务端处理
  • 性能改善可测量(前后计时对比)

常见问题

  • 过早优化:先分析。瓶颈很少在你认为的地方。
  • 缓存失效 bug:如果用户看到过期数据,缓存键没有包含所有相关输入。将缺失的依赖项添加到 bindCache()
  • future 变量作用域future_promise 在单独进程中运行。全局变量、数据库连接和响应式值必须显式捕获。
  • 响应式意大利面:如果响应式图复杂到难以理解,应用需要架构重构(模块),而不仅仅是缓存。
  • 过度缓存:缓存所有内容会浪费内存。只缓存昂贵且有重复输入模式的操作。

相关技能

  • build-shiny-module — 可维护响应式代码的模块化架构
  • scaffold-shiny-app — 从一开始选择合适的应用框架
  • deploy-shiny-app — 以适当服务器资源部署优化后的应用
  • test-shiny-app — 性能回归测试

GitHub 저장소

pjt222/agent-almanac
경로: i18n/zh-CN/skills/optimize-shiny-performance
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams
FAQ

Frequently asked questions

What is the optimize-shiny-performance skill?

optimize-shiny-performance is a Claude Skill by pjt222. Skills package instructions and resources that Claude loads on demand, so Claude can perform optimize-shiny-performance-related tasks without extra prompting.

How do I install optimize-shiny-performance?

Use the install commands on this page: add optimize-shiny-performance to Claude Code as a plugin, or clone its repository into your skills directory, then restart Claude so it picks up the skill.

What category does optimize-shiny-performance belong to?

optimize-shiny-performance is in the Other category, tagged general.

Is optimize-shiny-performance free to use?

Yes. optimize-shiny-performance is listed on AIMCP and free to install. It runs inside Claude, so no separate service account is required to use the skill itself.

연관 스킬

llamaguard
기타

LlamaGuard는 폭력 및 혐오 발언 등 6가지 안전 범주에서 LLM 입력과 출력을 조정하기 위한 Meta의 70-80억 파라미터 모델입니다. 94-95% 정확도를 제공하며 vLLM, Hugging Face 또는 Amazon SageMaker를 사용해 배포할 수 있습니다. 이 기술을 사용하여 AI 애플리케이션에 콘텐츠 필터링 및 안전 가드레일을 손쉽게 통합하세요.

스킬 보기
cost-optimization
기타

이 Claude Skill은 리소스 적정화, 태깅 전략, 지출 분석을 통해 개발자들이 클라우드 비용을 최적화할 수 있도록 지원합니다. AWS, Azure, GCP에서 클라우드 비용을 절감하고 비용 거버넌스를 구현하기 위한 프레임워크를 제공합니다. 인프라 비용을 분석하거나, 리소스를 적정화하거나, 예산 제약을 충족해야 할 때 사용하세요.

스킬 보기
sports-betting-analyzer
기타

이 Claude Skill은 스프레드, 오버/언더, 프로프 베트를 포함한 스포츠 베팅 시장을 분석합니다. 역사적 추이와 상황별 통계를 검토하여 가치 베트를 발견하고, 교육적 목적으로 실행 가능한 권장 사항이 담긴 구조화된 마크다운 결과를 제공합니다. 개발자는 이 기능을 스포츠 베팅 분석 도구에 활용할 수 있으며, 단순히 엔터테인먼트/교육 목적으로만 설계되었음을 유의해야 합니다.

스킬 보기
quantizing-models-bitsandbytes
기타

이 스킬은 bitsandbytes를 사용하여 LLM을 8비트 또는 4비트 정밀도로 양자화하며, 최소한의 정확도 손실로 50-75%의 메모리 감소를 달성합니다. 제한된 GPU 메모리에서 더 큰 모델을 실행하거나 추론을 가속화하는 데 이상적이며, INT8, NF4, FP4와 같은 형식을 지원합니다. 이 스킬은 HuggingFace Transformers와 통합되어 QLoRA 학습 및 8비트 옵티마이저를 가능하게 합니다.

스킬 보기