2016-10-14 8 views
10

Pythonの以前のバージョン(私は覚えていません)では、interned dictへの参照を取得するために、任意の内部文字列のgc.get_referrersを呼び出すことができました。Python 2.7.5でインターンされた文字列の数を調べる方法は?

これはPython 2.7.5では動作しなくなりました。gc.get_referrers(...)は、それが返すリストにinterned dictを含まなくなりました。

Python 2.7.5では、インターンされた文字列の数を調べる方法はありますか?もしそうなら、どうですか?

+2

なぜ気になりますか?このような低レベルのバージョン固有のハックで何を達成しようとしていますか?ああ、2.7.12は現在のバージョンなので、3歳以上のリリースでこのような詳細レベルが必要なのはなぜですか?私は敵対的であるということを意味するわけではありませんが、なぜこれが*重要であるかを知ることはできません。 – cco

+1

(a)Pythonプロセスのメモリ使用量を理解することに興味があり、これが追加のデータポイントの1つです。 (b)私はPython 2.7.5に興味があります。私たちの製品で使用しているバージョンだからですが、答えはPython 2.7.12でも同じだと思われます。 – jchl

+0

答えをありがとう。私は、アプリケーション内の(リテラルではない)文字列が常により重大な影響を与えているので、これらの文字列のそれぞれのコピーを1つしか持たないことを保証しているので、 'interned' dictのサイズを調査する時間は一度もありませんでした。私は自分の時間を過ごしました。結果として、私はあなたの目標が何であるかについてはまだ興味があります。あなたが求めている情報を持っているなら、それをどのように使うのでしょうか? – cco

答えて

2

あなたはこれを並べ替えることができますが、すべてのオプションは面倒で使い勝手の悪いところまで注意書きでいっぱいですので、まずは本当にしたいかどうかを考えましょう。

文字列を使用しても、その有効期間は延長されません。あなたが必要としない弦がいっぱい、永遠に成長している拘束された辞表について心配する必要はありません。したがって、文字列インターンは実際のメモリ上の問題になることはまずありません。また、いくつの文字列がインターンされているかを知ることはかなり役に立たないかもしれません。

これをやりたい場合は、オプションを選択してみましょう。


右の方法は、おそらく、Pythonの低迷弱参照のサポートは、あなたが文字列への弱参照を作成することはできませんことを除いて...独自のインターンの実装を使用することです。これは、この方法を試してみると、弱参照可能な文字列ラッパーを回すか、または文字列を永遠に生かすことができないということです。どちらのオプションもひどいです。


実際には、あなたが尋ねている情報を印刷する機能がありますが、すべての機能を無効にします。その存在は実装の詳細であり、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 

記載されている合計サイズは、文字列の長さの和であるので、それらは、オブジェクトヘッダ又はヌルターミネータを含みません。


あなたがいくつあったのかを確認するたびに、すべての拘束された文字列を解放しなければならないのはおそらく幸いです。残念ながら、Pythonは、C APIやGCフックを介しても、内部のdictを公開していません。他に何を試すことができますか?さて、よりクレイジーなオプションに移動すると、デバッガがあります。

ecatmurは、crazy hackは無人モードでGDBのプロセスを起動してerrnomapで取得するために、条件付きブレークポイントを使用して、アクセスしたいinterned dictのと非常に似て辞書を掲載しました。これは代わりにinterned dictにアクセスするように適合させることができます。非常に持ち運びが難しく、メンテナンスが非常に難しいでしょう。


デバッガの起動もひどいオプションです。他に何を試すことができますか?まあ、あなたはいつもPythonのカスタムビルドを構築することができます。 python.orgからソースをダウンロードし、構築し、Objects/stringobject.c

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

を追加し、インストールします。おそらくvirtualenvを使って普通のPythonインタプリタと別のものにしておきたいでしょう。このひどいハックを実行すると、すべての拘束された文字列のdictを得るために

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オプションなど、いくつかのオプションがあります。

関連する問題