{"id":49124521,"url":"https://github.com/shikokuchuo/mori","last_synced_at":"2026-04-22T14:00:44.325Z","repository":{"id":351782346,"uuid":"1212435025","full_name":"shikokuchuo/mori","owner":"shikokuchuo","description":"Shared Memory for R Objects","archived":false,"fork":false,"pushed_at":"2026-04-19T16:13:21.000Z","size":1588,"stargazers_count":18,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-21T13:44:30.474Z","etag":null,"topics":["r","shared-memory"],"latest_commit_sha":null,"homepage":"https://shikokuchuo.net/mori/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shikokuchuo.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-16T11:27:41.000Z","updated_at":"2026-04-21T10:20:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shikokuchuo/mori","commit_stats":null,"previous_names":["shikokuchuo/sora","shikokuchuo/mori"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shikokuchuo/mori","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shikokuchuo%2Fmori","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shikokuchuo%2Fmori/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shikokuchuo%2Fmori/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shikokuchuo%2Fmori/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shikokuchuo","download_url":"https://codeload.github.com/shikokuchuo/mori/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shikokuchuo%2Fmori/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32125094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T00:31:26.853Z","status":"online","status_checked_at":"2026-04-22T02:00:05.693Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["r","shared-memory"],"created_at":"2026-04-21T13:35:31.219Z","updated_at":"2026-04-22T14:00:44.318Z","avatar_url":"https://github.com/shikokuchuo.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n```\n\n# mori\n\n\u003c!-- badges: start --\u003e\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)\n[![R-CMD-check](https://github.com/shikokuchuo/mori/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/shikokuchuo/mori/actions/workflows/R-CMD-check.yaml)\n[![Codecov test coverage](https://codecov.io/gh/shikokuchuo/mori/graph/badge.svg)](https://app.codecov.io/gh/shikokuchuo/mori)\n\u003c!-- badges: end --\u003e\n\n      ________\n     /\\ mori  \\\n    /  \\       \\\n    \\  /  森   /\n     \\/_______/\n\nShared Memory for R Objects\n\n\n→ `share()` writes an R object into shared memory and returns a shared version\n\n→ ALTREP serialization hooks — shared objects serialize compactly and work transparently with `serialize()` and `mirai()`\n\n→ ALTREP-backed lazy access — a 100-column data frame is one `mmap`; columns materialize on first touch\n\n→ OS-level shared memory (POSIX / Win32) — pure C, no external dependencies; read-only in other processes, preventing corruption of shared data\n\n→ Automatic cleanup — shared memory is freed when the R object is garbage collected\n\n\u003cbr /\u003e\n\n## Installation\n\n``` r\ninstall.packages(\"mori\")\n```\n\n## Quick Start\n\n`share()` writes an R object once into shared memory and returns a\nzero-copy ALTREP view. Shared objects serialize compactly\nvia ALTREP serialization hooks, working transparently with mirai and any\nR serialization path. Shared memory is automatically freed when the\nobject is garbage collected.\n\n```{r quickstart}\nlibrary(mori)\n\n# Share a vector — returns an ALTREP-backed object\nx \u003c- share(rnorm(1e6))\nmean(x)\n\n# Serialized form is ~100 bytes, not ~8 MB\nx |\u003e serialize(NULL) |\u003e length()\n```\n\n## Sharing by Name\n\n`shared_name()` extracts the SHM name from a shared object.\n`map_shared()` opens a shared region by name — useful for accessing\nthe same data from another process without serialization:\n\n```{r byname}\nx \u003c- share(1:1e6)\n\n# Extract the SHM name\nnm \u003c- shared_name(x)\nnm\n\n# Another process can map the same region by name\ny \u003c- map_shared(nm)\nidentical(x[], y[])\n```\n\n## Use with mirai\n\nShared objects can be sent to local daemons — the ALTREP serialization\nhooks ensure only the SHM name crosses the wire, and the worker maps\nthe same physical memory.\n\n```{r mirai}\nlibrary(lobstr)\nlibrary(mirai)\n\ndaemons(1)\n\nx \u003c- share(rnorm(1e6))\n\n# Worker maps the same shared memory — 0 bytes copied\nm \u003c- mirai(list(mean = mean(x), size = lobstr::obj_size(x)), x = x)\nm[]\n\ndaemons(0)\n```\n\nElements of a shared list also serialize compactly — each element\ntravels as a reference to its position in the parent shared region,\nnot as the full data:\n\n```{r mirai_map}\ndaemons(3)\n\n# Share a list — all 3 vectors in a single shared region\nx \u003c- list(a = rnorm(1e6), b = rnorm(1e6), c = rnorm(1e6)) |\u003e share()\n\n# Each element is sent as (parent_name, index) — zero-copy on the worker\nmirai_map(x, \\(v) lobstr::obj_size(v) |\u003e format())[.flat]\n\ndaemons(0)\n```\n\n\n## Why mori\n\nParallel computing multiplies memory. When 8 workers each need the same\n210 MB dataset, that is 1.7 GB of serialization, transfer, and\ndeserialization — plus 8 separate copies consuming RAM.\n\nmori eliminates all of it. `share()` writes data into shared memory\nonce. Each worker maps the same physical pages, receiving a reference\nof ~300 bytes instead of the full dataset — a payload ~700,000 times\nsmaller, which translates into a significant saving in total runtime:\n\n```{r bench}\ndaemons(8)\n\n# 200 MB data frame — 5 columns × 5M rows\ndf \u003c- as.data.frame(matrix(rnorm(25e6), ncol = 5))\nshared_df \u003c- share(df)\n\nboot_mean \u003c- \\(i, data) colMeans(data[sample(nrow(data), replace = TRUE), ])\n\n# Without mori — each daemon deserializes a full copy\nmirai_map(1:8, boot_mean, data = df)[] |\u003e system.time()\n\n# With mori — each daemon maps the same shared memory\nmirai_map(1:8, boot_mean, data = shared_df)[] |\u003e system.time()\n\ndaemons(0)\n```\n\n## How It Works\n\n### What gets shared\n\nAll atomic vector types and lists / data frames are written directly\ninto shared memory, with attributes (`class`, `names`, `dim`, `levels`,\n`tzone`, …) preserved end-to-end. Pairlists are coerced to lists.\n`share()` returns ALTREP wrappers that point into the shared pages — no\ndeserialization, no per-process memory allocation.\n\nAll other R objects (environments, closures, language objects) are\nreturned unchanged by `share()` — no shared memory region is created.\n\n![Diagram showing share() writing an object once into OS-backed shared memory, which is then memory-mapped by other processes using zero-copy ALTREP wrappers](man/figures/mori-diagram.svg)\n\n### Lazy access\n\nA data frame with 10 columns lives in a single shared region; a task\nthat touches 3 columns pays for 3. Character strings are accessed\nlazily per element.\n\n### Lifetime\n\nShared memory is managed by R's garbage collector. The SHM region stays\nalive as long as the shared object (or any element extracted from it)\nis referenced in R. When no references remain, the garbage collector\nfrees the shared memory automatically.\n\n**Important:** Always assign the result of `share()` to a variable. The\nshared memory is kept alive by the R object reference — if the result\nis used as a temporary (not assigned), the garbage collector may free\nthe shared memory before a consumer process has mapped it.\n\n### Copy-on-write\n\nShared data is mapped read-only. Mutations are always local — R's\ncopy-on-write mechanism ensures other processes continue reading the\noriginal shared data:\n\n- **Structural changes** to a list or data frame (adding, removing, or\n  reordering elements) produce a regular R list. The shared region is\n  unaffected.\n- **Modifying values** within a shared vector (e.g., `X[1] \u003c- 0`)\n  materializes just that vector into a private copy. Other vectors in\n  the same shared region stay zero-copy.\n\n--\n\nPlease note that the mori project is released with a [Contributor Code of Conduct](https://shikokuchuo.net/mori/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshikokuchuo%2Fmori","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshikokuchuo%2Fmori","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshikokuchuo%2Fmori/lists"}