code: def print_compiledir_content():
      """
      print list of %d compiled individual ops in the "pytensor.config.compiledir"
      """
      max_key_file_size = 1 * 1024 * 1024  # 1M
  
      compiledir = config.compiledir
      table = []
      table_multiple_ops = []
      table_op_class = {}
      zeros_op = 0
      big_key_files = []
      total_key_sizes = 0
      nb_keys = {}
      for dir in os.listdir(compiledir):
          filename = os.path.join(compiledir, dir, "key.pkl")
          if not os.path.exists(filename):
              continue
          with open(filename, "rb") as file:
              try:
                  keydata = pickle.load(file)
                  ops = list(
                      {
                          x
                          for x in flatten(keydata.keys)
                          if isinstance(x, Op)
                      }
                  )
                  # Whatever the case, we count compilations for OP classes.
                  for op_class in {op.__class__ for op in ops}:
                      table_op_class.setdefault(op_class, 0)
                      table_op_class[op_class] += 1
                  if len(ops) == 0:
                      zeros_op += 1
                  else:
                      types = list(
                          {
                              x
                              for x in flatten(keydata.keys)
                              if isinstance(x, CType)
                          }
                      )
                      compile_start = compile_end = float("nan")
                      for fn in os.listdir(
                          os.path.join(compiledir, dir)
                      ):
                          if fn.startswith("mod.c"):
                              compile_start = os.path.getmtime(
                                  os.path.join(compiledir, dir, fn)
                              )
                          elif fn.endswith(".so"):
                              compile_end = os.path.getmtime(
                                  os.path.join(compiledir, dir, fn)
                              )
                      compile_time = compile_end - compile_start
                      if len(ops) == 1:
                          table.append(
                              (dir, ops[0], types, compile_time)
                          )
                      else:
                          ops_to_str = f"[{', '.join(sorted(str(op) for op in ops))}]"
                          types_to_str = f"[{', '.join(sorted(str(t) for t in types))}]"
                          table_multiple_ops.append(
                              (
                                  dir,
                                  ops_to_str,
                                  types_to_str,
                                  compile_time,
                              )
                          )
  
                  size = os.path.getsize(filename)
                  total_key_sizes += size
                  if size > max_key_file_size:
                      big_key_files.append((dir, size, ops))
  
                  nb_keys.setdefault(len(keydata.keys), 0)
                  nb_keys[len(keydata.keys)] += 1
              except OSError:
                  pass
              except AttributeError:
                  _logger.error(
                      f"Could not read key file '{filename}'."
                  )
  
      print_title(
          f"PyTensor cache: {compiledir}", overline="=", underline="="
      )
      print()
  
      print_title(
          f"List of {len(table)} compiled individual ops", underline="+"
      )
      print_title(
          "sub dir/compiletime/Op/set of different associated PyTensor types",
          underline="-",
      )
      table = sorted(table, key=lambda t: str(t[1]))
      for dir, op, types, compile_time in table:
          print(dir, f"{compile_time:.3f}s", op, types)
  
      print()
      print_title(
          f"List of {len(table_multiple_ops)} compiled sets of ops",
          underline="+",
      )
      print_title(
          "sub dir/compiletime/Set of ops/set of different associated PyTensor types",
          underline="-",
      )
      table_multiple_ops = sorted(
          table_multiple_ops, key=lambda t: (t[1], t[2])
      )
      for (
          dir,
          ops_to_str,
          types_to_str,
          compile_time,
      ) in table_multiple_ops:
          print(dir, f"{compile_time:.3f}s", ops_to_str, types_to_str)
  
      print()
      print_title(
          (
              f"List of {len(table_op_class)} compiled Op classes and "
              "the number of times they got compiled"
          ),
          underline="+",
      )
      table_op_class = sorted(
          table_op_class.items(), key=lambda t: t[1]
      )
      for op_class, nb in table_op_class:
          print(op_class, nb)
  
      if big_key_files:
          big_key_files = sorted(big_key_files, key=lambda t: str(t[1]))
          big_total_size = sum(sz for _, sz, _ in big_key_files)
          print(
              f"There are directories with key files bigger than {int(max_key_file_size)} bytes "
              "(they probably contain big tensor constants)"
          )
          print(
              f"They use {int(big_total_size)} bytes out of {int(total_key_sizes)} (total size "
              "used by all key files)"
          )
  
          for dir, size, ops in big_key_files:
              print(dir, size, ops)
  
      nb_keys = sorted(nb_keys.items())
      print()
      print_title("Number of keys for a compiled module", underline="+")
      print_title(
          "number of keys/number of modules with that number of keys",
          underline="-",
      )
      for n_k, n_m in nb_keys:
          print(n_k, n_m)
      print()
      print(
          f"Skipped {int(zeros_op)} files that contained 0 op "
          "(are they always pytensor.scalar ops?)"
      )
  
file_path: pytensor/pytensor/compile/compiledir.py
imports: import logging
  import os
  import pickle
  import shutil
  import numpy
  from pytensor.configdefaults import config
  from pytensor.graph.op import Op
  from pytensor.link.c.type import CType
  from pytensor.utils import flatten
label_desc: Use image node_id 3 for calling a global function with example usage: print_compiledir_content() without return types