You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "tustvold (via GitHub)" <gi...@apache.org> on 2023/03/03 19:10:23 UTC

[GitHub] [arrow-rs] tustvold opened a new pull request, #3801: Faster timezone parsing

tustvold opened a new pull request, #3801:
URL: https://github.com/apache/arrow-rs/pull/3801

   _Draft as builds on #3795_
   
   # Which issue does this PR close?
   
   <!--
   We generally require a GitHub issue to be filed for all bug fixes and enhancements and this helps us generate change logs for our releases. You can link an issue to this PR using the GitHub syntax. For example `Closes #123` indicates that this PR will close issue #123.
   -->
   
   Closes #.
   
   # Rationale for this change
    
   <!--
   Why are you proposing this change? If this is already explained clearly in the issue then this section is not needed.
   Explaining clearly why changes are proposed helps reviewers understand your changes and offer better suggestions for fixes.
   -->
   
   ```
   2020-09-08              time:   [27.715 ns 27.737 ns 27.761 ns]
                           change: [-96.582% -96.578% -96.573%] (p = 0.00 < 0.05)
                           Performance has improved.
   Found 1 outliers among 100 measurements (1.00%)
     1 (1.00%) high mild
   
   2020-09-08T13:42:29     time:   [39.525 ns 39.567 ns 39.610 ns]
                           change: [-93.047% -93.038% -93.030%] (p = 0.00 < 0.05)
                           Performance has improved.
   Found 1 outliers among 100 measurements (1.00%)
     1 (1.00%) high severe
   
   2020-09-08T13:42:29.190 time:   [43.056 ns 43.113 ns 43.182 ns]
                           change: [-92.520% -92.509% -92.497%] (p = 0.00 < 0.05)
                           Performance has improved.
   Found 1 outliers among 100 measurements (1.00%)
     1 (1.00%) high severe
   
   2020-09-08T13:42:29.190855
                           time:   [44.744 ns 44.805 ns 44.868 ns]
                           change: [-91.874% -91.860% -91.845%] (p = 0.00 < 0.05)
                           Performance has improved.
   Found 6 outliers among 100 measurements (6.00%)
     6 (6.00%) high mild
   
   2020-09-08T13:42:29.190855999
                           time:   [47.342 ns 47.397 ns 47.452 ns]
                           change: [-91.871% -91.860% -91.850%] (p = 0.00 < 0.05)
                           Performance has improved.
   
   2020-09-08T13:42:29+00:00
                           time:   [85.719 ns 85.824 ns 85.928 ns]
                           change: [+0.1636% +0.3298% +0.4943%] (p = 0.00 < 0.05)
                           Change within noise threshold.
   Found 1 outliers among 100 measurements (1.00%)
     1 (1.00%) high mild
   
   2020-09-08T13:42:29.190+00:00
                           time:   [88.597 ns 88.750 ns 88.906 ns]
                           change: [-0.9943% -0.7222% -0.4813%] (p = 0.00 < 0.05)
                           Change within noise threshold.
   Found 2 outliers among 100 measurements (2.00%)
     2 (2.00%) high mild
   
   2020-09-08T13:42:29.190855+00:00
                           time:   [96.412 ns 96.517 ns 96.626 ns]
                           change: [+6.3387% +6.5146% +6.6933%] (p = 0.00 < 0.05)
                           Performance has regressed.
   Found 5 outliers among 100 measurements (5.00%)
     2 (2.00%) low mild
     2 (2.00%) high mild
     1 (1.00%) high severe
   
   2020-09-08T13:42:29.190855999-05:00
                           time:   [94.288 ns 94.420 ns 94.595 ns]
                           change: [+2.5598% +2.9406% +3.2234%] (p = 0.00 < 0.05)
                           Performance has regressed.
   Found 5 outliers among 100 measurements (5.00%)
     4 (4.00%) high mild
     1 (1.00%) high severe
   
   2020-09-08T13:42:29.190855Z
                           time:   [25.864 ns 25.938 ns 26.013 ns]
                           change: [-70.863% -70.775% -70.687%] (p = 0.00 < 0.05)
                           Performance has improved.
   Found 1 outliers among 100 measurements (1.00%)
     1 (1.00%) high mild
   ```
   
   # What changes are included in this PR?
   
   <!--
   There is no need to duplicate the description in the issue here but it is sometimes worth providing a summary of the individual changes in this PR.
   -->
   
   # Are there any user-facing changes?
   
   
   <!--
   If there are user-facing changes then we may require documentation to be updated before approving the PR.
   -->
   
   <!---
   If there are any breaking changes to public APIs, please add the `breaking change` label.
   -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] jhorstmann commented on pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "jhorstmann (via GitHub)" <gi...@apache.org>.
