Sys.getsizeof: примеры (PYTHON)

Анализ размера объектов в Python с помощью sys.getsizeof
Раздел: Системные функции, Память
sys.getsizeof(object: any, default: int): int

Описание функции sys.getsizeof

Функция sys.getsizeof() из модуля sys в Python предназначена для получения размера объекта в байтах. Её основное применение - анализ использования памяти и оптимизация, когда требуется понимать, сколько памяти занимает конкретная структура данных. Это бывает полезно при работе с большими объемами информации, например, в сферах анализа данных, веб-скрапинга или разработки высоконагруженных приложений.

Аргументы функции:

  • object (обязательный): Любой объект Python, размер которого необходимо определить.
  • default (необязательный): Значение, возвращаемое функцией, если объект не поддерживает определение размера. Если этот параметр не задан, в такой ситуации возникает исключение TypeError.

Возвращаемое значение:

Целое число (int), представляющее размер переданного объекта в байтах. Важно помнить, что возвращаемый размер включает только память, непосредственно занятую самим объектом, и не учитывает память объектов, на которые он может ссылаться (например, элементы внутри списка или словаря).

Простые примеры использования

Определение размера для различных базовых типов данных.

Пример 1: Числа и строки

import sys

print(sys.getsizeof(5))
print(sys.getsizeof(3.14))
print(sys.getsizeof('a'))
print(sys.getsizeof('строка'))
28
24
50
104

Пример 2: Коллекции

import sys

empty_list = []
small_list = [1, 2, 3]
print(sys.getsizeof(empty_list))
print(sys.getsizeof(small_list))

empty_dict = {}
print(sys.getsizeof(empty_dict))
56
88
64

Пример 3: Использование параметра default

import sys

# Попытка получить размер объекта, не поддерживающего эту операцию
class MyClass:
    pass

obj = MyClass()
# Без default возникнет ошибка
# size = sys.getsizeof(obj, default='Неизмеримо')
# С default
size = sys.getsizeof(obj, default='Размер не поддерживается')
print(size)
Размер не поддерживается

Похожие функции в Python

В Python существуют другие инструменты для оценки использования памяти.

1. Метод объекта __sizeof__()

Функция sys.getsizeof() вызывает именно этот специальный метод. Его можно вызвать напрямую, но это не рекомендуется, так как sys.getsizeof() добавляет обработку сборщика мусора. Используется редко в пользовательском коде.

x = [1, 2, 3]
print(x.__sizeof__())
88

2. Модуль pympler.asizeof или pympler.asizeof.asizeof

Функция asizeof() из сторонней библиотеки Pympler рассчитывает рекурсивный размер объекта, включая все вложенные объекты. Это кардинальное отличие от sys.getsizeof. Предпочтительнее для точного анализа общего потребления памяти сложной структурой.

# Требует установки: pip install pympler
from pympler import asizeof

list_of_lists = [[1, 2], [3, 4, 5]]
print('sys.getsizeof:', sys.getsizeof(list_of_lists))
print('asizeof:', asizeof.asizeof(list_of_lists))
sys.getsizeof: 80
asizeof: 504

Когда что использовать: sys.getsizeof применяют для быстрой оценки размера отдельного объекта. Для получения полного размера сложного объекта со всем содержимым лучше использовать pympler.asizeof.

Альтернативы в других языках программирования

Аналогичная функциональность в разных языках реализована с особенностями.

JavaScript

Прямого аналога нет. Можно приблизительно оценить через сериализацию в JSON строку, но это неточно. В Node.js есть process.memoryUsage() для общей памяти.

// Неточная оценка для строки
let str = 'test';
let size = new TextEncoder().encode(str).length;
console.log(size); // Байты в UTF-8
4

Java

Используют инструментарий JVM (например, java.lang.instrument.Instrumentation), но он сложен для прямого вызова. Нет встроенной простой функции.

// Пример с использованием Instrumentation (упрощенно)
// Требует запуска с javaagent
// Runtime.getRuntime().totalMemory() - свободная память даёт общую картину.

PHP

Функция memory_get_usage() возвращает объем памяти, выделенный скрипту, а не размер конкретной переменной.

$start = memory_get_usage();
$array = range(1, 1000);
$end = memory_get_usage();
echo 'Приблизительно: ' . ($end - $start) . ' байт';
Приблизительно: 52840 байт

C#

Метод GC.GetTotalMemory() для общей памяти. Для объекта используется System.Runtime.InteropServices.Marshal.SizeOf(), но только для неуправляемых типов или структур.

