1919import os
2020import pathlib
2121import typing
22+ import time
23+ import sys
2224from typing import Any , DefaultDict , Dict , Mapping , Optional , Tuple
2325from hashlib import sha256
2426from collections import OrderedDict , defaultdict
3436from gapic .schema import api
3537from gapic import utils
3638from gapic .utils import Options
39+ from gapic .utils import rst as rst_module
3740from google .protobuf .compiler .plugin_pb2 import CodeGeneratorResponse
3841
42+ # <--- Profiling Global --->
43+ LOG_FILE = "/tmp/gapic_profile.log"
44+
45+ def _log (msg ):
46+ # Append mode so we don't wipe logs from previous steps/APIs
47+ with open (LOG_FILE , "a" , encoding = "utf-8" ) as f :
48+ f .write (f"[{ time .strftime ('%H:%M:%S' )} ] { msg } \n " )
49+ # <--- End Profiling Global --->
3950
4051class Generator :
4152 """A protoc code generator for client libraries.
@@ -91,6 +102,11 @@ def get_response(self, api_schema: api.API, opts: Options) -> CodeGeneratorRespo
91102 ~.CodeGeneratorResponse: A response describing appropriate
92103 files and contents. See ``plugin.proto``.
93104 """
105+ # <--- Profiling Start --->
106+ _log (f"--- GENERATION STARTED (get_response) FOR { api_schema .naming .proto_package } ---" )
107+ start_time = time .time () # FIXED: Variable name matches end usage
108+ # <--- Profiling End --->
109+
94110 output_files : Dict [str , CodeGeneratorResponse .File ] = OrderedDict ()
95111 sample_templates , client_templates = utils .partition (
96112 lambda fname : os .path .basename (fname ) == samplegen .DEFAULT_TEMPLATE_NAME ,
@@ -101,13 +117,15 @@ def get_response(self, api_schema: api.API, opts: Options) -> CodeGeneratorRespo
101117 # can be inserted into method docstrings.
102118 snippet_idx = snippet_index .SnippetIndex (api_schema )
103119 if sample_templates :
120+ t_samples = time .time ()
104121 sample_output , snippet_idx = self ._generate_samples_and_manifest (
105122 api_schema ,
106123 snippet_idx ,
107124 self ._env .get_template (sample_templates [0 ]),
108125 opts = opts ,
109126 )
110127 output_files .update (sample_output )
128+ _log (f"Phase: Sample Gen took { time .time () - t_samples :.4f} s" )
111129
112130 # Iterate over each template and add the appropriate output files
113131 # based on that template.
@@ -119,8 +137,9 @@ def get_response(self, api_schema: api.API, opts: Options) -> CodeGeneratorRespo
119137 filename = template_name .split ("/" )[- 1 ]
120138 if filename .startswith ("_" ) and filename != "__init__.py.j2" :
121139 continue
122-
123- # Append to the output files dictionary.
140+
141+ # <--- Profiling Template --->
142+ t_tpl = time .time ()
124143 output_files .update (
125144 self ._render_template (
126145 template_name ,
@@ -129,12 +148,18 @@ def get_response(self, api_schema: api.API, opts: Options) -> CodeGeneratorRespo
129148 snippet_index = snippet_idx ,
130149 )
131150 )
151+ duration = time .time () - t_tpl
152+ if duration > 1.0 :
153+ _log (f"Phase: Template [{ template_name } ] took { duration :.4f} s" )
154+ # <--- End Profiling Template --->
132155
133156 # Return the CodeGeneratorResponse output.
134157 res = CodeGeneratorResponse (
135158 file = [i for i in output_files .values ()]
136159 ) # type: ignore
137160 res .supported_features |= CodeGeneratorResponse .Feature .FEATURE_PROTO3_OPTIONAL # type: ignore
161+
162+ _log (f"TOTAL GENERATION COMPLETE (get_response): { time .time () - start_time :.4f} s" )
138163 return res
139164
140165 def _generate_samples_and_manifest (
@@ -400,6 +425,10 @@ def _get_file(
400425 context = context ,
401426 )
402427
428+ # <--- Profiling Render Start --->
429+ t_render = time .time ()
430+ # <--- End Profiling Render Start --->
431+
403432 # Render the file contents.
404433 cgr_file = CodeGeneratorResponse .File (
405434 content = formatter .fix_whitespace (
@@ -410,6 +439,12 @@ def _get_file(
410439 name = fn ,
411440 )
412441
442+ # <--- Profiling Render End --->
443+ duration = time .time () - t_render
444+ if duration > 0.5 :
445+ _log (f" > RENDER: { fn } ({ duration :.4f} s)" )
446+ # <--- End Profiling Render End --->
447+
413448 # Quick check: Do not render empty files.
414449 if utils .empty (cgr_file .content ) and not fn .endswith (
415450 ("py.typed" , "__init__.py" )
0 commit comments