diff --git a/app/helper/memory.py b/app/helper/memory.py index fac3b85c..279801be 100644 --- a/app/helper/memory.py +++ b/app/helper/memory.py @@ -130,10 +130,14 @@ class MemoryHelper(metaclass=Singleton): try: class_objects = self._get_class_memory_usage() - for i, class_info in enumerate(class_objects[:50], 1): # 只显示前50个类 - f.write(f"{i:3d}. {class_info['name']:<50} {class_info['size_mb']:>8.2f} MB ({class_info['count']} 个实例)\n") + if class_objects: + for i, class_info in enumerate(class_objects[:50], 1): # 只显示前50个类 + f.write(f"{i:3d}. {class_info['name']:<50} {class_info['size_mb']:>8.2f} MB ({class_info['count']} 个实例)\n") + else: + f.write("未找到有效的类实例信息\n") except Exception as e: - f.write(f"获取类对象信息失败: {e}\n") + logger.error(f"获取类实例信息失败: {e}") + f.write(f"获取类实例信息失败: {e}\n") # 添加详细的变量内存使用情况 f.write("\n" + "=" * 80 + "\n") @@ -142,9 +146,13 @@ class MemoryHelper(metaclass=Singleton): try: large_variables = self._get_large_variables(100) - for i, var_info in enumerate(large_variables, 1): - f.write(f"{i:3d}. {var_info['name']:<30} {var_info['type']:<15} {var_info['size_mb']:>8.2f} MB\n") + if large_variables: + for i, var_info in enumerate(large_variables, 1): + f.write(f"{i:3d}. {var_info['name']:<30} {var_info['type']:<15} {var_info['size_mb']:>8.2f} MB\n") + else: + f.write("未找到大内存变量\n") except Exception as e: + logger.error(f"获取大内存变量信息失败: {e}") f.write(f"获取变量信息失败: {e}\n") logger.info(f"内存快照已保存: {snapshot_file}, 当前内存使用: {memory_usage / 1024 / 1024:.2f} MB") @@ -176,26 +184,40 @@ class MemoryHelper(metaclass=Singleton): 获取所有类实例的内存使用情况,按内存大小排序 """ class_info = {} + processed_count = 0 + error_count = 0 # 获取所有对象 all_objects = muppy.get_objects() + logger.debug(f"开始分析 {len(all_objects)} 个对象的类实例内存使用情况") for obj in all_objects: - # 跳过类对象本身,统计类的实例 - if isinstance(obj, type): - continue - - # 获取对象的类名 - obj_class = type(obj) - class_name = f"{obj_class.__module__}.{obj_class.__name__}" if hasattr(obj_class, '__module__') else obj_class.__name__ - try: + # 跳过类对象本身,统计类的实例 + if isinstance(obj, type): + continue + + # 获取对象的类名 - 这里可能会出错 + obj_class = type(obj) + + # 安全地获取类名 + try: + if hasattr(obj_class, '__module__') and hasattr(obj_class, '__name__'): + class_name = f"{obj_class.__module__}.{obj_class.__name__}" + else: + class_name = str(obj_class) + except Exception as e: + # 如果获取类名失败,使用简单的类型描述 + class_name = f"" + logger.debug(f"获取类名失败: {e}") + # 计算对象的内存使用 size_bytes = asizeof.asizeof(obj) if size_bytes < 100: # 跳过太小的对象 continue size_mb = size_bytes / 1024 / 1024 + processed_count += 1 if class_name in class_info: class_info[class_name]['size_mb'] += size_mb @@ -206,10 +228,16 @@ class MemoryHelper(metaclass=Singleton): 'size_mb': size_mb, 'count': 1 } - except (OSError, ImportError, AttributeError, TypeError): - # 跳过有问题的对象 + + except Exception as e: + # 捕获所有可能的异常,包括SQLAlchemy、ORM等框架的异常 + error_count += 1 + if error_count <= 5: # 只记录前5个错误,避免日志过多 + logger.debug(f"分析对象时出错: {e}") continue + logger.debug(f"类实例分析完成: 处理了 {processed_count} 个对象, 遇到 {error_count} 个错误") + # 按内存大小排序 sorted_classes = sorted(class_info.values(), key=lambda x: x['size_mb'], reverse=True) return sorted_classes