MyNixOS website logo
Description

Zero-Copy Julia to R Array Bridge via ALTREP.

Provides zero-copy R views of Julia-owned arrays by implementing ALTREP (Alternative Representations) classes that return pointers directly into Julia's memory. The package integrates with 'JuliaCall' and uses C-level finalizers for safe cross-runtime garbage collection.

jlview — Zero-Copy Julia↔R Arrays via ALTREP

R-CMD-check

jlview provides zero-copy R views of Julia-owned arrays using R’s ALTREP (Alternative Representations) framework. Instead of copying data between Julia and R, jlview returns lightweight R vectors that point directly into Julia’s memory.

LatencyR Memory
jlview (zero-copy)38 ms0 MB
copy (collect)2.7 s9.3 GB
Improvement72×100% savings

Benchmark: 50K × 25K Float64 matrix (9.3 GB)

Installation

# install.packages("remotes")
remotes::install_github("tanaylab/jlview")

Requirements

Usage

library(jlview)
JuliaCall::julia_setup()

# Create a Julia array
JuliaCall::julia_command("x = randn(10000, 1000)")

# Zero-copy view — R sees Julia's memory directly
m <- jlview(JuliaCall::julia_eval("x"))
dim(m) # [1] 10000  1000
sum(m) # works natively, no data copied

# Named arrays are supported
JuliaCall::julia_command("using NamedArrays")
JuliaCall::julia_command("named = NamedArray(randn(3), [\"a\", \"b\", \"c\"])")
v <- jlview_named_vector(JuliaCall::julia_eval("named"))
v["a"] # access by name, still zero-copy

# Sparse matrices (zero-copy values, shifted indices)
JuliaCall::julia_command("using SparseArrays")
JuliaCall::julia_command("sp = sprand(1000, 500, 0.01)")
s <- jlview_sparse(JuliaCall::julia_eval("sp"))
class(s) # "dgCMatrix"

# Explicit release to free Julia memory early
jlview_release(m)

Key Features

  • Zero-copy dense arrays — Float64, Int32 map directly to R’s REALSXP, INTSXP
  • Type conversion — Float32, Int64, Int16 are converted once in Julia, then zero-copy to R
  • Named arrays — NamedArray row/column names attached atomically without triggering copy
  • Sparse matricesdgCMatrix with zero-copy values (nzval) and shifted indices
  • Copy-on-write — R’s standard COW semantics: reads are zero-copy, writes trigger materialization
  • GC safety — Julia arrays are pinned while R holds references; three-layer defense (pinning dict, memory pressure tracking, explicit release)
  • Fork safety — Safe with parallel::mclapply() (PID-guarded finalizers)
  • SerializationsaveRDS()/readRDS() work correctly (materializes on save)

Supported Types

Julia typeR typeMethod
Array{Float64}numericDirect zero-copy
Array{Int32}integerDirect zero-copy
Array{Float32}numericConvert in Julia, then zero-copy
Array{Int64}numericConvert in Julia, then zero-copy
Array{Int16}integerConvert in Julia, then zero-copy
Array{UInt8}rawALTREP RAWSXP zero-copy
Array{Bool}logicalCopy (layout incompatible)
String[]characterCopy (layout incompatible)

How It Works

jlview uses R’s ALTREP framework to create R vectors backed by Julia memory:

  1. Pin — The Julia array is stored in a global dictionary, preventing Julia’s GC from collecting it
  2. Wrap — An ALTREP R vector is created whose Dataptr returns Julia’s raw data pointer
  3. Use — R operations (sum, subsetting, etc.) read directly from Julia’s memory
  4. Release — When R garbage-collects the ALTREP object, a C finalizer calls Julia to unpin the array

The entire pin→ALTREP→finalizer path is implemented in C using Julia’s C API (jl_call1), avoiding JuliaCall overhead and ensuring safety during R’s garbage collection.

Metadata

Version

0.1.0

License

Unknown

Platforms (80)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    uefi
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-uefi
  • aarch64-windows
  • aarch64_be-none
  • arc-linux
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-linux
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • sh4-linux
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-uefi
  • x86_64-windows