You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by do...@apache.org on 2022/04/06 13:27:02 UTC

[arrow] branch master updated: ARROW-16117: [JS] Improve decode UTF8 performance

This is an automated email from the ASF dual-hosted git repository.

domoritz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new adfa60504b ARROW-16117: [JS] Improve decode UTF8 performance
adfa60504b is described below

commit adfa60504b7521c26bb0c53732b12a7e1aa180c7
Author: hzuo <so...@gmail.com>
AuthorDate: Wed Apr 6 09:26:54 2022 -0400

    ARROW-16117: [JS] Improve decode UTF8 performance
    
    (See comment below for benchmarks)
    
    While profiling the performance of decoding TPC-H Customer and Part in-browser, datasets where there are a lot of UTF8s, it turned out that much of the time was being spent in `getVariableWidthBytes` rather than in `TextDecoder` itself. Ideally all the time should be spent in `TextDecoder`.
    
    On Chrome `getVariableWidthBytes` took up to ~15% of the e2e decoding latency, and on Safari it was close to ~40% (Safari's TextDecoder is much faster than Chrome's, so this took up relatively more time).
    
    This is likely because the code in this PR is more amenable to V8/JSC's JIT, since `x` and `y` now are guaranteed to be SMIs ("small integers") instead of Object, allowing the JIT to emit efficient machine instructions that only deal in 32-bit integers. Once V8 discovers that a `x` and `y` can potentially be null (upon iterating past the bounds), it "poisons" the codepath forever, since it has to deal with the null case.
    
    See this V8 post for a more in-depth explanation (in particular see the examples underneath "Performance tips"):
    https://v8.dev/blog/elements-kinds
    
    Doing the bounds check explicitly instead of implicitly basically eliminates this function from showing up in the profiling. Empirically, on my machine decoding TPC-H Part dropped from 1.9s to 1.7s on Chrome, and Customer dropped from 1.4s to 1.2s.
    
    Closes #12793 from hzuo/hz/dp
    
    Authored-by: hzuo <so...@gmail.com>
    Signed-off-by: Dominik Moritz <do...@gmail.com>
---
 js/src/visitor/get.ts | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/js/src/visitor/get.ts b/js/src/visitor/get.ts
index 1012a884d8..1fd946fd94 100644
--- a/js/src/visitor/get.ts
+++ b/js/src/visitor/get.ts
@@ -109,8 +109,12 @@ function wrapGet<T extends DataType>(fn: (data: Data<T>, _1: any) => any) {
 const getNull = <T extends Null>(_data: Data<T>, _index: number): T['TValue'] => null;
 /** @ignore */
 const getVariableWidthBytes = (values: Uint8Array, valueOffsets: Int32Array, index: number) => {
-    const { [index]: x, [index + 1]: y } = valueOffsets;
-    return x != null && y != null ? values.subarray(x, y) : null as any;
+    if (index + 1 >= valueOffsets.length) {
+        return null as any;
+    }
+    const x = valueOffsets[index];
+    const y = valueOffsets[index + 1];
+    return values.subarray(x, y);
 };
 
 /** @ignore */