2016-10-14 8 views
10

이전 버전의 Python에서는 (어떤 것이 기억 나는지) 임의의 인턴 된 문자열에 gc.get_referrers을 호출하여 interned dict에 대한 참조를 얻은 다음 그 길이를 질의 할 수있었습니다.Python 2.7.5에서 인턴 된 문자열 수를 확인하는 방법은 무엇입니까?

하지만 더 이상 파이썬 2.7.5에서 작동하지 않습니다. gc.get_referrers(...)은 반환하는 목록에 interned dict를 더 이상 포함하지 않습니다.

Python 2.7.5에서 인턴 된 문자열의 수를 결정하는 다른 방법이 있습니까? 그렇다면 어떻게?

+2

왜 신경 씁니까? 저급 버전의 특정 해킹으로 무엇을하려합니까? 아, 그래, 2.7.12가 최신 버전 이니, 왜 3 살이 넘은 버전에서이 정도의 세부 사항이 필요한가요? 나는 적대적인 사람이되는 것을 의미하지는 않지만 이것이 왜 중요한지 짐작할 수는 없습니다. – cco

+1

(a) 파이썬 프로세스의 메모리 사용량을 이해하는 데 관심이 있기 때문에 관심이 있습니다. 이는 하나의 추가 데이터 요소입니다. (b) 파이썬 2.7.5에 관심이있다. 파이썬 2.7.12에서 그 대답이 같을 것으로 생각되지만, 우리 제품에 사용 된 버전이기 때문이다. – jchl

+0

답변 해 주셔서 감사합니다. 필자는 응용 프로그램의 (비 리터럴) 문자열이 항상 더 많은 결과를 가져 왔기 때문에'interned' dict의 크기를 조사하는 시간을 가져 본 적이 없었습니다. 그래서 나는 그 문자열 각각의 복사본을 하나만 가지고 있습니다. 나는 내 시간을 보냈다. 결과적으로, 나는 당신의 목표가 무엇인지 궁금해합니다. 당신이 요구하는 정보를 가지고 있다면 그것을 어떻게 사용할 것입니까? – cco

답변

2

일종의 정렬이 가능하지만 모든 옵션이 지저분하고 거의 쓸모가없는 부분까지주의해야하기 때문에 먼저 원하는지 여부를 고려해 봅시다.

문자열을 사용하면 수명이 연장되지 않습니다. 당신은 구속 영장에 대해 걱정할 필요가 없습니다, 당신이 필요없는 문자열이 가득. 따라서 string interning은 실제 메모리 문제가 될 것 같지 않으며, 얼마나 많은 문자열이 interned되어 있는지를 알면 꽤 쓸모가 없을 수도 있습니다.

그래도이 작업을 수행하려면 원하는 옵션을 선택하십시오.


올바른 방법은 아마도 파이썬의 빛이 약한 참조 지원 당신이 문자열에 약한 참조를 만들 수없는 것을 제외하고 ... 자신의 인턴 구현을 사용하는 것입니다. 즉,이 접근법을 시도하면 약한 참조 문자열 래퍼를 지나가거나 또는 인턴 된 문자열을 영원히 생생하게 유지할 수 있습니다. 두 옵션 모두 끔찍합니다.


실제로 묻는 정보를 인쇄하는 기능이 있지만 ... 또한 모든 것을 인턴으로 처리합니다. 그것의 존재는 구현 세부 사항이며 C API를 통해서만 액세스 할 수 있으므로 ctypes.pythonapi을 사용해야합니다.

import ctypes 

_Py_ReleaseInternedStrings = ctypes.pythonapi._Py_ReleaseInternedStrings 

_Py_ReleaseInternedStrings.argtypes =() 
_Py_ReleaseInternedStrings.restype = None 

_Py_ReleaseInternedStrings() 

출력 :

releasing 3461 interned strings 
total size of all interned strings: 33685/0 mortal/immortal 

나열된 전체 크기는 문자열의 길이의 합이다, 그래서 그들은 객체 헤더는 null 터미네이터가 포함되어 있지 않습니다.


얼마나 많은 인원 문자열이 있는지 확인하려고 할 때마다 모든 인턴 문자열을 해제해야하는 것에 대해 행복하지 않을 수 있습니다. 불행하게도, 파이썬은 C API 나 GC 훅을 통해서도 내부 딕셔너리를 노출하지 않는다. 그 밖의 무엇을 시도 할 수 있습니까? 글쎄, 심지어 미친 옵션으로 이동, 거기에 디버거가 있습니다. 무인 모드에서 GDB 프로세스를 시작하고 errnomap에서 얻을 수있는 조건부 중단 점을 사용하여 crazy hack을 게시 ecatmur

interned에 매우 비슷한 딕셔너리는 액세스하려는 DICT. 대신 interned dict에 액세스 할 수 있습니다. 휴대가 매우 어려우며 유지 관리가 매우 어려울 것입니다.


디버거를 시작하는 것은 끔찍한 옵션입니다. 그 밖의 무엇을 시도 할 수 있습니까? 자, 여러분은 언제나 파이썬의 커스텀 빌드를 구축 할 수 있습니다. , python.org에서 소스를 다운로드 Objects/stringobject.c

PyObject * 
AwfulHackToGetTheInternedDict(void) 
{ 
    if (interned == NULL) { 
     // No interned dict yet. 
     Py_RETURN_NONE; 
    } 
    Py_INCREF(interned); 
    return interned; 
} 

를 추가, 구축, 설치합니다. virtualenv를 사용하여 보통의 파이썬 인터프리터와 분리 해 두는 것이 좋습니다. 이 끔찍한 해킹으로 인내 한 모든 문자열의 명사를 얻기 위해서는

import ctypes 

AwfulHackToGetTheInternedDict = ctypes.pythonapi.AwfulHackToGetTheInternedDict 

AwfulHackToGetTheInternedDict.argtypes =() 
AwfulHackToGetTheInternedDict = ctypes.py_object 

interned = AwfulHackToGetTheInternedDict() 

을 얻을 수 있습니다.


그렇다면이 옵션은 내가 생각한 옵션이거나 적어도 생각한 옵션입니다. 또한 GC가 문자열을 추적 한 다음 GC를 통해 내부 구술을 볼 수 있도록 인턴을 시도했지만 문자열에 PyObject_GC_Track을 호출하면 치명적인 오류가 발생하여 작동하지 않습니다.

+0

매우 포괄적 인 답변을 주셔서 감사합니다. – jchl

0

실제적인 대답은보다 강력한 메모리 프로파일 링 솔루션을 사용하는 것입니다.

pypi의 무료 memory_profiler 옵션과 같이 몇 가지 옵션이 있습니다.