Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: parse points without heap allocation #223

Draft
wants to merge 28 commits into
base: mkirk/tiny-vec
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f0b72a2
spike on tinyvec
michaelkirk Aug 26, 2022
9778880
Position as opaque struct
michaelkirk Apr 6, 2023
a9d1f0e
BREAKING: address geo deprecations
michaelkirk Apr 7, 2023
6de1b4c
wip: parse points on stack
michaelkirk Apr 7, 2023
2ecceeb
wip: FeatureIterator not from json value
michaelkirk Apr 7, 2023
50aa2fb
DO NOT MERGE: added pretty_env_logger for debugging
michaelkirk Apr 7, 2023
fa89704
wip: deserializes geometry w/o JsonObject, but temporarily Ive broken…
michaelkirk Apr 7, 2023
db625f9
add test and make Id ser/de
michaelkirk Apr 7, 2023
6ef83b0
try to use derived ser/de
michaelkirk Apr 7, 2023
fa882c4
maybe dont merge... trying to see if the tagging is hurting my perf
michaelkirk Apr 7, 2023
3980aab
WIP: CoordField visitor
michaelkirk Apr 7, 2023
356b4cf
wip: the countries parse is now a little faster than tiny_vec! But ho…
michaelkirk Apr 8, 2023
5978430
disable custom serialization benches for now
michaelkirk Apr 8, 2023
7490611
formatting?
michaelkirk Apr 10, 2023
840ea37
fixup
michaelkirk Apr 10, 2023
1031b26
fix geometrycollection
michaelkirk Apr 10, 2023
2aa6856
fix point geometry
michaelkirk Apr 10, 2023
98f6693
Geometry type is not "Geometry", so this cannot be considered "tagged"
michaelkirk Apr 10, 2023
bc21f44
notes and cleanup
michaelkirk Apr 10, 2023
f0b6201
tagging top level geometry
michaelkirk Apr 10, 2023
7b1570f
remove redundant logger
michaelkirk Apr 10, 2023
a8708a0
geometry field is optional for Feature
michaelkirk Apr 10, 2023
4096bb2
better debug output
michaelkirk Apr 10, 2023
36d237a
NBD: format as guard
michaelkirk Apr 10, 2023
9d41e27
"type" is consumed by outer deserializer
michaelkirk Apr 10, 2023
83036d6
properties are optional
michaelkirk Apr 10, 2023
be9f602
accumulate foreign_members on feature collection
michaelkirk Apr 10, 2023
bbff616
expect different error
michaelkirk Apr 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ serde_json = "~1.0"
geo-types = { version = "0.7", features = ["serde"], optional = true }
thiserror = "1.0.20"
log = "0.4.17"
tinyvec = { version = "1.6.0", features = ["serde", "alloc"] }

[dev-dependencies]
num-traits = "0.2"
criterion = "0.4.0"
pretty_env_logger = "0.4.0"

[[bench]]
name = "parse"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ let geojson = geojson_str.parse::<GeoJson>().unwrap();
use geojson::{Feature, GeoJson, Geometry, Value, JsonObject, JsonValue};

let geometry = Geometry::new(
Value::Point(vec![-120.66029,35.2812])
Value::Point(Position::from([-120.66029,35.2812]))
);

let mut properties = JsonObject::new();
Expand Down
100 changes: 49 additions & 51 deletions benches/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ fn parse_feature_collection_benchmark(c: &mut Criterion) {
let geojson_str = include_str!("../tests/fixtures/countries.geojson");

c.bench_function("parse (countries.geojson)", |b| {
b.iter(|| match geojson_str.parse::<geojson::GeoJson>() {
Ok(GeoJson::FeatureCollection(fc)) => {
assert_eq!(fc.features.len(), 180);
black_box(fc)
}
_ => panic!("unexpected result"),
b.iter(|| {
let fc = geojson_str.parse::<geojson::FeatureCollection>().unwrap();
assert_eq!(fc.features.len(), 180);
black_box(fc);
})
});

Expand All @@ -32,52 +30,52 @@ fn parse_feature_collection_benchmark(c: &mut Criterion) {
});
});

