From f30af26cf54c5e10f7e01d535404f00870a1a82b Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 11 Mar 2020 17:39:14 +0000 Subject: [PATCH 1/2] Improve performance consistency Switch from HashMap / HashSet to IndexMap / IndexSet for consistent iteration order of various options and, as a result, more predictable performance. --- Cargo.lock | 12 +++++++++++ Cargo.toml | 2 ++ src/headers.rs | 4 ++-- src/lib.rs | 45 ++++++++++++++++++++---------------------- src/main.rs | 6 +++--- src/png/mod.rs | 6 +++--- src/reduction/alpha.rs | 12 +++++------ src/reduction/color.rs | 6 +++--- src/reduction/mod.rs | 5 ++--- tests/filters.rs | 8 +++----- tests/flags.rs | 8 +++----- tests/interlaced.rs | 6 ++---- tests/reduction.rs | 6 ++---- tests/regression.rs | 30 +++++++++++++--------------- 14 files changed, 78 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d65aec9a..14895d28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -192,6 +192,15 @@ dependencies = [ "png 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "inflate" version = "0.4.5" @@ -295,11 +304,13 @@ dependencies = [ "cloudflare-zlib 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rgb 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "wild 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "zopfli 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -460,6 +471,7 @@ dependencies = [ "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" "checksum image 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4e336ec01a678e7ab692914c641181528e8656451e6252f8f9e33728882eaf" +"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" diff --git a/Cargo.toml b/Cargo.toml index a59df56f..2d85b8fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,8 @@ num_cpus = "^1.0.0" zopfli = "^0.4.0" miniz_oxide = "0.3" rgb = "0.8.11" +vec_map = "0.8.1" +indexmap = { version = "1.3.2", features = ["rayon"] } [dependencies.rayon] optional = true diff --git a/src/headers.rs b/src/headers.rs index 1667bdbf..fcf92ae5 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -1,9 +1,9 @@ +use indexmap::IndexSet; use crate::colors::{BitDepth, ColorType}; use crate::error::PngError; use crate::PngResult; use byteorder::{BigEndian, ReadBytesExt}; use crc::crc32; -use std::collections::HashSet; use std::io::Cursor; #[derive(Debug, Clone, Copy)] @@ -35,7 +35,7 @@ pub enum Headers { /// Headers that won't affect rendering (all but cHRM, gAMA, iCCP, sBIT, sRGB, bKGD, hIST, pHYs, sPLT) Safe, /// Remove all non-critical chunks except these - Keep(HashSet), + Keep(IndexSet), /// All non-critical headers All, } diff --git a/src/lib.rs b/src/lib.rs index 5227bc0f..38888f0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,8 +28,8 @@ use crate::png::PngImage; use crate::reduction::*; use crc::crc32; use image::{DynamicImage, GenericImageView, ImageFormat, Pixel}; +use indexmap::{IndexSet, IndexMap}; use rayon::prelude::*; -use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt; use std::fs::{copy, File}; use std::io::{stdin, stdout, BufWriter, Read, Write}; @@ -154,7 +154,7 @@ pub struct Options { /// Which filters to try on the file (0-5) /// /// Default: `0,5` - pub filter: HashSet, + pub filter: IndexSet, /// Whether to change the interlacing type of the file. /// /// `None` will not change the current interlacing type. @@ -166,11 +166,11 @@ pub struct Options { /// Which zlib compression levels to try on the file (1-9) /// /// Default: `9` - pub compression: HashSet, + pub compression: IndexSet, /// Which zlib compression strategies to try on the file (0-3) /// /// Default: `0-3` - pub strategies: HashSet, + pub strategies: IndexSet, /// Window size to use when compressing the file, as `2^window` bytes. /// /// Doesn't affect compression but may affect speed and memory usage. @@ -179,7 +179,7 @@ pub struct Options { /// Default: `15` pub window: u8, /// Alpha filtering strategies to use - pub alphas: HashSet, + pub alphas: IndexSet, /// Whether to attempt bit depth reduction /// /// Default: `true` @@ -286,17 +286,17 @@ impl Options { impl Default for Options { fn default() -> Options { // Default settings based on -o 2 from the CLI interface - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(0); filter.insert(5); - let mut compression = HashSet::new(); + let mut compression = IndexSet::new(); compression.insert(9); - let mut strategies = HashSet::new(); + let mut strategies = IndexSet::new(); for i in 0..4 { strategies.insert(i); } // We always need NoOp to be present - let mut alphas = HashSet::new(); + let mut alphas = IndexSet::new(); alphas.insert(AlphaOptim::NoOp); Options { @@ -501,7 +501,7 @@ fn optimize_png( eprintln!(" File size = {} bytes", file_original_size); } - let mut filter = opts.filter.iter().cloned().collect::>(); + let mut filter = opts.filter.clone(); let compression = &opts.compression; let mut strategies = opts.strategies.clone(); @@ -511,14 +511,14 @@ fn optimize_png( && png.raw.ihdr.color_type != colors::ColorType::Indexed { if filter.is_empty() { - filter.push(5); + filter.insert(5); } if strategies.is_empty() { strategies.insert(1); } } else { if filter.is_empty() { - filter.push(0); + filter.insert(0); } if strategies.is_empty() { strategies.insert(0); @@ -582,8 +582,10 @@ fn optimize_png( eprintln!("Trying: {} combinations", results.len()); } - let filter_iter = filter.par_iter().with_max_len(1); - let filters: HashMap> = filter_iter + let filters: IndexMap> = + filter + .par_iter() + .with_max_len(1) .map(|f| { let png = png.clone(); (*f, png.raw.filter_image(*f)) @@ -864,15 +866,10 @@ fn perform_strip(png: &mut PngData, opts: &Options) { // Strip headers Headers::None => (), Headers::Keep(ref hdrs) => { - let keys: Vec<[u8; 4]> = raw.aux_headers.keys().cloned().collect(); - for hdr in &keys { - let preserve = std::str::from_utf8(hdr) - .ok() - .map_or(false, |name| hdrs.contains(name)); - if !preserve { - raw.aux_headers.remove(hdr); - } - } + raw.aux_headers.retain(|hdr, _| { + std::str::from_utf8(hdr) + .map_or(false, |name| hdrs.contains(name)) + }) } Headers::Strip(ref hdrs) => { for hdr in hdrs { @@ -892,7 +889,7 @@ fn perform_strip(png: &mut PngData, opts: &Options) { } } Headers::All => { - raw.aux_headers = BTreeMap::new(); + raw.aux_headers = IndexMap::new(); } } diff --git a/src/main.rs b/src/main.rs index 29631f58..473e6679 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,13 +14,13 @@ #![allow(clippy::cognitive_complexity)] use clap::{App, AppSettings, Arg, ArgMatches}; +use indexmap::IndexSet; use oxipng::AlphaOptim; use oxipng::Deflaters; use oxipng::Headers; use oxipng::Options; use oxipng::PngResult; use oxipng::{InFile, OutFile}; -use std::collections::HashSet; use std::fs::DirBuilder; use std::path::PathBuf; use std::process::exit; @@ -492,9 +492,9 @@ fn parse_numeric_range_opts( input: &str, min_value: u8, max_value: u8, -) -> Result, String> { +) -> Result, String> { const ERROR_MESSAGE: &str = "Not a valid input"; - let mut items = HashSet::new(); + let mut items = IndexSet::new(); // one value if let Ok(one_value) = input.parse::() { diff --git a/src/png/mod.rs b/src/png/mod.rs index 5ad3bed6..ee425ae6 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -6,9 +6,9 @@ use crate::headers::*; use crate::interlace::{deinterlace_image, interlace_image}; use byteorder::{BigEndian, WriteBytesExt}; use crc::crc32; +use indexmap::IndexMap; use rgb::ComponentSlice; use rgb::RGBA8; -use std::collections::BTreeMap; use std::fs::File; use std::io::{Read, Seek, SeekFrom}; use std::iter::Iterator; @@ -38,7 +38,7 @@ pub struct PngImage { /// The pixel value that should be rendered as transparent pub transparency_pixel: Option>, /// All non-critical headers from the PNG are stored here - pub aux_headers: BTreeMap<[u8; 4], Vec>, + pub aux_headers: IndexMap<[u8; 4], Vec>, } /// Contains all data relevant to a PNG image @@ -97,7 +97,7 @@ impl PngData { } byte_offset += 8; // Read the data headers - let mut aux_headers: BTreeMap<[u8; 4], Vec> = BTreeMap::new(); + let mut aux_headers: IndexMap<[u8; 4], Vec> = IndexMap::new(); let mut idat_headers: Vec = Vec::new(); while let Some(header) = parse_next_header(byte_data, &mut byte_offset, fix_errors)? { match &header.name { diff --git a/src/reduction/alpha.rs b/src/reduction/alpha.rs index 95b03744..39fa4f52 100644 --- a/src/reduction/alpha.rs +++ b/src/reduction/alpha.rs @@ -1,3 +1,4 @@ +use indexmap::IndexSet; use crate::colors::AlphaOptim; use crate::colors::ColorType; use crate::evaluate::Evaluator; @@ -8,22 +9,21 @@ use crate::png::PngImage; use crate::rayon::prelude::*; #[cfg(feature = "parallel")] use rayon::prelude::*; -use std::collections::HashSet; use std::sync::Arc; pub(crate) fn try_alpha_reductions( png: Arc, - alphas: &HashSet, + alphas: &IndexSet, eval: &Evaluator, ) { if alphas.is_empty() { return; } - let alphas = alphas.iter().collect::>(); - let alphas_iter = alphas.par_iter().with_max_len(1); - alphas_iter - .filter_map(|&alpha| filtered_alpha_channel(&png, *alpha)) + alphas + .par_iter() + .with_max_len(1) + .filter_map(|&alpha| filtered_alpha_channel(&png, alpha)) .for_each(|image| eval.try_image(Arc::new(image), 0.99)); } diff --git a/src/reduction/color.rs b/src/reduction/color.rs index bd692dc8..8be17402 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -1,9 +1,9 @@ use crate::colors::{BitDepth, ColorType}; use crate::headers::IhdrData; use crate::png::PngImage; +use indexmap::IndexMap; use itertools::Itertools; use rgb::{FromSlice, RGB8, RGBA8}; -use std::collections::HashMap; use std::hash::Hash; #[must_use] @@ -76,7 +76,7 @@ pub fn reduce_rgba_to_grayscale_alpha(png: &PngImage) -> Option { fn reduce_scanline_to_palette( iter: impl IntoIterator, - palette: &mut HashMap, + palette: &mut IndexMap, reduced: &mut Vec, ) -> bool where @@ -105,7 +105,7 @@ pub fn reduced_color_to_palette(png: &PngImage) -> Option { return None; } let mut raw_data = Vec::with_capacity(png.data.len()); - let mut palette = HashMap::with_capacity(257); + let mut palette = IndexMap::with_capacity(257); let transparency_pixel = png .transparency_pixel .as_ref() diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index 702e9cf0..b486d8fc 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -1,10 +1,9 @@ use crate::colors::{BitDepth, ColorType}; use crate::headers::IhdrData; use crate::png::PngImage; +use indexmap::map::{IndexMap, Entry::*}; use rgb::RGBA8; use std::borrow::Cow; -use std::collections::hash_map::Entry::*; -use std::collections::HashMap; pub mod alpha; use crate::alpha::*; @@ -79,7 +78,7 @@ pub fn reduced_palette(png: &PngImage) -> Option { }); let mut next_index = 0u16; - let mut seen = HashMap::with_capacity(palette.len()); + let mut seen = IndexMap::with_capacity(palette.len()); for (i, used) in used_enumerated.iter().cloned() { if !used { continue; diff --git a/tests/filters.rs b/tests/filters.rs index 3bc4e56e..41f92ca8 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -1,8 +1,6 @@ -use oxipng; - +use indexmap::IndexSet; use oxipng::internal_tests::*; use oxipng::{InFile, OutFile}; -use std::collections::HashSet; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -11,7 +9,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options::default(); options.verbosity = None; options.force = true; - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; @@ -33,7 +31,7 @@ fn test_it_converts( let (output, mut opts) = get_opts(&input); let png = PngData::new(&input, opts.fix_errors).unwrap(); - opts.filter = HashSet::new(); + opts.filter = IndexSet::new(); opts.filter.insert(filter); assert_eq!(png.raw.ihdr.color_type, color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); diff --git a/tests/flags.rs b/tests/flags.rs index 1e9a43f7..260402ef 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -1,8 +1,6 @@ -extern crate oxipng; - +use indexmap::IndexSet; use oxipng::internal_tests::*; use oxipng::{InFile, OutFile}; -use std::collections::HashSet; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -11,7 +9,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options::default(); options.verbosity = None; options.force = true; - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; @@ -342,7 +340,7 @@ fn interlaced_0_to_1_other_filter_mode() { let input = PathBuf::from("tests/files/interlaced_0_to_1_other_filter_mode.png"); let (output, mut opts) = get_opts(&input); opts.interlace = Some(1); - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(4); opts.filter = filter; diff --git a/tests/interlaced.rs b/tests/interlaced.rs index 7b93f0ee..8bc93df1 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -1,8 +1,6 @@ -extern crate oxipng; - +use indexmap::IndexSet; use oxipng::internal_tests::*; use oxipng::{InFile, OutFile}; -use std::collections::HashSet; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -11,7 +9,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options::default(); options.verbosity = None; options.force = true; - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; diff --git a/tests/reduction.rs b/tests/reduction.rs index d3b5cc5a..a27cd2a0 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -1,8 +1,6 @@ -use oxipng; - +use indexmap::IndexSet; use oxipng::internal_tests::*; use oxipng::{InFile, OutFile}; -use std::collections::HashSet; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -11,7 +9,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options::default(); options.verbosity = None; options.force = true; - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; diff --git a/tests/regression.rs b/tests/regression.rs index 867902ab..096fe8d8 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -1,8 +1,6 @@ -use oxipng; - +use indexmap::IndexSet; use oxipng::internal_tests::*; use oxipng::{InFile, OutFile}; -use std::collections::HashSet; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -11,7 +9,7 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options::default(); options.verbosity = None; options.force = true; - let mut filter = HashSet::new(); + let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; @@ -309,7 +307,7 @@ fn issue_113_white() { let input = "tests/files/issue-113.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(1); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Black); let output = OutFile::Path(Some( Path::new(input).with_extension("-white-out.png").to_owned(), @@ -329,7 +327,7 @@ fn issue_113_black() { let input = "tests/files/issue-113.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(1); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Black); let output = OutFile::Path(Some( Path::new(input).with_extension("-black-out.png").to_owned(), @@ -349,7 +347,7 @@ fn issue_113_right() { let input = "tests/files/issue-113.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(1); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Right); let output = OutFile::Path(Some( Path::new(input).with_extension("-right-out.png").to_owned(), @@ -369,7 +367,7 @@ fn issue_113_left() { let input = "tests/files/issue-113.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(1); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Left); let output = OutFile::Path(Some( Path::new(input).with_extension("-left-out.png").to_owned(), @@ -389,7 +387,7 @@ fn issue_113_up() { let input = "tests/files/issue-113.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(1); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Up); let output = OutFile::Path(Some( Path::new(input).with_extension("-up-out.png").to_owned(), @@ -409,7 +407,7 @@ fn issue_113_down() { let input = "tests/files/issue-113.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(1); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Down); let output = OutFile::Path(Some( Path::new(input).with_extension("-down-out.png").to_owned(), @@ -441,7 +439,7 @@ fn issue_129() { fn issue_133_black() { let input = "tests/files/issue-133.png"; let (_, mut opts) = get_opts(Path::new(input)); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Black); let output = OutFile::Path(Some( Path::new(input).with_extension("-black-out.png").to_owned(), @@ -460,7 +458,7 @@ fn issue_133_black() { fn issue_133_white() { let input = "tests/files/issue-133.png"; let (_, mut opts) = get_opts(Path::new(input)); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::White); let output = OutFile::Path(Some( Path::new(input).with_extension("-white-out.png").to_owned(), @@ -479,7 +477,7 @@ fn issue_133_white() { fn issue_133_up() { let input = "tests/files/issue-133.png"; let (_, mut opts) = get_opts(Path::new(input)); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Up); let output = OutFile::Path(Some( Path::new(input).with_extension("-up-out.png").to_owned(), @@ -498,7 +496,7 @@ fn issue_133_up() { fn issue_133_down() { let input = "tests/files/issue-133.png"; let (_, mut opts) = get_opts(Path::new(input)); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Down); let output = OutFile::Path(Some( Path::new(input).with_extension("-down-out.png").to_owned(), @@ -517,7 +515,7 @@ fn issue_133_down() { fn issue_133_right() { let input = "tests/files/issue-133.png"; let (_, mut opts) = get_opts(Path::new(input)); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Right); let output = OutFile::Path(Some( Path::new(input).with_extension("-right-out.png").to_owned(), @@ -536,7 +534,7 @@ fn issue_133_right() { fn issue_133_left() { let input = "tests/files/issue-133.png"; let (_, mut opts) = get_opts(Path::new(input)); - opts.alphas = HashSet::new(); + opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Left); let output = OutFile::Path(Some( Path::new(input).with_extension("-left-out.png").to_owned(), From 006e76f972a4944131291739fd5d4d673c181769 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 1 Apr 2020 01:30:40 +0100 Subject: [PATCH 2/2] Remove temporary dependency --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f72a2ca6..d1a2280a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ num_cpus = "^1.0.0" zopfli = "^0.4.0" miniz_oxide = "0.3" rgb = "0.8.11" -vec_map = "0.8.1" indexmap = { version = "1.3.2", features = ["rayon"] } [dependencies.rayon]