Description
I simplified it as much as possible. Here's my Cargo.toml
[package]
name = "geos-geometry"
version = "0.1.0"
edition = "2021"
[dependencies]
geos = "9.0.0"
rocket = "0.5.1"
main.rs:
#[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
let _: Vec<geos::Geometry> = (0..2_000_000)
.map(|_| geos::Geometry::create_empty_point().unwrap())
.collect();
"finished"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
GEOS version: 3.12.1-CAPI-1.18.1
Every time I request curl http://127.0.0.1:8000/
, I get a +3GB spike in memory. It never frees it. It continues allocating more and more until my OS runs out of memory and crashes. I'm on Ubuntu 24.04.
If you think this is related to rocket, I don't think it is. Here's a code where I only used Vec<i64>
:
#[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
let n: i64 = 1_000_000_000;
let mut array: Vec<i64> = Vec::with_capacity(n as usize);
for i in 0..n {
array.push(i);
}
"finished"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
This code spikes memory to about 7GB, but it instantly frees after the request is completed.
Here's the geos-sys version:
use geos::sys::{
GEOSGeom_createEmptyPoint_r, GEOSGeom_destroy_r, GEOSGeom_t, GEOS_finish_r, GEOS_init_r,
};
#[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
let ctx = unsafe { GEOS_init_r() };
let n = 10_000_000;
let mut geometries: Vec<*mut GEOSGeom_t> = Vec::with_capacity(n);
for _ in 0..n {
let geom;
unsafe {
geom = GEOSGeom_createEmptyPoint_r(ctx);
}
geometries.push(geom);
}
for geom in geometries {
unsafe {
GEOSGeom_destroy_r(ctx, geom);
}
}
unsafe {
GEOS_finish_r(ctx);
}
"finished"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
Interesting, but why geos::Geometry::create_empty_point()
creates a separate context for each new geometry? According to GEOS_init_r(), the context should be passed to other _r
functions. I think that's using a lot of memory.
In this geos-sys code, I was able to create 10 million points and only take up 1GB. The memory usage spiked from 1GB, 2GB, 3GB, and then it stayed on 3GB.