Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1695119

Browse files
feat: add caching to GapicCallable (#666)
* feat: optimize _GapicCallable* cleaned up metadata lines* chore: avoid type checks in error wrapper* Revert "chore: avoid type checks in error wrapper"This reverts commitc97a636.* add default wrapped function* fixed decorator order* fixed spacing* fixed comment typo* fixed spacing* fixed spacing* removed unneeded helpers* use caching* improved metadata parsing* improved docstring* fixed logic* added benchmark test* update threshold* run benchmark in loop for testing* use verbose logs* Revert testing* used smaller value* changed threshold* removed link in comment* use list type for metadata* add types to docstring* fixed lint* convert to list at init time---------Co-authored-by: Daniel Sanche <sanche@google.com>Co-authored-by: Daniel Sanche <d.sanche14@gmail.com>
1 parent3c69867 commit1695119

File tree

2 files changed

+57
-44
lines changed

2 files changed

+57
-44
lines changed

‎google/api_core/gapic_v1/method.py‎

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,6 @@ class _MethodDefault(enum.Enum):
4242
so the default should be used."""
4343

4444

45-
def_is_not_none_or_false(value):
46-
returnvalueisnotNoneandvalueisnotFalse
47-
48-
49-
def_apply_decorators(func,decorators):
50-
"""Apply a list of decorators to a given function.
51-
52-
``decorators`` may contain items that are ``None`` or ``False`` which will
53-
be ignored.
54-
"""
55-
filtered_decorators=filter(_is_not_none_or_false,reversed(decorators))
56-
57-
fordecoratorinfiltered_decorators:
58-
func=decorator(func)
59-
60-
returnfunc
61-
62-
6345
class_GapicCallable(object):
6446
"""Callable that applies retry, timeout, and metadata logic.
6547
@@ -91,44 +73,53 @@ def __init__(
9173
):
9274
self._target=target
9375
self._retry=retry
76+
ifisinstance(timeout, (int,float)):
77+
timeout=TimeToDeadlineTimeout(timeout=timeout)
9478
self._timeout=timeout
9579
self._compression=compression
96-
self._metadata=metadata
80+
self._metadata=list(metadata)ifmetadataisnotNoneelseNone
9781

9882
def__call__(
9983
self,*args,timeout=DEFAULT,retry=DEFAULT,compression=DEFAULT,**kwargs
10084
):
10185
"""Invoke the low-level RPC with retry, timeout, compression, and metadata."""
10286

103-
ifretryisDEFAULT:
104-
retry=self._retry
105-
106-
iftimeoutisDEFAULT:
107-
timeout=self._timeout
108-
10987
ifcompressionisDEFAULT:
11088
compression=self._compression
111-
112-
ifisinstance(timeout, (int,float)):
113-
timeout=TimeToDeadlineTimeout(timeout=timeout)
114-
115-
# Apply all applicable decorators.
116-
wrapped_func=_apply_decorators(self._target, [retry,timeout])
89+
ifcompressionisnotNone:
90+
kwargs["compression"]=compression
11791

11892
# Add the user agent metadata to the call.
11993
ifself._metadataisnotNone:
120-
metadata=kwargs.get("metadata", [])
121-
# Due to the nature of invocation, None should be treated the same
122-
# as not specified.
123-
ifmetadataisNone:
124-
metadata= []
125-
metadata=list(metadata)
126-
metadata.extend(self._metadata)
127-
kwargs["metadata"]=metadata
128-
ifself._compressionisnotNone:
129-
kwargs["compression"]=compression
94+
try:
95+
# attempt to concatenate default metadata with user-provided metadata
96+
kwargs["metadata"]= [*kwargs["metadata"],*self._metadata]
97+
except (KeyError,TypeError):
98+
# if metadata is not provided, use just the default metadata
99+
kwargs["metadata"]=self._metadata
100+
101+
call=self._build_wrapped_call(timeout,retry)
102+
returncall(*args,**kwargs)
103+
104+
@functools.lru_cache(maxsize=4)
105+
def_build_wrapped_call(self,timeout,retry):
106+
"""
107+
Build a wrapped callable that applies retry, timeout, and metadata logic.
108+
"""
109+
wrapped_func=self._target
110+
iftimeoutisDEFAULT:
111+
timeout=self._timeout
112+
elifisinstance(timeout, (int,float)):
113+
timeout=TimeToDeadlineTimeout(timeout=timeout)
114+
iftimeoutisnotNone:
115+
wrapped_func=timeout(wrapped_func)
116+
117+
ifretryisDEFAULT:
118+
retry=self._retry
119+
ifretryisnotNone:
120+
wrapped_func=retry(wrapped_func)
130121

131-
returnwrapped_func(*args,**kwargs)
122+
returnwrapped_func
132123

133124

134125
defwrap_method(
@@ -202,8 +193,9 @@ def get_topic(name, timeout=None):
202193
203194
Args:
204195
func (Callable[Any]): The function to wrap. It should accept an
205-
optional ``timeout`` argument. If ``metadata`` is not ``None``, it
206-
should accept a ``metadata`` argument.
196+
optional ``timeout`` (google.api_core.timeout.Timeout) argument.
197+
If ``metadata`` is not ``None``, it should accept a ``metadata``
198+
(Sequence[Tuple[str, str]]) argument.
207199
default_retry (Optional[google.api_core.Retry]): The default retry
208200
strategy. If ``None``, the method will not retry by default.
209201
default_timeout (Optional[google.api_core.Timeout]): The default

‎tests/unit/gapic/test_method.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,24 @@ def test_wrap_method_with_call_not_supported():
222222
withpytest.raises(ValueError)asexc_info:
223223
google.api_core.gapic_v1.method.wrap_method(method,with_call=True)
224224
assert"with_call=True is only supported for unary calls"instr(exc_info.value)
225+
226+
227+
deftest_benchmark_gapic_call():
228+
"""
229+
Ensure the __call__ method performance does not regress from expectations
230+
231+
__call__ builds a new wrapped function using passed-in timeout and retry, but
232+
subsequent calls are cached
233+
234+
Note: The threshold has been tuned for the CI workers. Test may flake on
235+
slower hardware
236+
"""
237+
fromgoogle.api_core.gapic_v1.methodimport_GapicCallable
238+
fromgoogle.api_core.retryimportRetry
239+
fromtimeitimporttimeit
240+
241+
gapic_callable=_GapicCallable(
242+
lambda*a,**k:1,retry=Retry(),timeout=1010,compression=False
243+
)
244+
avg_time=timeit(lambda:gapic_callable(),number=10_000)
245+
assertavg_time<0.4

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp