You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2019/03/19 03:28:15 UTC

[impala] 02/03: IMPALA-5393. Use THREAD_LOCAL state for regexp

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

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

commit 6e8c330f40da087ca0d8ba844cd9d97a8e60ff67
Author: Todd Lipcon <to...@apache.org>
AuthorDate: Fri Mar 15 22:58:51 2019 -0700

    IMPALA-5393. Use THREAD_LOCAL state for regexp
    
    This changes the built-in regexp-related UDFs to use THREAD_LOCAL
    re2::RE instances instead of FRAGMENT_LOCAL.
    
    Although re2::RE is thread-safe, it achieves that thread safety through
    a certain amount of locking. Using thread-local regexps improves
    performance substantially.
    
    I ran a simple test query:
    
    select sum(l_linenumber) from item_20x where length(regexp_extract(l_shipinstruct, '.*', 0)) > 0
    
    on a table with three underlying parquet files (thus getting 3 scanner
    threads). Prior to this change, the query took ~60 seconds and burned
    2m16sec CPU time. With this change, it took ~19sec and 43s CPU time. For
    a query with more scanner threads, the improvement should be even more
    dramatic.
    
    The only potential downside of this change is slightly increased memory
    consumption by having one RE instance per thread, but the REs themselves
    should be small relative to all of the other per-scanner-thread memory.
    
    Change-Id: Ibc331151a302e755701cb08adb3e6f289d54c3a6
    Reviewed-on: http://gerrit.cloudera.org:8080/12772
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
    Reviewed-by: Todd Lipcon <to...@apache.org>
---
 be/src/exprs/string-functions-ir.cc | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/be/src/exprs/string-functions-ir.cc b/be/src/exprs/string-functions-ir.cc
index a4d4962..67b7ce1 100644
--- a/be/src/exprs/string-functions-ir.cc
+++ b/be/src/exprs/string-functions-ir.cc
@@ -664,7 +664,7 @@ bool StringFunctions::SetRE2Options(const StringVal& match_parameter,
 
 void StringFunctions::RegexpPrepare(
     FunctionContext* context, FunctionContext::FunctionStateScope scope) {
-  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
+  if (scope != FunctionContext::THREAD_LOCAL) return;
   if (!context->IsArgConstant(1)) return;
   DCHECK_EQ(context->GetArgType(1)->type, FunctionContext::TYPE_STRING);
   StringVal* pattern = reinterpret_cast<StringVal*>(context->GetConstantArg(1));
@@ -681,7 +681,7 @@ void StringFunctions::RegexpPrepare(
 
 void StringFunctions::RegexpClose(
     FunctionContext* context, FunctionContext::FunctionStateScope scope) {
-  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
+  if (scope != FunctionContext::THREAD_LOCAL) return;
   re2::RE2* re = reinterpret_cast<re2::RE2*>(context->GetFunctionState(scope));
   delete re;
   context->SetFunctionState(scope, nullptr);
@@ -715,7 +715,7 @@ StringVal StringFunctions::RegexpExtract(FunctionContext* context, const StringV
   if (index.val < 0) return StringVal();
 
   re2::RE2* re = reinterpret_cast<re2::RE2*>(
-      context->GetFunctionState(FunctionContext::FRAGMENT_LOCAL));
+      context->GetFunctionState(FunctionContext::THREAD_LOCAL));
   scoped_ptr<re2::RE2> scoped_re; // destroys re if we have to locally compile it
   if (re == NULL) {
     DCHECK(!context->IsArgConstant(1));
@@ -747,7 +747,7 @@ StringVal StringFunctions::RegexpReplace(FunctionContext* context, const StringV
   if (str.is_null || pattern.is_null || replace.is_null) return StringVal::null();
 
   re2::RE2* re = reinterpret_cast<re2::RE2*>(
-      context->GetFunctionState(FunctionContext::FRAGMENT_LOCAL));
+      context->GetFunctionState(FunctionContext::THREAD_LOCAL));
   scoped_ptr<re2::RE2> scoped_re; // destroys re if state->re is NULL
   if (re == NULL) {
     DCHECK(!context->IsArgConstant(1));
@@ -769,7 +769,7 @@ StringVal StringFunctions::RegexpReplace(FunctionContext* context, const StringV
 
 void StringFunctions::RegexpMatchCountPrepare(FunctionContext* context,
     FunctionContext::FunctionStateScope scope) {
-  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
+  if (scope != FunctionContext::THREAD_LOCAL) return;
   int num_args = context->GetNumArgs();
   DCHECK(num_args == 2 || num_args == 4);
   if (!context->IsArgConstant(1) || (num_args == 4 && !context->IsArgConstant(3))) return;
@@ -816,7 +816,7 @@ IntVal StringFunctions::RegexpMatchCount4Args(FunctionContext* context,
   }
 
   re2::RE2* re = reinterpret_cast<re2::RE2*>(
-      context->GetFunctionState(FunctionContext::FRAGMENT_LOCAL));
+      context->GetFunctionState(FunctionContext::THREAD_LOCAL));
   // Destroys re if we have to locally compile it.
   scoped_ptr<re2::RE2> scoped_re;
   if (re == NULL) {