c.bench_function("FeatureReader::deserialize (countries.geojson)", |b| {
b.iter(|| {
#[allow(unused)]
#[derive(serde::Deserialize)]
struct Country {
geometry: geojson::Geometry,
name: String,
}
let feature_reader =
geojson::FeatureReader::from_reader(BufReader::new(geojson_str.as_bytes()));

let mut count = 0;
for feature in feature_reader.deserialize::<Country>().unwrap() {
let feature = feature.unwrap();
black_box(feature);
count += 1;
}
assert_eq!(count, 180);
});
});

#[cfg(feature = "geo-types")]
c.bench_function(
"FeatureReader::deserialize to geo-types (countries.geojson)",
|b| {
b.iter(|| {
#[allow(unused)]
#[derive(serde::Deserialize)]
struct Country {
#[serde(deserialize_with = "deserialize_geometry")]
geometry: geo_types::Geometry,
name: String,
}
let feature_reader =
geojson::FeatureReader::from_reader(BufReader::new(geojson_str.as_bytes()));
// c.bench_function("FeatureReader::deserialize (countries.geojson)", |b| {
// b.iter(|| {
// #[allow(unused)]
// #[derive(serde::Deserialize)]
// struct Country {
// geometry: geojson::Geometry,
// name: String,
// }
// let feature_reader =
// geojson::FeatureReader::from_reader(BufReader::new(geojson_str.as_bytes()));
//
// let mut count = 0;
// for feature in feature_reader.deserialize::<Country>().unwrap() {
// let feature = feature.unwrap();
// black_box(feature);
// count += 1;
// }
// assert_eq!(count, 180);
// });
// });

let mut count = 0;
for feature in feature_reader.deserialize::<Country>().unwrap() {
let feature = feature.unwrap();
black_box(feature);
count += 1;
}
assert_eq!(count, 180);
});
},
);
// #[cfg(feature = "geo-types")]
// c.bench_function(
// "FeatureReader::deserialize to geo-types (countries.geojson)",
// |b| {
// b.iter(|| {
// #[allow(unused)]
// #[derive(serde::Deserialize)]
// struct Country {
// #[serde(deserialize_with = "deserialize_geometry")]
// geometry: geo_types::Geometry,
// name: String,
// }
// let feature_reader =
// geojson::FeatureReader::from_reader(BufReader::new(geojson_str.as_bytes()));
//
// let mut count = 0;
// for feature in feature_reader.deserialize::<Country>().unwrap() {
// let feature = feature.unwrap();
// black_box(feature);
// count += 1;
// }
// assert_eq!(count, 180);
// });
// },
// );
}

fn parse_geometry_collection_benchmark(c: &mut Criterion) {
Expand Down
98 changes: 49 additions & 49 deletions benches/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,56 +18,56 @@ fn serialize_feature_collection_benchmark(c: &mut Criterion) {
},
);

c.bench_function("serialize custom struct (countries.geojson)", |b| {
#[derive(serde::Serialize, serde::Deserialize)]
struct Country {
geometry: geojson::Geometry,
name: String,
}
let features =
geojson::de::deserialize_feature_collection_str_to_vec::<Country>(geojson_str).unwrap();
assert_eq!(features.len(), 180);
// c.bench_function("serialize custom struct (countries.geojson)", |b| {
// #[derive(serde::Serialize, serde::Deserialize)]
// struct Country {
// geometry: geojson::Geometry,
// name: String,
// }
// let features =
// geojson::de::deserialize_feature_collection_str_to_vec::<Country>(geojson_str).unwrap();
// assert_eq!(features.len(), 180);
//
// b.iter(|| {
// let geojson_string = geojson::ser::to_feature_collection_string(&features).unwrap();
// // Sanity check that we serialized a long string of some kind.
// //
// // Note this is slightly shorter than the GeoJson round-trip above because we drop
// // some fields, like foreign members
// assert_eq!(geojson_string.len(), 254908);
// black_box(geojson_string);
// });
// });

b.iter(|| {
let geojson_string = geojson::ser::to_feature_collection_string(&features).unwrap();
// Sanity check that we serialized a long string of some kind.
//
// Note this is slightly shorter than the GeoJson round-trip above because we drop
// some fields, like foreign members
assert_eq!(geojson_string.len(), 254908);
black_box(geojson_string);
});
});

