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

marin-ma pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new d35552e625 [VL] Fix SCOPED_TIMER macro destroying timer immediately 
(#12083)
d35552e625 is described below

commit d35552e62551f1042811a907e0668df086853816
Author: Luis Peñaranda <[email protected]>
AuthorDate: Thu May 14 18:01:21 2026 +0200

    [VL] Fix SCOPED_TIMER macro destroying timer immediately (#12083)
---
 cpp/core/utils/Macros.h            |  3 +-
 cpp/velox/tests/CMakeLists.txt     |  1 +
 cpp/velox/tests/ScopedTimerTest.cc | 88 ++++++++++++++++++++++++++++++++++++++
 cpp/velox/utils/Common.h           | 28 +++++++++---
 4 files changed, 113 insertions(+), 7 deletions(-)

diff --git a/cpp/core/utils/Macros.h b/cpp/core/utils/Macros.h
index 74128cca35..cbdfdcbc2e 100644
--- a/cpp/core/utils/Macros.h
+++ b/cpp/core/utils/Macros.h
@@ -28,7 +28,8 @@
 #define GLUTEN_EXPAND(x) x
 #define GLUTEN_STRINGIFY(x) #x
 #define GLUTEN_TOSTRING(x) GLUTEN_STRINGIFY(x)
-#define GLUTEN_CONCAT(x, y) x##y
+#define GLUTEN_CONCAT_INNER(x, y) x##y
+#define GLUTEN_CONCAT(x, y) GLUTEN_CONCAT_INNER(x, y)
 
 #define TIME_NANO_DIFF(finish, start) (finish.tv_sec - start.tv_sec) * 
1000000000 + (finish.tv_nsec - start.tv_nsec)
 
diff --git a/cpp/velox/tests/CMakeLists.txt b/cpp/velox/tests/CMakeLists.txt
index 37d9cfb238..0cd9e38bc6 100644
--- a/cpp/velox/tests/CMakeLists.txt
+++ b/cpp/velox/tests/CMakeLists.txt
@@ -134,6 +134,7 @@ add_velox_test(spark_functions_test SOURCES 
SparkFunctionTest.cc
 add_velox_test(runtime_test SOURCES RuntimeTest.cc)
 add_velox_test(velox_memory_test SOURCES MemoryManagerTest.cc)
 add_velox_test(buffer_outputstream_test SOURCES BufferOutputStreamTest.cc)
+add_velox_test(scoped_timer_test SOURCES ScopedTimerTest.cc)
 if(BUILD_EXAMPLES)
   add_velox_test(my_udf_test SOURCES MyUdfTest.cc)
 endif()
diff --git a/cpp/velox/tests/ScopedTimerTest.cc 
b/cpp/velox/tests/ScopedTimerTest.cc
new file mode 100644
index 0000000000..09479cb9f4
--- /dev/null
+++ b/cpp/velox/tests/ScopedTimerTest.cc
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/Common.h"
+
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <thread>
+
+#include "velox/common/time/CpuWallTimer.h"
+
+namespace gluten {
+
+// Regression test: SCOPED_TIMER must accumulate elapsed time across the
+// enclosing scope. A previous implementation wrapped the underlying
+// DeltaCpuWallTimer in a `do { ... } while (0)` block, which destroyed the
+// timer immediately after construction and recorded ~0 ns. See
+// https://github.com/apache/gluten/pull/<this-PR>.
+TEST(ScopedTimerTest, accumulatesElapsedTime) {
+  facebook::velox::CpuWallTiming timing{};
+  constexpr auto kSleep = std::chrono::milliseconds(50);
+
+  {
+    SCOPED_TIMER(timing);
+    std::this_thread::sleep_for(kSleep);
+  }
+
+  EXPECT_EQ(timing.count, 1);
+  // The sleep is on wall clock, not CPU. Allow a generous lower bound
+  // to tolerate scheduler jitter on CI.
+  constexpr uint64_t kMinWallNanos = std::chrono::nanoseconds(kSleep).count() 
/ 2;
+  EXPECT_GT(timing.wallNanos, kMinWallNanos);
+}
+
+// Multiple SCOPED_TIMER calls in the same scope must each accumulate
+// independently. The unique-naming pattern in the macro (using __LINE__)
+// is what makes this work.
+TEST(ScopedTimerTest, multipleTimersInSameScope) {
+  facebook::velox::CpuWallTiming timing1{};
+  facebook::velox::CpuWallTiming timing2{};
+  constexpr auto kSleep = std::chrono::milliseconds(20);
+
+  {
+    SCOPED_TIMER(timing1);
+    SCOPED_TIMER(timing2);
+    std::this_thread::sleep_for(kSleep);
+  }
+
+  EXPECT_EQ(timing1.count, 1);
+  EXPECT_EQ(timing2.count, 1);
+  constexpr uint64_t kMinWallNanos = std::chrono::nanoseconds(kSleep).count() 
/ 2;
+  EXPECT_GT(timing1.wallNanos, kMinWallNanos);
+  EXPECT_GT(timing2.wallNanos, kMinWallNanos);
+}
+
+// SCOPED_TIMER must accept arbitrary lvalue expressions (e.g. an array
+// element) as the timing target, not just simple identifiers.
+TEST(ScopedTimerTest, acceptsArrayElementAsTarget) {
+  std::vector<facebook::velox::CpuWallTiming> timings(2);
+  constexpr auto kSleep = std::chrono::milliseconds(20);
+
+  {
+    SCOPED_TIMER(timings[1]);
+    std::this_thread::sleep_for(kSleep);
+  }
+
+  EXPECT_EQ(timings[0].count, 0);
+  EXPECT_EQ(timings[1].count, 1);
+  constexpr uint64_t kMinWallNanos = std::chrono::nanoseconds(kSleep).count() 
/ 2;
+  EXPECT_GT(timings[1].wallNanos, kMinWallNanos);
+}
+
+} // namespace gluten
diff --git a/cpp/velox/utils/Common.h b/cpp/velox/utils/Common.h
index 6dd92b409d..5c82d0ee69 100644
--- a/cpp/velox/utils/Common.h
+++ b/cpp/velox/utils/Common.h
@@ -21,6 +21,7 @@
 #include <memory>
 #include <string>
 
+#include "utils/Macros.h"
 #include "velox/common/base/SimdUtil.h"
 #include "velox/common/time/CpuWallTimer.h"
 
@@ -35,11 +36,26 @@ static inline void fastCopy(void* dst, const void* src, 
size_t n) {
   facebook::velox::simd::memcpy(dst, src, n);
 }
 
-#define SCOPED_TIMER(timing)                                                   
           \
-  do {                                                                         
           \
-    auto ptiming = &timing;                                                    
           \
-    facebook::velox::DeltaCpuWallTimer timer{                                  
           \
-        [ptiming](const facebook::velox::CpuWallTiming& delta) { 
ptiming->add(delta); }}; \
-  } while (0)
+// SCOPED_TIMER — RAII-style timer that lives until the end of the
+// enclosing scope and reports elapsed CPU+wall time to `timing` on
+// destruction.
+//
+// Implementation note: a `do { … } while (0)` wrapper would destroy
+// the DeltaCpuWallTimer immediately at the end of the do-block,
+// recording essentially zero. Instead we declare uniquely-named
+// locals (via GLUTEN_CONCAT(..., __LINE__)) so the timer survives
+// until the enclosing scope closes — which is what every call site
+// already expects.
+//
+// Note: we capture the timing target by pointer in a unique local
+// variable rather than directly in the lambda, because `timing` may
+// be an arbitrary expression (e.g. `array_[idx]`) that is not a valid
+// lambda capture name.
+#define SCOPED_TIMER(timing)                                                   
                   \
+  auto GLUTEN_CONCAT(_glutenScopedTimerTarget_, __LINE__) = &(timing);         
                   \
+  facebook::velox::DeltaCpuWallTimer GLUTEN_CONCAT(_glutenScopedTimer_, 
__LINE__) {               \
+    [_glutenScopedTimerTargetPtr = GLUTEN_CONCAT(_glutenScopedTimerTarget_, 
__LINE__)](           \
+        const facebook::velox::CpuWallTiming& delta) { 
_glutenScopedTimerTargetPtr->add(delta); } \
+  }
 
 } // namespace gluten


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to