diff --git a/flamegraphs/06-use-read_line/flamegraph.svg b/flamegraphs/06-use-read_line/flamegraph.svg new file mode 100644 index 0000000..776d59a --- /dev/null +++ b/flamegraphs/06-use-read_line/flamegraph.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch <alloc::string::String as core::ops::deref::Deref>::deref (212 samples, 0.28%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (212 samples, 0.28%)alloc::vec::Vec<T,A>::as_ptr (210 samples, 0.28%)alloc::raw_vec::RawVec<T,A>::ptr (210 samples, 0.28%)core::ptr::drop_in_place<core::result::Result<usize,std::io::error::Error>> (242 samples, 0.32%)<F as core::str::pattern::Pattern>::into_searcher (13 samples, 0.02%)<core::str::pattern::MultiCharEqPattern<C> as core::str::pattern::Pattern>::into_searcher (13 samples, 0.02%)core::str::<impl str>::char_indices (13 samples, 0.02%)core::str::<impl str>::chars (13 samples, 0.02%)core::slice::<impl [T]>::iter (13 samples, 0.02%)core::slice::iter::Iter<T>::new (13 samples, 0.02%)core::str::<impl str>::trim_matches (13 samples, 0.02%)<F as core::str::pattern::MultiCharEq>::matches (503 samples, 0.67%)core::str::_<impl str>::trim::_{{closure}} (503 samples, 0.67%)core::char::methods::<impl char>::is_whitespace (503 samples, 0.67%)<core::slice::iter::Iter<T> as core::iter::traits::double_ended::DoubleEndedIterator>::next_back (216 samples, 0.29%)<core::ptr::non_null::NonNull<T> as core::cmp::PartialEq>::eq (203 samples, 0.27%)<core::str::pattern::MultiCharEqSearcher<C> as core::str::pattern::ReverseSearcher>::next_back (952 samples, 1.26%)<core::str::iter::CharIndices as core::iter::traits::double_ended::DoubleEndedIterator>::next_back (449 samples, 0.59%)<core::str::iter::Chars as core::iter::traits::double_ended::DoubleEndedIterator>::next_back (449 samples, 0.59%)core::str::validations::next_code_point_reverse (449 samples, 0.59%)<core::str::pattern::CharPredicateSearcher<F> as core::str::pattern::ReverseSearcher>::next_reject_back (992 samples, 1.31%)core::str::pattern::ReverseSearcher::next_reject_back (992 samples, 1.31%)core::str::<impl str>::trim_matches (40 samples, 0.05%)<F as core::str::pattern::MultiCharEq>::matches (73 samples, 0.10%)core::str::_<impl str>::trim::_{{closure}} (73 samples, 0.10%)core::char::methods::<impl char>::is_whitespace (73 samples, 0.10%)core::str::<impl str>::trim_matches (33 samples, 0.04%)<core::str::iter::CharIndices as core::iter::traits::iterator::Iterator>::next (244 samples, 0.32%)<core::str::iter::Chars as core::iter::traits::iterator::Iterator>::next (49 samples, 0.06%)core::str::validations::next_code_point (16 samples, 0.02%)<core::str::pattern::MultiCharEqSearcher<C> as core::str::pattern::Searcher>::next (333 samples, 0.44%)<core::str::pattern::CharPredicateSearcher<F> as core::str::pattern::Searcher>::next_reject (571 samples, 0.76%)core::str::pattern::Searcher::next_reject (571 samples, 0.76%)core::str::<impl str>::trim_matches (238 samples, 0.32%)core::str::<impl str>::trim (2,197 samples, 2.91%)co..core::str::<impl str>::trim_matches (2,173 samples, 2.88%)co..core::str::<impl str>::get_unchecked (27 samples, 0.04%)core::str::traits::<impl core::slice::index::SliceIndex<str> for core::ops::range::Range<usize>>::get_unchecked (27 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialEq<&B> for &A>::eq (2,342 samples, 3.10%)cor..core::slice::cmp::<impl core::cmp::PartialEq<[B]> for [A]>::eq (2,342 samples, 3.10%)cor..<[A] as core::slice::cmp::SlicePartialEq<B>>::equal (2,342 samples, 3.10%)<[A..[libc.so.6] (1,184 samples, 1.57%)core::slice::<impl [T]>::get (62 samples, 0.08%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (62 samples, 0.08%)core::num::<impl usize>::repeat_u8 (31 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::align_offset (87 samples, 0.12%)core::ptr::align_offset (87 samples, 0.12%)core::slice::memchr::contains_zero_byte (121 samples, 0.16%)core::num::<impl usize>::wrapping_sub (9 samples, 0.01%)core::slice::memchr::memchr_aligned (1,206 samples, 1.60%)core::slice::memchr::memchr_naive (673 samples, 0.89%)<core::str::pattern::CharSearcher as core::str::pattern::Searcher>::next_match (9,167 samples, 12.14%)<core::str::patter..core::slice::memchr::memchr (4,734 samples, 6.27%)core::sl..core::slice::memchr::memchr_naive (3,246 samples, 4.30%)core:..core::str::iter::SplitInternal<P>::get_end (326 samples, 0.43%)core::str::<impl str>::get_unchecked (40 samples, 0.05%)core::str::traits::<impl core::slice::index::SliceIndex<str> for core::ops::range::Range<usize>>::get_unchecked (40 samples, 0.05%)core::str::iter::SplitInternal<P>::next (14,881 samples, 19.71%)core::str::iter::SplitInternal<..<core::str::iter::Split<P> as core::iter::traits::iterator::Iterator>::next (15,454 samples, 20.46%)<core::str::iter::Split<P> as co..__rdl_alloc (251 samples, 0.33%)__rust_alloc (283 samples, 0.37%)core::ptr::read_volatile (219 samples, 0.29%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (2,479 samples, 3.28%)<al..alloc::alloc::Global::alloc_impl (2,479 samples, 3.28%)all..alloc::alloc::alloc (2,479 samples, 3.28%)all..malloc (1,510 samples, 2.00%)m..alloc::vec::Vec<T,A>::with_capacity_in (2,503 samples, 3.31%)all..alloc::raw_vec::RawVec<T,A>::with_capacity_in (2,503 samples, 3.31%)all..alloc::raw_vec::RawVec<T,A>::allocate_in (2,503 samples, 3.31%)all..core::alloc::layout::Layout::array (13 samples, 0.02%)core::alloc::layout::Layout::array::inner (13 samples, 0.02%)alloc::str::<impl alloc::borrow::ToOwned for str>::to_owned (4,066 samples, 5.38%)alloc::..alloc::slice::<impl alloc::borrow::ToOwned for [T]>::to_owned (4,066 samples, 5.38%)alloc::..alloc::slice::<impl [T]>::to_vec (4,066 samples, 5.38%)alloc::..alloc::slice::<impl [T]>::to_vec_in (4,066 samples, 5.38%)alloc::..alloc::slice::hack::to_vec (4,066 samples, 5.38%)alloc::..<T as alloc::slice::hack::ConvertVec>::to_vec (4,066 samples, 5.38%)<T as a..core::ptr::const_ptr::<impl *const T>::copy_to_nonoverlapping (1,563 samples, 2.07%)c..core::intrinsics::copy_nonoverlapping (1,563 samples, 2.07%)c..[libc.so.6] (1,520 samples, 2.01%)[..core::option::Option<T>::expect (818 samples, 1.08%)core::str::<impl str>::split (772 samples, 1.02%)<f32 as fast_float::float::Float>::from_u64 (28 samples, 0.04%)<f32 as fast_float::float::Float>::pow10_fast_path (19 samples, 0.03%)fast_float::number::Number::try_fast_path (950 samples, 1.26%)fast_float::number::Number::is_fast_path (221 samples, 0.29%)fast_float::common::AsciiStr::check_first (17 samples, 0.02%)fast_float::common::AsciiStr::is_empty (17 samples, 0.02%)fast_float::common::AsciiStr::check_first_either (96 samples, 0.13%)fast_float::common::AsciiStr::is_empty (95 samples, 0.13%)fast_float::common::AsciiStr::first (10 samples, 0.01%)fast_float::number::try_parse_8digits_le (225 samples, 0.30%)fast_float::common::AsciiStr::try_read_u64 (225 samples, 0.30%)fast_float::common::AsciiStr::check_len (199 samples, 0.26%)core::ptr::const_ptr::<impl *const T>::add (115 samples, 0.15%)core::num::<impl u8>::is_ascii_digit (342 samples, 0.45%)fast_float::common::AsciiStr::first (8 samples, 0.01%)fast_float::common::AsciiStr::is_empty (202 samples, 0.27%)fast_float::common::AsciiStr::step (69 samples, 0.09%)fast_float::common::AsciiStr::step_by (69 samples, 0.09%)core::ptr::const_ptr::<impl *const T>::add (69 samples, 0.09%)core::num::<impl u64>::wrapping_add (133 samples, 0.18%)fast_float::parse (8,478 samples, 11.23%)fast_float::parsefast_float::FastFloat::parse_float (8,478 samples, 11.23%)fast_float::FastF..fast_float::FastFloat::parse_float_partial (8,478 samples, 11.23%)fast_float::FastF..fast_float::parse::parse_float (8,478 samples, 11.23%)fast_float::parse..fast_float::number::parse_number (6,341 samples, 8.40%)fast_float::..fast_float::number::try_parse_digits (1,263 samples, 1.67%)fast_float::common::AsciiStr::parse_digits (1,263 samples, 1.67%)fast_float::number::try_parse_digits::_{{closure}} (147 samples, 0.19%)rust_1brc::read_line (29,630 samples, 39.24%)rust_1brc::read_linestd::collections::hash::map::Entry<K,V>::and_modify (600 samples, 0.79%)rust_1brc::calculate_station_values::_{{closure}} (600 samples, 0.79%)__rdl_dealloc (258 samples, 0.34%)__rust_dealloc (255 samples, 0.34%)std::collections::hash::map::Entry<K,V>::or_insert (3,434 samples, 4.55%)std::..std::collections::hash::map::OccupiedEntry<K,V>::into_mut (3,434 samples, 4.55%)std::..hashbrown::rustc_entry::RustcOccupiedEntry<K,V,A>::into_mut (3,434 samples, 4.55%)hashb..core::ptr::drop_in_place<hashbrown::rustc_entry::RustcOccupiedEntry<alloc::string::String,rust_1brc::StationValues>> (3,434 samples, 4.55%)core:..core::ptr::drop_in_place<core::option::Option<alloc::string::String>> (3,434 samples, 4.55%)core:..core::ptr::drop_in_place<alloc::string::String> (3,415 samples, 4.52%)core:..core::ptr::drop_in_place<alloc::vec::Vec<u8>> (3,415 samples, 4.52%)core:..core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (3,415 samples, 4.52%)core:..<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (3,415 samples, 4.52%)<allo..<alloc::alloc::Global as core::alloc::Allocator>::deallocate (3,415 samples, 4.52%)<allo..alloc::alloc::dealloc (3,415 samples, 4.52%)alloc..cfree (2,630 samples, 3.48%)cfr..[libc.so.6] (1,832 samples, 2.43%)[l..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (231 samples, 0.31%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index (231 samples, 0.31%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (231 samples, 0.31%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (231 samples, 0.31%)<usize as core::ops::bit::BitXor>::bitxor (416 samples, 0.55%)core::num::<impl usize>::rotate_left (780 samples, 1.03%)<rustc_hash::FxHasher as core::hash::Hasher>::write (3,773 samples, 5.00%)<rustc..rustc_hash::FxHasher::add_to_hash (2,915 samples, 3.86%)rust..core::num::<impl usize>::wrapping_mul (1,719 samples, 2.28%)c..<usize as core::ops::bit::BitXor>::bitxor (603 samples, 0.80%)<rustc_hash::FxHasher as core::hash::Hasher>::write_u8 (845 samples, 1.12%)rustc_hash::FxHasher::add_to_hash (845 samples, 1.12%)core::num::<impl usize>::wrapping_mul (242 samples, 0.32%)hashbrown::map::make_hash (4,788 samples, 6.34%)hashbrow..core::hash::BuildHasher::hash_one (4,788 samples, 6.34%)core::ha..core::hash::impls::<impl core::hash::Hash for &T>::hash (4,788 samples, 6.34%)core::ha..<alloc::string::String as core::hash::Hash>::hash (4,747 samples, 6.29%)<alloc::..core::hash::impls::<impl core::hash::Hash for str>::hash (4,747 samples, 6.29%)core::ha..core::hash::Hasher::write_str (4,747 samples, 6.29%)core::ha..hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S,A>>::rustc_entry (129 samples, 0.17%)<hashbrown::raw::bitmask::BitMaskIter as core::iter::traits::iterator::Iterator>::next (23 samples, 0.03%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (23 samples, 0.03%)core::num::nonzero::NonZero<u16>::new (22 samples, 0.03%)hashbrown::raw::RawTable<T,A>::bucket (481 samples, 0.64%)hashbrown::raw::Bucket<T>::from_base_index (481 samples, 0.64%)core::ptr::mut_ptr::<impl *mut T>::sub (481 samples, 0.64%)core::ptr::mut_ptr::<impl *mut T>::offset (230 samples, 0.30%)hashbrown::raw::RawTable<T,A>::find::_{{closure}} (8,477 samples, 11.23%)hashbrown::raw::R..hashbrown::rustc_entry::_<impl hashbrown::map::HashMap<K,V,S,A>>::rustc_entry::_{{closure}} (7,996 samples, 10.59%)hashbrown::rust..<alloc::string::String as core::cmp::PartialEq>::eq (7,996 samples, 10.59%)<alloc::string:..alloc::vec::partial_eq::<impl core::cmp::PartialEq<alloc::vec::Vec<U,A2>> for alloc::vec::Vec<T,A1>>::eq (7,996 samples, 10.59%)alloc::vec::par..core::slice::cmp::<impl core::cmp::PartialEq<[B]> for [A]>::eq (7,996 samples, 10.59%)core::slice::cm..<[A] as core::slice::cmp::SlicePartialEq<B>>::equal (7,996 samples, 10.59%)<[A] as core::s..[libc.so.6] (5,089 samples, 6.74%)[libc.so...hashbrown::raw::h2 (2,291 samples, 3.03%)has..hashbrown::raw::sse2::Group::load (234 samples, 0.31%)core::core_arch::x86::sse2::_mm_loadu_si128 (234 samples, 0.31%)hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S,A>>::rustc_entry (234 samples, 0.31%)hashbrown::raw::sse2::Group::match_byte (2,450 samples, 3.24%)has..core::core_arch::x86::sse2::_mm_movemask_epi8 (2,450 samples, 3.24%)cor..hashbrown::raw::sse2::Group::match_empty (100 samples, 0.13%)hashbrown::raw::sse2::Group::match_byte (100 samples, 0.13%)core::core_arch::x86::sse2::_mm_movemask_epi8 (100 samples, 0.13%)hashbrown::raw::RawTableInner::find_inner (15,333 samples, 20.30%)hashbrown::raw::RawTableInner::f..hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S,A>>::rustc_entry (129 samples, 0.17%)hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S,A>>::rustc_entry (21,709 samples, 28.75%)hashbrown::rustc_entry::<impl hashbrown::map::..hashbrown::raw::RawTable<T,A>::find (15,600 samples, 20.66%)hashbrown::raw::RawTable<T,A>::fi..std::collections::hash::map::HashMap<K,V,S>::entry (21,982 samples, 29.11%)std::collections::hash::map::HashMap<K,V,S>::en..<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index (410 samples, 0.54%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (410 samples, 0.54%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index (410 samples, 0.54%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (287 samples, 0.38%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (287 samples, 0.38%)core::ptr::const_ptr::<impl *const T>::add (287 samples, 0.38%)alloc::string::String::len (280 samples, 0.37%)alloc::vec::Vec<T,A>::len (280 samples, 0.37%)core::ptr::drop_in_place<std::io::Guard> (14 samples, 0.02%)<std::io::Guard as core::ops::drop::Drop>::drop (14 samples, 0.02%)alloc::vec::Vec<T,A>::set_len (14 samples, 0.02%)core::result::Result<T,E>::is_err (212 samples, 0.28%)core::result::Result<T,E>::is_ok (212 samples, 0.28%)core::num::<impl usize>::wrapping_sub (21 samples, 0.03%)core::str::converts::from_utf8 (7,108 samples, 9.41%)core::str::co..core::str::validations::run_utf8_validation (4,086 samples, 5.41%)core::s..core::str::validations::utf8_char_width (81 samples, 0.11%)std::io::append_to_string (281 samples, 0.37%)<std::io::buffered::bufreader::BufReader<R> as std::io::BufRead>::consume (412 samples, 0.55%)std::io::buffered::bufreader::buffer::Buffer::consume (412 samples, 0.55%)core::cmp::min (322 samples, 0.43%)core::cmp::Ord::min (322 samples, 0.43%)std::io::append_to_string (322 samples, 0.43%)<std::io::buffered::bufreader::BufReader<R> as std::io::BufRead>::fill_buf (457 samples, 0.61%)std::io::buffered::bufreader::buffer::Buffer::fill_buf (457 samples, 0.61%)std::io::impls::<impl std::io::Read for &mut R>::read_buf (453 samples, 0.60%)<std::fs::File as std::io::Read>::read_buf (453 samples, 0.60%)read (447 samples, 0.59%)[unknown] (446 samples, 0.59%)[unknown] (373 samples, 0.49%)[unknown] (352 samples, 0.47%)[unknown] (348 samples, 0.46%)[unknown] (344 samples, 0.46%)[unknown] (282 samples, 0.37%)[unknown] (240 samples, 0.32%)[unknown] (211 samples, 0.28%)[unknown] (154 samples, 0.20%)[unknown] (119 samples, 0.16%)[unknown] (79 samples, 0.10%)[unknown] (32 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (23 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::reserve (23 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::needs_to_grow (23 samples, 0.03%)alloc::vec::Vec<T,A>::append_elements (1,388 samples, 1.84%)a..core::intrinsics::copy_nonoverlapping (1,326 samples, 1.76%)[libc.so.6] (1,086 samples, 1.44%)alloc::vec::Vec<T,A>::extend_from_slice (1,397 samples, 1.85%)a..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<&T,core::slice::iter::Iter<T>>>::spec_extend (1,397 samples, 1.85%)<..std::io::append_to_string (9 samples, 0.01%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (13 samples, 0.02%)<core::ops::range::RangeToInclusive<usize> as core::slice::index::SliceIndex<[T]>>::index (13 samples, 0.02%)<core::ops::range::RangeInclusive<usize> as core::slice::index::SliceIndex<[T]>>::index (13 samples, 0.02%)[libc.so.6] (75,500 samples, 99.98%)[libc.so.6]main (75,500 samples, 99.98%)mainstd::rt::lang_start_internal (75,500 samples, 99.98%)std::rt::lang_start_internalstd::rt::lang_start::_{{closure}} (75,500 samples, 99.98%)std::rt::lang_start::_{{closure}}std::sys_common::backtrace::__rust_begin_short_backtrace (75,500 samples, 99.98%)std::sys_common::backtrace::__rust_begin_short_backtracecore::ops::function::FnOnce::call_once (75,500 samples, 99.98%)core::ops::function::FnOnce::call_oncerust_1brc::main (75,500 samples, 99.98%)rust_1brc::mainrust_1brc::calculate_station_values (75,500 samples, 99.98%)rust_1brc::calculate_station_valuesstd::io::BufRead::read_line (16,070 samples, 21.28%)std::io::BufRead::read_linestd::io::append_to_string (16,068 samples, 21.28%)std::io::append_to_stringstd::io::BufRead::read_line::_{{closure}} (4,876 samples, 6.46%)std::io:..std::io::read_until (4,595 samples, 6.08%)std::io:..std::sys_common::memchr::memchr (1,953 samples, 2.59%)st..std::sys::pal::unix::memchr::memchr (1,724 samples, 2.28%)s..[libc.so.6] (877 samples, 1.16%)all (75,517 samples, 100%)rust-1brc (75,517 samples, 100.00%)rust-1brc_start (75,501 samples, 99.98%)_start__libc_start_main (75,501 samples, 99.98%)__libc_start_main \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c04149d..d9920f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ struct StationValues { count: u32, } -fn read_line(data: String) -> (String, f32) { +fn read_line(data: &str) -> (String, f32) { let mut parts = data.split(';'); let station_name = parts.next().expect("Failed to parse station name"); let value_str = parts.next().expect("Failed to parse value string"); @@ -35,10 +35,15 @@ fn read_line(data: String) -> (String, f32) { } // Calculate the station values -fn calculate_station_values(data: BufReader) -> FxHashMap { +fn calculate_station_values(reader: &mut BufReader) -> FxHashMap { let mut result: FxHashMap = FxHashMap::default(); - for line in data.lines() { - let line = line.expect("Failed to read line"); + let mut buf = String::new(); + + while let Ok(bytes_read) = reader.read_line(&mut buf) { + if bytes_read == 0 { + break; + } + let line = buf.trim(); let (station_name, value) = read_line(line); result .entry(station_name) @@ -58,6 +63,9 @@ fn calculate_station_values(data: BufReader) -> FxHashMap