diff --git a/Cargo.toml b/Cargo.toml index d8bafb180e45c..3c74b37602d5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -573,7 +573,7 @@ incremental = true [profile.ci] inherits = "release" -overflow-checks = false +overflow-checks = true incremental = false debug-assertions = true @@ -583,7 +583,7 @@ debug-assertions = true [profile.dev] split-debuginfo = "unpacked" -overflow-checks = false +overflow-checks = true # Report to https://github.com/rust-lang/rust/issues/100142 if incremental works well incremental = true diff --git a/src/common/column/src/buffer/iterator.rs b/src/common/column/src/buffer/iterator.rs index 91b4d351b5d5e..5771de1ec7d3f 100644 --- a/src/common/column/src/buffer/iterator.rs +++ b/src/common/column/src/buffer/iterator.rs @@ -20,20 +20,20 @@ use super::Buffer; /// This crates' equivalent of [`std::vec::IntoIter`] for [`Buffer`]. #[derive(Debug, Clone)] pub struct IntoIter { - values: Buffer, - index: usize, - end: usize, + buffer: Buffer, + current: *const T, + end: *const T, } impl IntoIter { - /// Creates a new [`Buffer`] #[inline] - pub fn new(values: Buffer) -> Self { - let end = values.len(); + pub fn new(buffer: Buffer) -> Self { + let ptr = buffer.as_ptr(); + let len = buffer.len(); Self { - values, - index: 0, - end, + current: ptr, + end: unsafe { ptr.add(len) }, + buffer, } } } @@ -43,40 +43,30 @@ impl Iterator for IntoIter { #[inline] fn next(&mut self) -> Option { - if self.index == self.end { - return None; + if self.current == self.end { + None + } else { + let value = unsafe { *self.current }; + self.current = unsafe { self.current.add(1) }; + Some(value) } - let old = self.index; - self.index += 1; - Some(*unsafe { self.values.get_unchecked(old) }) } #[inline] fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } - - #[inline] - fn nth(&mut self, n: usize) -> Option { - let new_index = self.index + n; - if new_index > self.end { - self.index = self.end; - None - } else { - self.index = new_index; - self.next() - } + let len = unsafe { self.end.offset_from(self.current) } as usize; + (len, Some(len)) } } impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { - if self.index == self.end { + if self.current == self.end { None } else { - self.end -= 1; - Some(*unsafe { self.values.get_unchecked(self.end) }) + self.end = unsafe { self.end.sub(1) }; + Some(unsafe { *self.end }) } } } diff --git a/src/query/expression/benches/bench.rs b/src/query/expression/benches/bench.rs index b0e18083fc801..8ff91219fa5c5 100644 --- a/src/query/expression/benches/bench.rs +++ b/src/query/expression/benches/bench.rs @@ -16,6 +16,7 @@ extern crate criterion; use criterion::Criterion; +use databend_common_column::buffer::Buffer; use databend_common_expression::arrow::deserialize_column; use databend_common_expression::arrow::serialize_column; use databend_common_expression::types::BinaryType; @@ -130,6 +131,81 @@ fn bench(c: &mut Criterion) { }); } } + + for length in [10240, 102400] { + let (left, right) = generate_random_int_data(&mut rng, length); + + group.bench_function(format!("function_iterator_iterator_v1/{length}"), |b| { + b.iter(|| { + let left = left.clone(); + let right = right.clone(); + + let _c = left + .into_iter() + .zip(right.into_iter()) + .map(|(a, b)| a + b) + .collect::>(); + }) + }); + + group.bench_function(format!("function_iterator_iterator_v2/{length}"), |b| { + b.iter(|| { + let _c = left + .iter() + .cloned() + .zip(right.iter().cloned()) + .map(|(a, b)| a + b) + .collect::>(); + }) + }); + + group.bench_function( + format!("function_buffer_index_unchecked_iterator/{length}"), + |b| { + b.iter(|| { + let _c = (0..length) + .map(|i| unsafe { left.get_unchecked(i) + right.get_unchecked(i) }) + .collect::>(); + }) + }, + ); + + group.bench_function( + format!("function_slice_index_unchecked_iterator/{length}"), + |b| { + b.iter(|| { + let left = left.as_slice(); + let right = right.as_slice(); + + let _c = (0..length) + .map(|i| unsafe { left.get_unchecked(i) + right.get_unchecked(i) }) + .collect::>(); + }) + }, + ); + + let left_vec: Vec<_> = left.iter().cloned().collect(); + let right_vec: Vec<_> = right.iter().cloned().collect(); + + group.bench_function( + format!("function_vec_index_unchecked_iterator/{length}"), + |b| { + b.iter(|| { + let _c = (0..length) + .map(|i| unsafe { left_vec.get_unchecked(i) + right_vec.get_unchecked(i) }) + .collect::>(); + }) + }, + ); + + group.bench_function(format!("function_buffer_index_iterator/{length}"), |b| { + b.iter(|| { + let _c = (0..length) + .map(|i| left[i] + right[i]) + .collect::>(); + }) + }); + } } criterion_group!(benches, bench); @@ -155,3 +231,9 @@ fn generate_random_string_data(rng: &mut StdRng, length: usize) -> (Vec, (iter_str, iter_binary) } + +fn generate_random_int_data(rng: &mut StdRng, length: usize) -> (Buffer, Buffer) { + let s: Buffer = (0..length).map(|_| rng.gen_range(-1000..1000)).collect(); + let b: Buffer = (0..length).map(|_| rng.gen_range(-1000..1000)).collect(); + (s, b) +} diff --git a/src/query/expression/src/filter/like.rs b/src/query/expression/src/filter/like.rs index de5a0ba9d17e0..0de572a947cc7 100644 --- a/src/query/expression/src/filter/like.rs +++ b/src/query/expression/src/filter/like.rs @@ -304,13 +304,13 @@ fn find(mut haystack: &[u8], needle: &[u8]) -> Option { return None; } // Inspired by fast_strstr (https://github.com/RaphaelJ/fast_strstr). - let mut checksum = 0; + let mut checksum: i64 = 0; for i in 0..needle_len { // # Safety // `needle_len` <= haystack_len unsafe { - checksum += haystack.get_unchecked(i); - checksum -= needle.get_unchecked(i); + checksum += *haystack.get_unchecked(i) as i64; + checksum -= *needle.get_unchecked(i) as i64; } } let mut idx = 0; @@ -331,8 +331,8 @@ fn find(mut haystack: &[u8], needle: &[u8]) -> Option { // # Safety // `idx` < `haystack_len` and `idx` + `needle_len` < `haystack_len`. unsafe { - checksum -= haystack.get_unchecked(idx); - checksum += haystack.get_unchecked(idx + needle_len); + checksum -= *haystack.get_unchecked(idx) as i64; + checksum += *haystack.get_unchecked(idx + needle_len) as i64; } idx += 1; } diff --git a/src/query/expression/src/utils/block_debug.rs b/src/query/expression/src/utils/block_debug.rs index 05f877215ea5c..d6ffa2191cdc4 100644 --- a/src/query/expression/src/utils/block_debug.rs +++ b/src/query/expression/src/utils/block_debug.rs @@ -186,7 +186,7 @@ fn create_box_table( let row_count: usize = results.iter().map(|block| block.num_rows()).sum(); let mut rows_to_render = row_count.min(max_rows); - if row_count <= max_rows + 3 { + if row_count <= max_rows.saturating_add(3) { // hiding rows adds 3 extra rows // so hiding rows makes no sense if we are only slightly over the limit // if we are 1 row over the limit hiding rows will actually increase the number of lines we display! @@ -228,7 +228,7 @@ fn create_box_table( // "..." take up three lengths if max_width > 0 { (widths, column_map) = - compute_render_widths(schema, max_width, max_col_width + 3, &res_vec); + compute_render_widths(schema, max_width, max_col_width.saturating_add(3), &res_vec); } let mut header = Vec::with_capacity(schema.fields().len()); @@ -355,7 +355,7 @@ fn compute_render_widths( for field in schema.fields() { // head_name = field_name + "\n" + field_data_type let col_length = field.name().len().max(field.data_type().to_string().len()); - widths.push(col_length + 3); + widths.push(col_length.saturating_add(3)); } for values in results { diff --git a/src/query/service/src/sessions/session_ctx.rs b/src/query/service/src/sessions/session_ctx.rs index 0a0e03b6d4fc2..f79f5c5c076ec 100644 --- a/src/query/service/src/sessions/session_ctx.rs +++ b/src/query/service/src/sessions/session_ctx.rs @@ -297,7 +297,7 @@ impl SessionContext { index }; - if idx < 0 || idx > (query_ids_len - 1) as i32 { + if query_ids_len < 1 || idx < 0 || idx > (query_ids_len - 1) as i32 { return "".to_string(); } diff --git a/src/query/service/src/sessions/session_mgr_status.rs b/src/query/service/src/sessions/session_mgr_status.rs index 69e43bea1afa4..2db67041972af 100644 --- a/src/query/service/src/sessions/session_mgr_status.rs +++ b/src/query/service/src/sessions/session_mgr_status.rs @@ -31,7 +31,7 @@ impl SessionManagerStatus { } pub(crate) fn query_finish(&mut self, now: SystemTime) { - self.running_queries_count -= 1; + self.running_queries_count = self.running_queries_count.saturating_sub(1); if self.running_queries_count == 0 { self.last_query_finished_at = Some(now) } diff --git a/tests/suites/1_stateful/02_query/02_0000_kill_query.py b/tests/suites/1_stateful/02_query/02_0000_kill_query.py index 590a8821f1ccd..d538411d4662b 100755 --- a/tests/suites/1_stateful/02_query/02_0000_kill_query.py +++ b/tests/suites/1_stateful/02_query/02_0000_kill_query.py @@ -37,7 +37,7 @@ res = mycursor.fetchone() kill_query = "kill query " + str(res[0]) + ";" mycursor.execute(kill_query) - time.sleep(1) + time.sleep(10) mycursor.execute( "SELECT * FROM system.processes WHERE extra_info LIKE '%SELECT max(number)%' AND extra_info NOT LIKE '%system.processes%';" )