#[cfg(feature = "geo-types")]
c.bench_function(
"serialize custom struct to geo-types (countries.geojson)",
|b| {
#[derive(serde::Serialize, serde::Deserialize)]
struct Country {
#[serde(
serialize_with = "serialize_geometry",
deserialize_with = "deserialize_geometry"
)]
geometry: geo_types::Geometry,
name: String,
}
let features =
geojson::de::deserialize_feature_collection_str_to_vec::<Country>(geojson_str)
.unwrap();
assert_eq!(features.len(), 180);

b.iter(|| {
let geojson_string = geojson::ser::to_feature_collection_string(&features).unwrap();
// Sanity check that we serialized a long string of some kind.
//
// Note this is slightly shorter than the GeoJson round-trip above because we drop
// some fields, like foreign members
assert_eq!(geojson_string.len(), 254908);
black_box(geojson_string);
});
},
);
// #[cfg(feature = "geo-types")]
// c.bench_function(
// "serialize custom struct to geo-types (countries.geojson)",
// |b| {
// #[derive(serde::Serialize, serde::Deserialize)]
// struct Country {
// #[serde(
// serialize_with = "serialize_geometry",
// deserialize_with = "deserialize_geometry"
// )]
// geometry: geo_types::Geometry,
// name: String,
// }
// let features =
// geojson::de::deserialize_feature_collection_str_to_vec::<Country>(geojson_str)
// .unwrap();
// assert_eq!(features.len(), 180);
//
// b.iter(|| {
// let geojson_string = geojson::ser::to_feature_collection_string(&features).unwrap();
// // Sanity check that we serialized a long string of some kind.
// //
// // Note this is slightly shorter than the GeoJson round-trip above because we drop
// // some fields, like foreign members
// assert_eq!(geojson_string.len(), 254908);
// black_box(geojson_string);
// });
// },
// );
}

criterion_group!(benches, serialize_feature_collection_benchmark);
Expand Down
21 changes: 10 additions & 11 deletions src/conversion/from_geo_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,15 @@ where
{
let x: f64 = point.x().to_f64().unwrap();
let y: f64 = point.y().to_f64().unwrap();

vec![x, y]
crate::Position::from([x, y])
}

fn create_line_string_type<T>(line_string: &geo_types::LineString<T>) -> LineStringType
where
T: CoordFloat,
{
line_string
.points_iter()
.points()
.map(|point| create_point_type(&point))
.collect()
}
Expand Down Expand Up @@ -242,7 +241,7 @@ where
{
let mut coords = vec![polygon
.exterior()
.points_iter()
.points()
.map(|point| create_point_type(&point))
.collect()];

Expand Down Expand Up @@ -271,8 +270,8 @@ where
mod tests {
use crate::{GeoJson, Geometry, Value};
use geo_types::{
Coordinate, GeometryCollection, Line, LineString, MultiLineString, MultiPoint,
MultiPolygon, Point, Polygon, Rect, Triangle,
Coord, GeometryCollection, Line, LineString, MultiLineString, MultiPoint, MultiPolygon,
Point, Polygon, Rect, Triangle,
};

#[test]
Expand Down Expand Up @@ -356,9 +355,9 @@ mod tests {

#[test]
fn geo_triangle_conversion_test() {
let c1 = Coordinate { x: 0., y: 0. };
let c2 = Coordinate { x: 10., y: 20. };
let c3 = Coordinate { x: 20., y: -10. };
let c1 = Coord { x: 0., y: 0. };
let c2 = Coord { x: 10., y: 20. };
let c3 = Coord { x: 20., y: -10. };

let triangle = Triangle(c1, c2, c3);

Expand All @@ -381,8 +380,8 @@ mod tests {

#[test]
fn geo_rect_conversion_test() {
let c1 = Coordinate { x: 0., y: 0. };
let c2 = Coordinate { x: 10., y: 20. };
let c1 = Coord { x: 0., y: 0. };
let c2 = Coord { x: 10., y: 20. };

let rect = Rect::new(c1, c2);

Expand Down
Loading
Loading