Proposal: Feature flags for Additional functionalities
In line with #158 & #165, features such as image,drawing,chart support can be moved to a single/multiple feature flags as per the broad consensus of the community. This would reduce the size, execution times and memory footprints of the binary and can in general be good for flexibility of the system. Note: Same is being implemented with Calamine library which can be investigated for replication.
@agentjill Thank you for your suggestion. I agree with your response to features. Let's definitely do it.
Absolutely worth it. As written in a guide:
This is undoubtedly a very useful feature to have for some applications, but in the context of rust-analyzer we don’t need it. Simple env_logger-style filtering would be enough.
Once you identify a similar redundant dependency, it’s usually enough to tweak features field somewhere, or to send a PR upstream to make non-essential bits configurable.
If we check the compilation with cargo +nightly build -p YOUR_PACKAGE --timings --release, we may see that these image encoders/decoders take a huge time, even though in my project I don't really them. The image to be inserted into a cell is just a include_bytes!("some.jpg") and is already encoded.
| Unit | Total | Codegen | Features |
|---|---|---|---|
| image v0.25.2 | 22.5s | 20.1s (89%) | avif, bmp, dds, default, default-formats, exr, ff, gif, hdr, ico, jpeg, png, pnm, qoi, rayon, tga, tiff, webp |
| ravif v0.11.10 | 20.5s | 20.1s (98%) | |
| rav1e v0.7.1 | 7.0s | 2.7s (39%) |
@xamgore Thanks for the useful information! I will try to proceed with this correspondence as soon as possible.
The issue can be fixed in many ways.
The first is to proxy all the image codec features through umya-spreadsheet. So if someone needs png they will turn on the feature umya-spreadsheet = { version = "*", features = ["image/png"] }. Most of the time, people insert only one concrete, static image, so... that's enough for them.
On the other hand, when people insert an image from a previously defined set (for example, organization stamps which are meant to be printed on paper), usually those images have the same dimensions, to prevent bloating. Which means a new method could be made:
#[cfg(feature = "image")]
pub fn new_image(&mut self, path: &str, marker: MarkerType) {
let path = std::path::Path::new(path);
let img = image::open(path).unwrap();
let (width, height) = img.dimensions(); // 👈 the image crate is only used here
self.new_image_with_dimensions(path, height, width, marker) // so we just pass dimensions
}
pub fn new_image_with_dimensions(&mut self, path: &str, height: i64, width: i64, marker: MarketType) {
let mut file = File::open(path).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap(); // caution: lacks std::read::BufReader
picture.set_image_data(buf);
// ...
one_cell_anchor.get_extent_mut().set_cy(height as i64 * 9525);
one_cell_anchor.get_extent_mut().set_cx(width as i64 * 9525);
one_cell_anchor.set_picture(picture);
}
Also, people may want to include_bytes!("picture.jpg") or pass an in-memory buffer, which they got from a user or dynamically download on the Internet. So the method could become even more straightforward, letting the user do I/O themselves:
pub fn new_image_with_dimensions<B: Into<Vec<u8>>>(&mut self, buf: B, height: i64, width: i64, marker: MarketType) {
picture.set_image_data(buf.into());
// ...
one_cell_anchor.get_extent_mut().set_cy(height as i64 * 9525);
one_cell_anchor.get_extent_mut().set_cx(width as i64 * 9525);
one_cell_anchor.set_picture(picture);
}
Don't you mind helping me with a PR?
@MathNya if you wish to include this, you can create a feature branch. This will facilitate development of the necessary feature which could be merged on suitable time.