Python 정수 대상 실현 원리 상세 설명

정수 대상 은 Python 내부 에서 PyIntObject 구조 체 로 표시 합 니 다.

typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
PyObject_HEAD 매크로 에서 정의 하 는 두 속성 은 다음 과 같 습 니 다.

int ob_refcnt; 
struct _typeobject *ob_type;
이 두 속성 은 모든 Python 대상 의 고유 한 것 입 니 다.
  • ob_refcnt:대상 의 인용 수 는 Python 의 메모리 관리 체제 와 관련 이 있 으 며 인용 수 를 바탕 으로 하 는 쓰레기 수집 체 제 를 실현 합 니 다
  • ob_type:Python 대상 의 유형 정 보 를 설명 하 는 데 사 용 됩 니 다
  • 이 를 통 해 알 수 있 듯 이 PyIntObject 는 C 언어 에서 long 유형의 수 치 를 확장 하 는 것 입 니 다.성능 을 고려 하여 작은 정수 에 대해 Python 은 작은 정수 대상 지 small 을 사용 합 니 다.ints 는[-5,257)사이 의 정 수 를 캐 시 했 습 니 다.이 범위 안의 정 수 는 Python 시스템 에서 공 유 됩 니 다.
    
    #define NSMALLPOSINTS 257
    #define NSMALLNEGINTS 5
    static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

    이 범 위 를 초과 한 정 수 는 값 이 같 더 라 도 대상 이 꼭 같은 것 은 아니다.다음 과 같다.a 와 b 의 값 이 모두 10000 이지 만 같은 대상 이 아니 라 값 이 1 일 때 a 와 b 는 같은 대상 에 속한다.
    
    >>> a = 10000
    >>> b = 10000
    >>> print a is b
    False
    >>> a = 1
    >>> b = 1
    >>> print a is b
    True
    [-5,257)사 이 를 초과 한 다른 정수 에 대해 Python 역시 전문 적 인 버퍼 를 제공 하여 이른바 큰 정수 로 사용 할 수 있 도록 제공 하여 매번 사용 할 때마다 끊임없이 malloc 분배 메모리 가 가 져 오 는 효율 적 인 손실 을 피한다.이 메모리 공간 은 PyIntBlock 입 니 다.
    
    struct _intblock {
    struct _intblock *next;
    PyIntObject objects[N_INTOBJECTS];
    };
    typedef struct _intblock PyIntBlock;
    static PyIntBlock *block_list = NULL;
    static PyIntObject *free_list = NULL;
    이 메모리 블록(PyIntBlock)은 단 방향 링크 를 통 해 구성 되 어 있 으 며,표 두 는 Block 입 니 다.list,표 두 는 항상 새로 만 든 PyIntBlock 대상 을 가리 키 고 있 습 니 다.
    PyIntBlock 은 두 가지 속성 이 있 습 니 다:next,objects.next 포인터 가 다음 PyIntBlock 대상 을 가리 키 고 있 습 니 다.objects 는 PyIntObject 배열(최종 적 으로 단 방향 링크 로 바 뀔 것 입 니 다)입 니 다.캐 시 된 PyIntObjet 대상 을 저장 하 는 메모리 공간 입 니 다.
    free_list 단 방향 링크 는 모든 PyIntBlock 메모리 블록 에 남 은 메모리 입 니 다.모든 남 은 메모리 가 하나의 링크 를 통 해 구 성 된 장점 은 Python 이 새로운 메모리 가 필요 할 때 새로운 PyIntObject 대상 을 저장 할 때 freelist 필요 한 메모 리 를 빠르게 가 져 옵 니 다.

    정수 대상 을 만 들 때 작은 정수 범위 내 에 있 으 면 작은 정수 버퍼 에서 바로 돌아 갑 니 다.이 범위 내 에 있 지 않 으 면 큰 정수 버퍼 메모리 공간 을 엽 니 다.
    
    [intobject.c]
    PyObject* PyInt_FromLong(long ival)
    {
    register PyIntObject *v; 
    #if NSMALLNEGINTS + NSMALLPOSINTS > 0
    //[1] :          
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
    v = small_ints[ival + NSMALLNEGINTS];
    Py_INCREF(v);
    return (PyObject *) v;
    }
    #endif
    //[2] :                
    if (free_list == NULL) {
    if ((free_list = fill_free_list()) == NULL)
    return NULL;
    }
    //[3] : (inline)  PyObject_New   
    v = free_list;
    free_list = (PyIntObject *)v->ob_type;
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
    }
    fill_free_list 는 큰 정수 버퍼 메모리 공간 을 만 드 는 논리 입 니 다.이 함 수 는 free 를 되 돌려 줍 니 다.list 링크,정수 대상 ival 생 성 성공 후 freelist 헤더 가 v->ob 를 가리 키 고 있 습 니 다.type,ob_type 은 모든 Python 대상 에서 형식 정 보 를 표시 하 는 필드 가 아 닙 니까?왜 여기 서 연결 지침 으로 하나 요?이것 은 Python 이 성능 과 코드 의 우아 함 사이 에서 중용의 도 를 취하 고 이름 의 남용 으로 유형 안전 에 대한 견 지 를 포기 한 것 이다.다음 PyIntObject 를 가리 키 는 지침 으로 이해 하면 됩 니 다.
    
    [intobject.c]
    static PyIntObject* fill_free_list(void)
    {
    PyIntObject *p, *q;
    //      sizeof(PyIntBlock)     
    // block list         PyIntBlock
    p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
    ((PyIntBlock *)p)->next = block_list;
    block_list = (PyIntBlock *)p;
    //: PyIntBlock  PyIntObject  (objects)       
    p = &((PyIntBlock *)p)->objects[0];
    q = p + N_INTOBJECTS;
    while (--q > p)
    // ob_type          PyIntObject。
    q->ob_type = (struct _typeobject *)(q-1);
    q->ob_type = NULL;
    return p + N_INTOBJECTS - 1;
    }
    서로 다른 PyIntBlock 의 남 은 메모리 가 어떻게 연결 되 어 free 를 구성 하 는 지리스트 는 요?이 비밀 은 정수 대상 쓰레기 회수 시 PyIntObject 대상 tpdealloc 작업 중 볼 수 있 는 것:
    
    [intobject.c]
    static void int_dealloc(PyIntObject *v)
    {
    if (PyInt_CheckExact(v)) {
    v->ob_type = (struct _typeobject *)free_list;
    free_list = v;
    }
    else
    v->ob_type->tp_free((PyObject *)v);
    }
    원래 PyIntObject 대상 이 소각 되 었 을 때 사용 하 는 메모리 가 방출 되 지 않 고 Python 에 의 해 계속 사용 되 어 freelist 헤더 가 삭 제 될 대상 을 가리 키 고 있 습 니 다.
    총결산
    파 이 썬 의 int 대상 은 c 언어 에서 long 형식 수치의 확장 입 니 다
  • 작은 정수 대상[-5,257]은 python 에서 공유 합 니 다
  • 4.567917.정수 대상 은 모두 버퍼 에서 얻 은 것 이다
  • 정수 대상 을 회수 할 때 메모리 가 시스템 에 반환 되 지 않 고 대상 의 obtype 지향 freelist,새로 만 든 정수 대상 사용
  • 이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기