Spaces:
Sleeping
Sleeping
Download Rscripts/prep/profile_startup.R from diegoellissoto/Biodiversity_Access: direct link, hf CLI and curl.
- Browser
- Download file 15.8 kB
-
https://huggingface.co/spaces/diegoellissoto/Biodiversity_Access/resolve/main/Rscripts/prep/profile_startup.R
- Command line
-
hf download hf://spaces/diegoellissoto/Biodiversity_Access/Rscripts/prep/profile_startup.R
-
curl -L -o profile_startup.R https://huggingface.co/spaces/diegoellissoto/Biodiversity_Access/resolve/main/Rscripts/prep/profile_startup.R
15.8 kB
| # ============================================================================ | |
| # Startup Performance Profiling | |
| # ============================================================================ | |
| # This script benchmarks each data loading step in setup.R to identify | |
| # bottlenecks and guide optimization decisions (precomputation, caching, etc.) | |
| # library(tidyverse) | |
| library(profvis) | |
| # Create benchmark dataframe to track timings | |
| benchmarks <- tibble( | |
| step = character(), | |
| description = character(), | |
| time_sec = numeric(), | |
| time_pct = numeric() | |
| ) | |
| start_overall <- Sys.time() | |
| # ============================================================================ | |
| # 1. Library Loading | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| library(shiny) | |
| library(shinydashboard) | |
| library(leaflet) | |
| library(mapboxapi) | |
| # library(tidyverse) | |
| library(tidycensus) | |
| library(sf) | |
| library(DT) | |
| library(RColorBrewer) | |
| library(terra) | |
| library(data.table) | |
| library(mapview) | |
| # library(sjPlot) | |
| # library(sjlabelled) | |
| library(bslib) | |
| library(shinycssloaders) | |
| library(DBI) | |
| library(duckdb) | |
| library(dbplyr) | |
| library(gtfsrouter) | |
| library(tidytransit) | |
| library(fmsb) | |
| library(scales) | |
| time_libraries <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "00_libraries", | |
| description = "Load all 23 packages", | |
| time_sec = time_libraries, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 2. Greenspace (OSM) | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| osm_greenspace <- st_read("/vsicurl/https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/greenspaces_osm_nad83.shp", quiet = TRUE) |> | |
| st_transform(4326) | |
| if (!"name" %in% names(osm_greenspace)) { | |
| osm_greenspace$name <- "Unnamed Greenspace" | |
| } | |
| time_greenspace <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "01_greenspace", | |
| description = "Load OSM greenspace polygons", | |
| time_sec = time_greenspace, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 3. Greenspace Distance Rasters | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| greenspace_dist_raster <- terra::rast("/vsicurl/https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/nearest_greenspace_dist.tif") | |
| greenspace_osmid_raster <- terra::rast("/vsicurl/https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/nearest_greenspace_osmid.tif") | |
| time_gs_rasters <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "02_gs_rasters", | |
| description = "Load greenspace distance rasters", | |
| time_sec = time_gs_rasters, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 4. NDVI Raster | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| ndvi <- terra::rast("/vsicurl/https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/SF_EastBay_NDVI_Sentinel_10.tif") | |
| time_ndvi <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "03_ndvi", | |
| description = "Load NDVI raster", | |
| time_sec = time_ndvi, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 5. CBG Vector Data | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| download.file( | |
| 'https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/cbg_vect_sf.Rdata', | |
| '/tmp/cbg_vect_sf.Rdata', | |
| mode = 'wb', | |
| quiet = TRUE | |
| ) | |
| load('/tmp/cbg_vect_sf.Rdata') | |
| if (!"unique_species" %in% names(cbg_vect_sf)) { | |
| cbg_vect_sf$unique_species <- cbg_vect_sf$n_species | |
| } | |
| if (!"n_observations" %in% names(cbg_vect_sf)) { | |
| cbg_vect_sf$n_observations <- cbg_vect_sf$n | |
| } | |
| if (!"median_inc" %in% names(cbg_vect_sf)) { | |
| cbg_vect_sf$median_inc <- cbg_vect_sf$medincE | |
| } | |
| if (!"ndvi_mean" %in% names(cbg_vect_sf)) { | |
| cbg_vect_sf$ndvi_mean <- cbg_vect_sf$ndvi_sentinel | |
| } | |
| time_cbg <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "04_cbg", | |
| description = "Download + load census block groups", | |
| time_sec = time_cbg, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 6. Hotspots/Coldspots | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| biodiv_hotspots <- st_read("/vsicurl/https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/hotspots.shp", quiet = TRUE) |> | |
| st_transform(4326) | |
| biodiv_coldspots <- st_read("/vsicurl/https://huggingface.co/datasets/boettiger-lab/sf_biodiv_access/resolve/main/coldspots.shp", quiet = TRUE) |> | |
| st_transform(4326) | |
| time_hotcold <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "05_hotcold", | |
| description = "Load hotspots and coldspots", | |
| time_sec = time_hotcold, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 7. RSF Projects | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| rsf_projects <- st_read("data/source/RSF_Program_Projects_polygons.gpkg", quiet = TRUE) |> | |
| st_transform(4326) | |
| time_rsf <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "06_rsf", | |
| description = "Load RSF program projects", | |
| time_sec = time_rsf, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 8. GBIF Parquet Reference (just get path, don't load yet) | |
| # ============================================================================ | |
| time_gbif_setup <- 0.001 # negligible | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "07_gbif_setup", | |
| description = "GBIF parquet path (lazy load in server)", | |
| time_sec = time_gbif_setup, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 9. GTFS Data | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| gtfs_path <- '/Users/diegoellis/Desktop/RSF_next_steps/GPFS_OSM_Transit/sf_muni_gtfs-current/' | |
| # Stops | |
| gtfs_stops_sf <- tryCatch({ | |
| read.csv(file.path(gtfs_path, 'stops.txt')) |> | |
| st_as_sf(coords = c("stop_lon", "stop_lat"), crs = 4326) | |
| }, error = function(e) { | |
| warning("GTFS stops failed: ", e$message) | |
| NULL | |
| }) | |
| # Route shapes | |
| gtfs_shapes_raw <- read.csv(file.path(gtfs_path, 'shapes.txt')) | |
| gtfs_trips_raw <- read.csv(file.path(gtfs_path, 'trips.txt')) | |
| gtfs_routes_raw <- read.csv(file.path(gtfs_path, 'routes.txt')) | |
| shape_route_map <- gtfs_trips_raw |> | |
| distinct(shape_id, route_id) | |
| route_meta <- gtfs_routes_raw |> | |
| select(route_id, route_short_name, route_long_name, route_color) |> | |
| mutate(route_color_hex = paste0("#", trimws(route_color))) | |
| shapes_split <- gtfs_shapes_raw |> | |
| arrange(shape_id, shape_pt_sequence) |> | |
| group_by(shape_id) |> | |
| group_split() | |
| shape_geoms <- lapply(shapes_split, function(s) { | |
| st_linestring(cbind(s$shape_pt_lon, s$shape_pt_lat)) | |
| }) | |
| gtfs_routes_sf <- st_sf( | |
| shape_id = sapply(shapes_split, function(s) s$shape_id[1]), | |
| geometry = st_sfc(shape_geoms, crs = 4326) | |
| ) |> | |
| left_join(shape_route_map, by = "shape_id") |> | |
| left_join(route_meta, by = "route_id") | |
| time_gtfs_basic <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "08_gtfs_basic", | |
| description = "Load GTFS stops and route shapes", | |
| time_sec = time_gtfs_basic, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 10. gtfsrouter Initialization | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| gtfs_router <- tryCatch({ | |
| gtfs_zip_path <- tempfile(fileext = ".zip") | |
| old_wd <- getwd() | |
| setwd(gtfs_path) | |
| utils::zip(gtfs_zip_path, files = list.files('.', pattern = "\\.txt$")) | |
| setwd(old_wd) | |
| gr <- gtfsrouter::extract_gtfs(gtfs_zip_path) | |
| gtfsrouter::gtfs_timetable(gr, day = "Monday") | |
| }, error = function(e) { | |
| warning("gtfsrouter failed: ", e$message) | |
| NULL | |
| }) | |
| time_gtfs_router <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "09_gtfs_router", | |
| description = "Initialize gtfsrouter + timetable", | |
| time_sec = time_gtfs_router, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 11. tidytransit Headways | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| gtfs_stop_headways <- tryCatch({ | |
| gt <- tidytransit::read_gtfs(gtfs_path) | |
| tidytransit::get_stop_frequency(gt, start_time = 7 * 3600, end_time = 9 * 3600) |> | |
| group_by(stop_id) |> | |
| summarise( | |
| mean_headway_min = mean(mean_headway, na.rm = TRUE) / 60, | |
| n_departures_peak = sum(n_departures, na.rm = TRUE), | |
| .groups = "drop" | |
| ) |> | |
| mutate(stop_id = as.character(stop_id)) | |
| }, error = function(e) { | |
| warning("tidytransit failed: ", e$message) | |
| NULL | |
| }) | |
| if (!is.null(gtfs_stop_headways) && !is.null(gtfs_stops_sf)) { | |
| gtfs_stops_sf <- gtfs_stops_sf |> | |
| mutate(stop_id = as.character(stop_id)) |> | |
| left_join(gtfs_stop_headways, by = "stop_id") | |
| } | |
| time_gtfs_headways <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "10_gtfs_headways", | |
| description = "Compute transit stop headways (AM peak)", | |
| time_sec = time_gtfs_headways, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 12. CalEnviroScreen | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| calenviro_path <- '/Users/diegoellis/Downloads/calenviroscreen40gdb_F_2021.gdb' | |
| if (!file.exists(calenviro_path)) { | |
| calenviro_path <- '/Users/diegoellis/Desktop/Projects/Presentations/Data_Schell_Lab_Tutorial/calenviroscreen40gdb_F_2021.gdb' | |
| } | |
| cenv_sf <- tryCatch({ | |
| sf::st_read(calenviro_path, quiet = TRUE) |> | |
| dplyr::filter(grepl("san francisco", County, ignore.case = TRUE), !is.na(CIscore)) |> | |
| dplyr::select( | |
| Tract, CIscore, CIscoreP, | |
| PM2_5, PM2_5_Pctl, Traffic, Traffic_Pctl, | |
| Poverty, Poverty_Pctl, HousBurd, HousBurd_Pctl, | |
| County | |
| ) |> | |
| sf::st_transform(4326) |> | |
| sf::st_make_valid() | |
| }, error = function(e) { | |
| warning("CalEnviroScreen failed: ", e$message) | |
| NULL | |
| }) | |
| time_calenviro <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "11_calenviro", | |
| description = "Load CalEnviroScreen layer", | |
| time_sec = time_calenviro, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # 13. SF EJ Communities | |
| # ============================================================================ | |
| t1 <- Sys.time() | |
| sf_ej_path <- '/Users/diegoellis/Downloads/San Francisco Environmental Justice Communities Map_20251217/geo_export_a21b0a0a-7306-46fd-8381-06581cdbe6e9.shp' | |
| sf_ej_sf <- tryCatch({ | |
| sf::st_read(sf_ej_path, quiet = TRUE) |> | |
| dplyr::mutate( | |
| symbol_hex = stringr::str_split(symbol_rgb, ",\\s*") |> | |
| lapply(function(x) sprintf("#%02X%02X%02X", | |
| as.integer(x[1]), as.integer(x[2]), as.integer(x[3]))) |> | |
| unlist(), | |
| ej_label = dplyr::case_when( | |
| is.na(score) ~ "Not EJ", | |
| score >= 21 ~ "High EJ burden (21-30)", | |
| score >= 11 ~ "Moderate EJ burden (11-20)", | |
| score >= 1 ~ "Low EJ burden (1-10)", | |
| score == 0 ~ "Score 0", | |
| TRUE ~ "Unknown" | |
| ) | |
| ) |> | |
| sf::st_transform(4326) |> | |
| sf::st_make_valid() | |
| }, error = function(e) { | |
| warning("SF EJ layer failed: ", e$message) | |
| NULL | |
| }) | |
| time_ej <- as.numeric(difftime(Sys.time(), t1, units = "secs")) | |
| benchmarks <- bind_rows(benchmarks, tibble( | |
| step = "12_ej", | |
| description = "Load SF EJ communities layer", | |
| time_sec = time_ej, | |
| time_pct = NA | |
| )) | |
| # ============================================================================ | |
| # SUMMARY | |
| # ============================================================================ | |
| time_overall <- as.numeric(difftime(Sys.time(), start_overall, units = "secs")) | |
| benchmarks <- benchmarks |> | |
| mutate(time_pct = round(100 * time_sec / time_overall, 1)) | |
| # Print results | |
| cat("\n") | |
| cat("================================================================================\n") | |
| cat("STARTUP PERFORMANCE BENCHMARK\n") | |
| cat("================================================================================\n\n") | |
| print(benchmarks |> select(step, description, time_sec, time_pct)) | |
| cat("\n") | |
| cat("TOTAL STARTUP TIME: ", round(time_overall, 2), " seconds\n") | |
| cat("================================================================================\n\n") | |
| # ============================================================================ | |
| # OPTIMIZATION RECOMMENDATIONS | |
| # ============================================================================ | |
| cat("OPTIMIZATION RECOMMENDATIONS:\n") | |
| cat("================================================================================\n\n") | |
| # Flag slow steps (>5 seconds or >10% of total) | |
| slow_steps <- benchmarks |> | |
| filter(time_sec > 5 | time_pct > 10) |> | |
| arrange(desc(time_sec)) | |
| if (nrow(slow_steps) > 0) { | |
| cat("CRITICAL BOTTLENECKS (>5s or >10%):\n\n") | |
| for (i in 1:nrow(slow_steps)) { | |
| row <- slow_steps[i, ] | |
| cat(" •", row$step, "(", row$time_sec, "s,", row$time_pct, "%)\n") | |
| cat(" Description:", row$description, "\n") | |
| if (grepl("libraries", row$step)) { | |
| cat(" Recommendation: Load packages only in server() if possible. Use lazy loading.\n") | |
| } else if (grepl("download", row$step)) { | |
| cat(" Recommendation: Cache downloaded files locally or use precomputed versions.\n") | |
| } else if (grepl("gtfsrouter|tidytransit", row$step)) { | |
| cat(" Recommendation: Pre-compute and cache GTFS timetable. Consider lazy loading for session.\n") | |
| } else if (grepl("calenviro|ej", row$step)) { | |
| cat(" Recommendation: Pre-filter to SF boundary. Store as .gpkg or parquet locally.\n") | |
| } | |
| cat("\n") | |
| } | |
| } else { | |
| cat("No critical bottlenecks detected (all steps < 5s).\n\n") | |
| } | |
| # Create visualization | |
| p <- ggplot(benchmarks, aes(x = reorder(step, -time_sec), y = time_sec, fill = time_pct)) + | |
| geom_col() + | |
| geom_text(aes(label = paste0(round(time_sec, 2), "s")), vjust = -0.3, size = 3) + | |
| scale_fill_gradient(low = "green", high = "red", name = "% of Total") + | |
| labs( | |
| title = "Shiny App Startup Performance Profile", | |
| subtitle = paste0("Total time: ", round(time_overall, 2), " seconds"), | |
| x = "Loading Step", | |
| y = "Time (seconds)" | |
| ) + | |
| theme_minimal() + | |
| theme( | |
| axis.text.x = element_text(angle = 45, hjust = 1, size = 9), | |
| plot.title = element_text(face = "bold", size = 14), | |
| legend.position = "right" | |
| ) | |
| print(p) | |
| ggsave("/Users/diegoellis/Desktop/Projects/Postdoc/Biodiversity_Access_Indicator/SF_biodiv_access_shiny/startup_benchmark.png", | |
| p, width = 12, height = 6, dpi = 150) | |
| cat("\nBenchmark plot saved to: startup_benchmark.png\n") | |
| # ============================================================================ | |
| # Export benchmark data | |
| # ============================================================================ | |
| write_csv(benchmarks, | |
| "/Users/diegoellis/Desktop/Projects/Postdoc/Biodiversity_Access_Indicator/SF_biodiv_access_shiny/startup_benchmarks.csv") | |
| cat("Benchmark data saved to: startup_benchmarks.csv\n\n") | |