Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 553368e

Browse files
committed
chore: investigate b/440407542
1 parent 8804ada commit 553368e

File tree

11 files changed

+307
-6
lines changed

11 files changed

+307
-6
lines changed

bigframes/bigquery/_operations/search.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def create_vector_index(
8787

8888
read_gbq_query(sql)
8989

90-
90+
import bigframes.perf_inspect as perf_inspect
91+
@perf_inspect.runtime_logger
9192
def vector_search(
9293
base_table: str,
9394
column_to_search: str,
@@ -246,5 +247,4 @@ def vector_search(
246247
df.index.names = index_labels
247248
else:
248249
df = query._session.read_gbq_query(sql, allow_large_results=allow_large_results)
249-
250250
return df

bigframes/core/blocks.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
Union,
4242
)
4343
import warnings
44+
import bigframes.perf_inspect as perf_inspect
4445

4546
import bigframes_vendored.constants as constants
4647
import google.cloud.bigquery as bigquery
@@ -940,6 +941,8 @@ def split(
940941
]
941942
return [sliced_block.drop_columns(drop_cols) for sliced_block in sliced_blocks]
942943

944+
945+
@perf_inspect.runtime_logger
943946
def _compute_dry_run(
944947
self,
945948
value_keys: Optional[Iterable[str]] = None,
@@ -1629,6 +1632,7 @@ def slice(
16291632
# Using cache to optimize for Jupyter Notebook's behavior where both '__repr__'
16301633
# and '__repr_html__' are called in a single display action, reducing redundant
16311634
# queries.
1635+
@perf_inspect.runtime_logger
16321636
@functools.cache
16331637
def retrieve_repr_request_results(
16341638
self, max_results: int
@@ -1646,22 +1650,29 @@ def retrieve_repr_request_results(
16461650
array_value=self.expr,
16471651
config=executors.CacheConfig(optimize_for="head", if_cached="reuse-strict"),
16481652
)
1653+
import time
1654+
start_time = time.monotonic()
16491655
head_result = self.session._executor.execute(
16501656
self.expr.slice(start=None, stop=max_results, step=None),
16511657
execution_spec.ExecutionSpec(
16521658
promise_under_10gb=True,
16531659
ordered=True,
16541660
),
16551661
)
1662+
print("Time taken to execute head: {:.2f} seconds".format(time.monotonic() - start_time))
1663+
start_time = time.monotonic()
16561664
row_count = self.session._executor.execute(
16571665
self.expr.row_count(),
16581666
execution_spec.ExecutionSpec(
16591667
promise_under_10gb=True,
16601668
ordered=False,
16611669
),
16621670
).to_py_scalar()
1671+
print("Time taken to execute row_count: {:.2f} seconds".format(time.monotonic() - start_time))
16631672

1673+
start_time = time.monotonic()
16641674
head_df = head_result.to_pandas()
1675+
print("Time taken to execute to_pandas: {:.2f} seconds".format(time.monotonic() - start_time))
16651676
return self._copy_index_to_pandas(head_df), row_count, head_result.query_job
16661677

16671678
def promote_offsets(self, label: Label = None) -> typing.Tuple[Block, str]:

bigframes/core/global_session.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ def close_session() -> None:
8383
bigframes._config.options.bigquery._session_started = False
8484

8585

86+
import bigframes.perf_inspect as perf_inspect
87+
@perf_inspect.runtime_logger
8688
def get_global_session():
8789
"""Gets the global session.
8890

bigframes/dataframe.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
import pyarrow
5555
import tabulate
5656

57+
import bigframes.perf_inspect as perf_inspect
58+
5759
import bigframes._config.display_options as display_options
5860
import bigframes.constants
5961
import bigframes.core
@@ -116,6 +118,8 @@ class DataFrame(vendored_pandas_frame.DataFrame):
116118
# Must be above 5000 for pandas to delegate to bigframes for binops
117119
__pandas_priority__ = 15000
118120

121+
import bigframes.perf_inspect as perf_inspect
122+
@perf_inspect.runtime_logger
119123
def __init__(
120124
self,
121125
data=None,
@@ -725,6 +729,7 @@ def __setattr__(self, key: str, value):
725729
else:
726730
object.__setattr__(self, key, value)
727731

732+
@perf_inspect.runtime_logger
728733
def __repr__(self) -> str:
729734
"""Converts a DataFrame to a string. Calls to_pandas.
730735
@@ -777,6 +782,7 @@ def __repr__(self) -> str:
777782
lines.append(f"[{row_count} rows x {column_count} columns]")
778783
return "\n".join(lines)
779784

785+
@perf_inspect.runtime_logger
780786
def _repr_html_(self) -> str:
781787
"""
782788
Returns an html string primarily for use by notebooks for displaying
@@ -1703,6 +1709,9 @@ def to_pandas(
17031709
) -> pandas.Series:
17041710
...
17051711

1712+
1713+
import bigframes.perf_inspect as perf_inspect
1714+
@perf_inspect.runtime_logger
17061715
def to_pandas(
17071716
self,
17081717
max_download_size: Optional[int] = None,
@@ -1887,6 +1896,7 @@ def to_pandas_batches(
18871896
allow_large_results=allow_large_results,
18881897
)
18891898

1899+
@perf_inspect.runtime_logger
18901900
def _compute_dry_run(self) -> bigquery.QueryJob:
18911901
_, query_job = self._block._compute_dry_run()
18921902
return query_job

bigframes/formatting_helpers.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ def repr_query_job_html(query_job: Optional[bigquery.QueryJob]):
9090
table_html += "</table>"
9191
return widgets.HTML(table_html)
9292

93-
9493
def repr_query_job(query_job: Optional[bigquery.QueryJob]):
9594
"""Return query job as a formatted string.
9695
Args:
@@ -118,7 +117,6 @@ def repr_query_job(query_job: Optional[bigquery.QueryJob]):
118117
res += f"""{key}: {job_val}"""
119118
return res
120119

121-
122120
def wait_for_query_job(
123121
query_job: bigquery.QueryJob,
124122
max_results: Optional[int] = None,

bigframes/perf_inspect.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import functools
16+
import time
17+
18+
global_counter = 0
19+
20+
def runtime_logger(func):
21+
"""Decorator to log the runtime of a function."""
22+
23+
@functools.wraps(func)
24+
def wrapper(*args, **kwargs):
25+
global global_counter
26+
global_counter += 1
27+
prefix = "--" * global_counter
28+
29+
start_time = time.monotonic()
30+
31+
print(f"|{prefix}{func.__qualname__} started at {start_time:.2f} seconds")
32+
result = func(*args, **kwargs)
33+
end_time = time.monotonic()
34+
print(
35+
f"|{prefix}{func.__qualname__} ended at {end_time:.2f} seconds. "
36+
f"Runtime: {end_time - start_time:.2f} seconds"
37+
)
38+
global_counter -= 1
39+
return result
40+
41+
return wrapper

bigframes/session/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ class Session(
130130
An object providing client library objects.
131131
"""
132132

133+
import bigframes.perf_inspect as perf_inspect
134+
@perf_inspect.runtime_logger
133135
def __init__(
134136
self,
135137
context: Optional[bigquery_options.BigQueryOptions] = None,
@@ -143,7 +145,6 @@ def __init__(
143145

144146
if context is None:
145147
context = bigquery_options.BigQueryOptions()
146-
147148
if context.location is None:
148149
self._location = "US"
149150
msg = bfe.format_message(
@@ -184,7 +185,6 @@ def __init__(
184185
client_endpoints_override=context.client_endpoints_override,
185186
requests_transport_adapters=context.requests_transport_adapters,
186187
)
187-
188188
# TODO(shobs): Remove this logic after https://github.com/ibis-project/ibis/issues/8494
189189
# has been fixed. The ibis client changes the default query job config
190190
# so we are going to remember the current config and restore it after

bigframes/session/bq_caching_executor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import bigframes.session.metrics
5252
import bigframes.session.planner
5353
import bigframes.session.temporary_storage
54+
import bigframes.perf_inspect as perf_inspect
5455

5556
# Max complexity that should be executed as a single query
5657
QUERY_COMPLEXITY_LIMIT = 1e7
@@ -182,6 +183,8 @@ def to_sql(
182183
compiled = compile.compile_sql(compile.CompileRequest(node, sort_rows=ordered))
183184
return compiled.sql
184185

186+
187+
@perf_inspect.runtime_logger
185188
def execute(
186189
self,
187190
array_value: bigframes.core.ArrayValue,

bigframes/session/clients.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
_BIGQUERYSTORAGE_REGIONAL_ENDPOINT = "bigquerystorage.{location}.rep.googleapis.com"
5151

5252

53+
import bigframes.perf_inspect as perf_inspect
54+
@perf_inspect.runtime_logger
5355
def _get_default_credentials_with_project():
5456
return pydata_google_auth.default(scopes=_SCOPES, use_local_webserver=False)
5557

@@ -72,6 +74,8 @@ def _get_application_names():
7274
class ClientsProvider:
7375
"""Provides client instances necessary to perform cloud operations."""
7476

77+
import bigframes.perf_inspect as perf_inspect
78+
@perf_inspect.runtime_logger
7579
def __init__(
7680
self,
7781
project: Optional[str] = None,

bigframes/session/executor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import bigframes.core.schema
3131
import bigframes.session._io.pandas as io_pandas
3232
import bigframes.session.execution_spec as ex_spec
33+
import bigframes.perf_inspect as perf_inspect
3334

3435
_ROW_LIMIT_EXCEEDED_TEMPLATE = (
3536
"Execution has downloaded {result_rows} rows so far, which exceeds the "
@@ -150,6 +151,7 @@ def to_sql(
150151
raise NotImplementedError("to_sql not implemented for this executor")
151152

152153
@abc.abstractmethod
154+
@perf_inspect.runtime_logger
153155
def execute(
154156
self,
155157
array_value: bigframes.core.ArrayValue,

0 commit comments

Comments
 (0)