report_memory_usage.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. # Copyright 2024 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. import os
  15. from waflib import Logs, Task
  16. from waflib.TaskGen import after_method, feature
  17. from binutils import size
  18. from memory_reports import (app_memory_report, app_resource_memory_error,
  19. app_appstore_resource_memory_error,
  20. bytecode_memory_report, simple_memory_report)
  21. from sdk_helpers import is_sdk_2x
  22. class memory_usage_report(Task.Task):
  23. """
  24. Task class to print a memory usage report for the specified binary and resources, if any
  25. """
  26. def run(self):
  27. """
  28. This method executes when the memory usage report task runs
  29. :return: None
  30. """
  31. bin_type = self.bin_type
  32. platform = self.generator.env.PLATFORM_NAME
  33. if bin_type == 'rocky':
  34. env = self.generator.bld.all_envs[self.env.PLATFORM_NAME]
  35. Logs.pprint(*bytecode_memory_report(platform, env.SNAPSHOT_SIZE, env.SNAPSHOT_MAX))
  36. return
  37. bin_path = self.inputs[0].abspath()
  38. resources_path = self.inputs[1].abspath() if len(self.inputs) > 1 else None
  39. max_ram, max_resources, max_appstore_resources = self.max_sizes
  40. # Handle zero-size binaries (more common with packages)
  41. ram_size = sum(size(bin_path)) if size(bin_path) != 0 else 0
  42. resource_size = os.stat(resources_path).st_size if resources_path else None
  43. if resource_size and max_resources and max_appstore_resources:
  44. if resource_size > max_resources:
  45. Logs.pprint(*app_appstore_resource_memory_error(platform, resource_size,
  46. max_resources))
  47. return -1
  48. elif resource_size > max_appstore_resources:
  49. Logs.pprint(*app_appstore_resource_memory_error(platform, resource_size,
  50. max_appstore_resources))
  51. if max_ram:
  52. # resource_size and max_appstore_resources are optional
  53. free_ram = max_ram - ram_size
  54. Logs.pprint(*app_memory_report(platform, bin_type, ram_size, max_ram,
  55. free_ram, resource_size, max_appstore_resources))
  56. else:
  57. # resource_size is optional
  58. Logs.pprint(*simple_memory_report(platform, ram_size, resource_size))
  59. @feature('memory_usage')
  60. @after_method('cprogram', 'cstlib', 'process_rocky_js')
  61. def generate_memory_usage_report(task_gen):
  62. """
  63. Generates and prints a report of the project's memory usage (binary + resources, if applicable).
  64. Keyword arguments:
  65. app -- The path to the app elf file, if this is an app being evaluated
  66. worker - The path to the worker elf file, if this is a worker being evaluated
  67. lib - The path to the library archive file, if this is a library being evaluated
  68. resources - The path to the resource pack or resource ball, if resources exist for this bin_type
  69. :param task_gen: the task generator instance
  70. :return: None
  71. """
  72. app, worker, lib, resources = (getattr(task_gen, attr, None)
  73. for attr in ('app', 'worker', 'lib', 'resources'))
  74. max_resources = task_gen.env.PLATFORM["MAX_RESOURCES_SIZE"]
  75. max_resources_appstore = task_gen.env.PLATFORM["MAX_RESOURCES_SIZE_APPSTORE"]
  76. app_max_ram = task_gen.env.PLATFORM["MAX_APP_MEMORY_SIZE"] if app else None
  77. worker_max_ram = task_gen.env.PLATFORM["MAX_WORKER_MEMORY_SIZE"] if worker else None
  78. if app:
  79. app_task = task_gen.create_task('memory_usage_report',
  80. [task_gen.to_nodes(app)[0],
  81. task_gen.to_nodes(resources)[0]])
  82. app_task.max_sizes = (app_max_ram, max_resources, max_resources_appstore)
  83. app_task.bin_type = 'app'
  84. if worker:
  85. worker_task = task_gen.create_task('memory_usage_report',
  86. task_gen.to_nodes(worker)[0])
  87. worker_task.max_sizes = (worker_max_ram, None, None)
  88. worker_task.bin_type = 'worker'
  89. if lib:
  90. lib_task = task_gen.create_task('memory_usage_report',
  91. [task_gen.to_nodes(lib)[0],
  92. task_gen.to_nodes(resources)[0]])
  93. lib_task.max_sizes = (None, None, None)
  94. lib_task.bin_type = 'lib'
  95. if getattr(task_gen, 'bin_type', None) == 'rocky':
  96. rocky_task = task_gen.create_task('memory_usage_report', task_gen.env.JS_RESO)
  97. rocky_task.bin_type = 'rocky'
  98. rocky_task.vars = ['PLATFORM_NAME']