// Для структуры (значимый тип)
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
struct Point { public int X; public int Y; }
int size = Marshal.SizeOf(typeof(Point)); // 8 байт

Golang

Пакет unsafe с функцией Sizeof(), но она работает аналогично C, определяя размер типа, а не конкретного значения или сложной структуры данных с динамическими полями.

package main
import (
    "fmt"
    "unsafe"
)
func main() {
    var x int64 = 10
    fmt.Println(unsafe.Sizeof(x)) // Размер типа int64
}
8

Основное отличие Python - наличие в стандартной библиотеке простой функции для любого объекта, хотя и с ограничением на вложенность.

Типичные ошибки и недоразумения

1. Ожидание рекурсивного подсчета размера

Самая частая ошибка - предположение, что sys.getsizeof(list) вернет размер списка вместе со всеми его элементами.

import sys

list_of_numbers = [1, 2, 3, 4, 5]
print(sys.getsizeof(list_of_numbers))
# Ожидание: размер 5 чисел. Реальность: размер только объекта-контейнера списка.
104

2. Попытка измерить размер бесконечного генератора

Генератор как объект имеет размер, но это не размер всех генерируемых им данных, которые потенциально бесконечны.

import sys
gen = (i for i in range(1000000))
print(sys.getsizeof(gen))  # Размер объекта-генератора
112

3. Забывание импортировать модуль sys

# NameError: name 'sys' is not defined
print(getsizeof([]))
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'getsizeof' is not defined

4. Сравнение размеров разных типов без контекста

Размер целого числа (28 байт) больше, чем размер булева значения (28 байт), что кажется нелогичным. Это накладные расходы CPython на хранение любого объекта.

Изменения в последних версиях Python

Функция sys.getsizeof() появилась в Python 2.6. С тех пор её интерфейс и базовое поведение оставались стабильными. В Python 3.x она работает аналогично. Однако внутренняя реализация может меняться от версии к версии CPython, что приводит к разному базовому размеру для одних и тех же типов объектов из-за оптимизаций в структурах данных интерпретатора. Например, размер пустого списка или словаря может незначительно отличаться между минорными версиями Python 3. Это не изменение функции, а изменение объектов. Рекомендуется не полагаться на конкретные числовые значения, а использовать функцию для сравнительного анализа в рамках одной версии интерпретатора.

Расширенные и специальные примеры

1. Сравнение эффективности структур данных

Пример python
import sys

# Кортеж vs Список
tuple_data = (1, 2, 3, 4, 5)
list_data = [1, 2, 3, 4, 5]
print(f'Кортеж: {sys.getsizeof(tuple_data)}')
print(f'Список: {sys.getsizeof(list_data)}')
# Кортеж часто занимает меньше памяти, так как он неизменяем.
Кортеж: 80
Список: 104

2. Влияние длины строки на размер

Пример python
import sys

for length in [0, 1, 10, 100]:
    s = 'x' * length
    print(f'Длина {length}: {sys.getsizeof(s)} байт')
Длина 0: 49 байт
Длина 1: 50 байт
Длина 10: 59 байт
Длина 100: 149 байт

3. Размер объекта класса и его экземпляра

Пример python
import sys

class SimpleClass:
    def __init__(self, value):
        self.value = value

obj = SimpleClass(42)
print(f'Размер экземпляра: {sys.getsizeof(obj)}')
print(f'Размер класса: {sys.getsizeof(SimpleClass)}')
# Размер экземпляра - это размер служебного объекта, атрибуты - отдельные объекты.
Размер экземпляра: 56
Размер класса: 1056

4. Использование для отслеживания утечек памяти (шаблон)

Пример python
import sys
import tracemalloc  # Более современный и надежный инструмент

# Но для демонстрации с getsizeof:
def check_memory_growth(data_storage):
    baseline = sys.getsizeof(data_storage)
    # ... выполнение операций ...
    data_storage.append('new_data' * 100)
    after = sys.getsizeof(data_storage)
    print(f'Рост памяти контейнера: {after - baseline} байт')

storage = []
check_memory_growth(storage)
Рост памяти контейнера: 32 байт

5. Определение размера numpy массива

Пример python
import sys
import numpy as np

arr = np.zeros((10, 10), dtype=np.float64)
print(f'sys.getsizeof (объект ndarray): {sys.getsizeof(arr)}')
print(f'nbytes (только данные): {arr.nbytes}')
# sys.getsizeof дает размер объекта Python-обертки, а nbytes - размер буфера данных.
sys.getsizeof (объект ndarray): 176
nbytes (только данные): 800

питон sys.getsizeof function comments

En
Sys.getsizeof Get object memory size