jhorstmann commented on PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#issuecomment-1460630141

   Impressive results!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129936448


##########
arrow-array/src/timezone.rs:
##########
@@ -18,29 +18,34 @@
 //! Timezone for timestamp arrays
 
 use arrow_schema::ArrowError;
-use chrono::format::{parse, Parsed, StrftimeItems};
 use chrono::FixedOffset;
 pub use private::{Tz, TzOffset};
 
-/// Parses a fixed offset of the form "+09:00"
-fn parse_fixed_offset(tz: &str) -> Result<FixedOffset, ArrowError> {
-    let mut parsed = Parsed::new();
-
-    if let Ok(fixed_offset) = parse(&mut parsed, tz, StrftimeItems::new("%:z"))
-        .and_then(|_| parsed.to_fixed_offset())
-    {
-        return Ok(fixed_offset);
+/// Parses a fixed offset of the form "+09:00", "-09" or "+0930"
+fn parse_fixed_offset(tz: &str) -> Option<FixedOffset> {
+    let bytes = tz.as_bytes();
+
+    let mut values = match bytes.len() {
+        // [+-]XX:XX
+        6 if bytes[3] == b':' => [bytes[1], bytes[2], bytes[4], bytes[5]],
+        // [+-]XXXX
+        5 => [bytes[1], bytes[2], bytes[3], bytes[4]],
+        // [+-]XX
+        3 => [bytes[1], bytes[2], b'0', b'0'],
+        _ => return None,
+    };
+    values.iter_mut().for_each(|x| *x = x.wrapping_sub(b'0'));

Review Comment:
   Wrapping sub will just underflow harmlessly for such values, which will then fail on the check for `< 9`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1130816225


##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,
+}
+
+impl TimestampParser {
+    fn new(bytes: &[u8]) -> Self {
+        let mut digits = [0; 32];
+        let mut mask = 0;
+
+        for (idx, (o, i)) in digits.iter_mut().zip(bytes).enumerate() {
+            *o = i.wrapping_sub(b'0');
+            mask |= ((*o < 10) as u32) << idx
+        }
+
+        Self { digits, mask }
+    }
+
+    /// Returns true if the byte at `idx` equals `b`

Review Comment:
   This is not correct, will update the docs



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129934411


##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,
+}
+
+impl TimestampParser {
+    fn new(bytes: &[u8]) -> Self {
+        let mut digits = [0; 32];
+        let mut mask = 0;
+
+        for (idx, (o, i)) in digits.iter_mut().zip(bytes).enumerate() {

Review Comment:
   Yeah, LLVM does vectorise it automatically, not especially well, but it does sort of



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] jhorstmann commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "jhorstmann (via GitHub)" <gi...@apache.org>.
jhorstmann commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129875692


##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,
+}
+
+impl TimestampParser {
+    fn new(bytes: &[u8]) -> Self {
+        let mut digits = [0; 32];
+        let mut mask = 0;
+
+        for (idx, (o, i)) in digits.iter_mut().zip(bytes).enumerate() {

Review Comment:
   fun fact, this would a a handful of instructions without any loops with avx512. unfortunately still requires nightly, and we should probably find a general answer to target-specific optimizations first, instead of sprinkling intrinsics all over the place. In case you want to benchmark it, the code would look like
   
   ```rust
               use std::arch::x86_64::*;
               unsafe {
                   let load_mask = u32::MAX >> 32_usize.saturating_sub(bytes.len());
                   let v = _mm256_maskz_loadu_epi8(load_mask, bytes.as_ptr().cast());
                   let d = _mm256_sub_epi8(v, _mm256_set1_epi8(b'0' as _));
                   _mm256_storeu_si256(digits.as_mut_ptr().cast(), d);
                   mask = _mm256_cmplt_epu8_mask(d, _mm256_set1_epi8(10));
               }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129934411


##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,
+}
+
+impl TimestampParser {
+    fn new(bytes: &[u8]) -> Self {
+        let mut digits = [0; 32];
+        let mut mask = 0;
+
+        for (idx, (o, i)) in digits.iter_mut().zip(bytes).enumerate() {

Review Comment:
   Yeah, LLVM does vectorise it automatically, not especially well, but it does sort of. This was not accidental :smile: 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] doki23 commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "doki23 (via GitHub)" <gi...@apache.org>.
doki23 commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1130411077


##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,
+}
+
+impl TimestampParser {
+    fn new(bytes: &[u8]) -> Self {
+        let mut digits = [0; 32];
+        let mut mask = 0;
+
+        for (idx, (o, i)) in digits.iter_mut().zip(bytes).enumerate() {
+            *o = i.wrapping_sub(b'0');
+            mask |= ((*o < 10) as u32) << idx
+        }
+
+        Self { digits, mask }
+    }
+
+    /// Returns true if the byte at `idx` equals `b`
+    fn test(&self, idx: usize, b: u8) -> bool {
+        self.digits[idx] == b.wrapping_sub(b'0')
+    }
+
+    /// Parses a date of the form `1997-01-31`
+    fn date(&self) -> Option<NaiveDate> {
+        if self.mask & 0b1111111111 != 0b1101101111
+            || !self.test(4, b'-')
+            || !self.test(7, b'-')
+        {
+            return None;
+        }
+
+        let year = self.digits[0] as u16 * 1000
+            + self.digits[1] as u16 * 100
+            + self.digits[2] as u16 * 10
+            + self.digits[3] as u16;
+
+        let month = self.digits[5] * 10 + self.digits[6];
+        let day = self.digits[8] * 10 + self.digits[9];
+
+        NaiveDate::from_ymd_opt(year as _, month as _, day as _)
+    }
+
+    /// Parses a time of any of forms
+    /// - `09:26:56`
+    /// - `09:26:56.123`
+    /// - `09:26:56.123456`
+    /// - `09:26:56.123456789`
+    /// - `092656`
+    ///
+    /// Returning the end byte offset
+    fn time(&self) -> Option<(NaiveTime, usize)> {
+        match (self.mask >> 11) & 0b11111111 {
+            // 09:26:56
+            0b11011011 if self.test(13, b':') && self.test(16, b':') => {
+                let hour = self.digits[11] * 10 + self.digits[12];
+                let minute = self.digits[14] * 10 + self.digits[15];
+                let second = self.digits[17] * 10 + self.digits[18];
+                let time = NaiveTime::from_hms_opt(hour as _, minute as _, second as _)?;
+
+                let millis = || {
+                    self.digits[20] as u32 * 100_000_000
+                        + self.digits[21] as u32 * 10_000_000
+                        + self.digits[22] as u32 * 1_000_000
+                };
+
+                let micros = || {
+                    self.digits[23] as u32 * 100_000
+                        + self.digits[24] as u32 * 10_000
+                        + self.digits[25] as u32 * 1_000
+                };
+
+                let nanos = || {
+                    self.digits[26] as u32 * 100
+                        + self.digits[27] as u32 * 10
+                        + self.digits[28] as u32
+                };
+
+                match self.test(19, b'.') {
+                    true => match (self.mask >> 20).trailing_ones() {
+                        3 => Some((time.with_nanosecond(millis())?, 23)),
+                        6 => Some((time.with_nanosecond(millis() + micros())?, 26)),
+                        9 => Some((
+                            time.with_nanosecond(millis() + micros() + nanos())?,
+                            29,
+                        )),
+                        _ => None,
+                    },
+                    false => Some((time, 19)),
+                }
+            }
+            // 09:26:56

Review Comment:
   a typo -- should be `// 092656`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold merged pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold merged PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129936448


##########
arrow-array/src/timezone.rs:
##########
@@ -18,29 +18,34 @@
 //! Timezone for timestamp arrays
 
 use arrow_schema::ArrowError;
-use chrono::format::{parse, Parsed, StrftimeItems};
 use chrono::FixedOffset;
 pub use private::{Tz, TzOffset};
 
-/// Parses a fixed offset of the form "+09:00"
-fn parse_fixed_offset(tz: &str) -> Result<FixedOffset, ArrowError> {
-    let mut parsed = Parsed::new();
-
-    if let Ok(fixed_offset) = parse(&mut parsed, tz, StrftimeItems::new("%:z"))
-        .and_then(|_| parsed.to_fixed_offset())
-    {
-        return Ok(fixed_offset);
+/// Parses a fixed offset of the form "+09:00", "-09" or "+0930"
+fn parse_fixed_offset(tz: &str) -> Option<FixedOffset> {
+    let bytes = tz.as_bytes();
+
+    let mut values = match bytes.len() {
+        // [+-]XX:XX
+        6 if bytes[3] == b':' => [bytes[1], bytes[2], bytes[4], bytes[5]],
+        // [+-]XXXX
+        5 => [bytes[1], bytes[2], bytes[3], bytes[4]],
+        // [+-]XX
+        3 => [bytes[1], bytes[2], b'0', b'0'],
+        _ => return None,
+    };
+    values.iter_mut().for_each(|x| *x = x.wrapping_sub(b'0'));

Review Comment:
   Wrapping sub will just underflow harmlessly for such values



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129936448


##########
arrow-array/src/timezone.rs:
##########
@@ -18,29 +18,34 @@
 //! Timezone for timestamp arrays
 
 use arrow_schema::ArrowError;
-use chrono::format::{parse, Parsed, StrftimeItems};
 use chrono::FixedOffset;
 pub use private::{Tz, TzOffset};
 
-/// Parses a fixed offset of the form "+09:00"
-fn parse_fixed_offset(tz: &str) -> Result<FixedOffset, ArrowError> {
-    let mut parsed = Parsed::new();
-
-    if let Ok(fixed_offset) = parse(&mut parsed, tz, StrftimeItems::new("%:z"))
-        .and_then(|_| parsed.to_fixed_offset())
-    {
-        return Ok(fixed_offset);
+/// Parses a fixed offset of the form "+09:00", "-09" or "+0930"
+fn parse_fixed_offset(tz: &str) -> Option<FixedOffset> {
+    let bytes = tz.as_bytes();
+
+    let mut values = match bytes.len() {
+        // [+-]XX:XX
+        6 if bytes[3] == b':' => [bytes[1], bytes[2], bytes[4], bytes[5]],
+        // [+-]XXXX
+        5 => [bytes[1], bytes[2], bytes[3], bytes[4]],
+        // [+-]XX
+        3 => [bytes[1], bytes[2], b'0', b'0'],
+        _ => return None,
+    };
+    values.iter_mut().for_each(|x| *x = x.wrapping_sub(b'0'));

Review Comment:
   Wrapping sub will just underflow harmlessly



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] alamb commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "alamb (via GitHub)" <gi...@apache.org>.
alamb commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129867567


##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,
+}
+
+impl TimestampParser {
+    fn new(bytes: &[u8]) -> Self {
+        let mut digits = [0; 32];
+        let mut mask = 0;
+
+        for (idx, (o, i)) in digits.iter_mut().zip(bytes).enumerate() {
+            *o = i.wrapping_sub(b'0');
+            mask |= ((*o < 10) as u32) << idx
+        }
+
+        Self { digits, mask }
+    }
+
+    /// Returns true if the byte at `idx` equals `b`

Review Comment:
   ```suggestion
       /// Returns true if the byte at `idx` represents the ASCII character with the numeric value of `b`. 
       /// This is intended to quickly check for numerals like `'0'`, `'1'`, `'2'`, etc
       ///
       /// given "12foo"
       /// test(0, 1) -> true
       /// test(0, 2) -> false
       /// test(4, 0) -> false
   ```



##########
arrow-cast/src/parse.rs:
##########
@@ -15,11 +15,117 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use arrow_array::timezone::Tz;
 use arrow_array::types::*;
 use arrow_array::ArrowPrimitiveType;
 use arrow_schema::ArrowError;
 use chrono::prelude::*;
 
+/// Helper for parsing timestamps
+struct TimestampParser {
+    digits: [u8; 32],
+    mask: u32,

Review Comment:
   Can we please document what mask represents? I think it is a bitmask of digits ?



##########
arrow-cast/src/parse.rs:
##########
@@ -565,11 +637,11 @@ mod tests {
         // Test parsing invalid formats
 
         // It would be nice to make these messages better
-        expect_timestamp_parse_error("", "Error parsing '' as timestamp");
-        expect_timestamp_parse_error("SS", "Error parsing 'SS' as timestamp");
+        expect_timestamp_parse_error("", "Error parsing timestamp from '': timestamp must contain at least 10 characters");

Review Comment:
   Can we also add some tests for invalid timestamps
   
   Cases:
   1.   timzone with bad characters `00: 4` (aka put a space in there),
   2.  timezones without `:`, such as `+00`
   3. extra content after the timestamp
   
   Perhaps the explictly stated unsupported formats:
   ```
   ///     "2023-01-01 040506 America/Los_Angeles",
   ///     "2023-01-01 04:05:06.789 +07:30:00",
   ///     "2023-01-01 040506 +07:30:00",
   ///     "2023-01-01 04:05:06.789 PST",
   ///     "2023-01-01 04:05:06.789 -08",
   ```
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] alamb commented on a diff in pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "alamb (via GitHub)" <gi...@apache.org>.
alamb commented on code in PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#discussion_r1129861219


##########
arrow-array/src/timezone.rs:
##########
@@ -18,29 +18,34 @@
 //! Timezone for timestamp arrays
 
 use arrow_schema::ArrowError;
-use chrono::format::{parse, Parsed, StrftimeItems};
 use chrono::FixedOffset;
 pub use private::{Tz, TzOffset};
 
-/// Parses a fixed offset of the form "+09:00"
-fn parse_fixed_offset(tz: &str) -> Result<FixedOffset, ArrowError> {
-    let mut parsed = Parsed::new();
-
-    if let Ok(fixed_offset) = parse(&mut parsed, tz, StrftimeItems::new("%:z"))
-        .and_then(|_| parsed.to_fixed_offset())
-    {
-        return Ok(fixed_offset);
+/// Parses a fixed offset of the form "+09:00", "-09" or "+0930"
+fn parse_fixed_offset(tz: &str) -> Option<FixedOffset> {
+    let bytes = tz.as_bytes();
+
+    let mut values = match bytes.len() {
+        // [+-]XX:XX
+        6 if bytes[3] == b':' => [bytes[1], bytes[2], bytes[4], bytes[5]],
+        // [+-]XXXX
+        5 => [bytes[1], bytes[2], bytes[3], bytes[4]],
+        // [+-]XX
+        3 => [bytes[1], bytes[2], b'0', b'0'],
+        _ => return None,
+    };
+    values.iter_mut().for_each(|x| *x = x.wrapping_sub(b'0'));

Review Comment:
   this converts the ascii to the numeric representation, right? I am thinking that the use of wrapping sub ensures that any values like ` ` (20) that is lower than `'0'` will not pass this check, is that correct?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] tustvold commented on pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "tustvold (via GitHub)" <gi...@apache.org>.
tustvold commented on PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#issuecomment-1461806364

   I've added some more tests, PTAL, including the chrono test cases I could find... They aren't actually all that extensive... - https://github.com/chronotope/chrono/blob/main/src/format/parse.rs#L932


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [arrow-rs] ursabot commented on pull request #3801: Faster timestamp parsing (~70-90% faster)

Posted by "ursabot (via GitHub)" <gi...@apache.org>.
ursabot commented on PR #3801:
URL: https://github.com/apache/arrow-rs/pull/3801#issuecomment-1462308440

   Benchmark runs are scheduled for baseline = de9f82693f94721916e37f4896e9394411d8076f and contender = cdb042ed02a6c9afd0cf3f6f86072b09c599f59a. cdb042ed02a6c9afd0cf3f6f86072b09c599f59a is a master commit associated with this PR. Results will be available as each benchmark for each run completes.
   Conbench compare runs links:
   [Skipped :warning: Benchmarking of arrow-rs-commits is not supported on ec2-t3-xlarge-us-east-2] [ec2-t3-xlarge-us-east-2](https://conbench.ursa.dev/compare/runs/cc52ac54ad0543b48870aaebbd4fe88c...c4677d8b1cfb45daa14ce8e2d0bbd639/)
   [Skipped :warning: Benchmarking of arrow-rs-commits is not supported on test-mac-arm] [test-mac-arm](https://conbench.ursa.dev/compare/runs/de5409f2ea244d0486a2c5d6fd164dc5...5a947e9f01d54d8091e7211426dda9e9/)
   [Skipped :warning: Benchmarking of arrow-rs-commits is not supported on ursa-i9-9960x] [ursa-i9-9960x](https://conbench.ursa.dev/compare/runs/1fa4950bac264f0ba575d208fdec0780...3978447b80a24d2eacb944865e1b36b5/)
   [Skipped :warning: Benchmarking of arrow-rs-commits is not supported on ursa-thinkcentre-m75q] [ursa-thinkcentre-m75q](https://conbench.ursa.dev/compare/runs/a8148e4cb80046758e80ad7c9fe1546a...8f3e575d3d194dd09e28413c7ab48501/)
   Buildkite builds:
   Supported benchmarks:
   ec2-t3-xlarge-us-east-2: Supported benchmark langs: Python, R. Runs only benchmarks with cloud = True
   test-mac-arm: Supported benchmark langs: C++, Python, R
   ursa-i9-9960x: Supported benchmark langs: Python, R, JavaScript
   ursa-thinkcentre-m75q: Supported benchmark langs: C++, Java
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org