Skip to content

Commit 046cc90

Browse files
committed
https://github.com/kbengine/kbengine/issues/166
对c++中产生的(new)py对象进行跟踪 kbengine.debugKBETracing, 参考API手册
1 parent ac8835e commit 046cc90

File tree

13 files changed

+140
-17
lines changed

13 files changed

+140
-17
lines changed

docs/api/kbengine_api.chm

1.11 KB
Binary file not shown.

kbe/src/lib/client_lib/entity.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
2626
#include "network/channel.hpp"
2727
#include "network/bundle.hpp"
2828
#include "network/fixed_messages.hpp"
29+
#include "pyscript/py_gc.hpp"
2930

3031
#include "../../../server/baseapp/baseapp_interface.hpp"
3132
#include "../../../server/cellapp/cellapp_interface.hpp"
@@ -71,13 +72,15 @@ enterword_(false),
7172
isOnGound_(true)
7273
{
7374
ENTITY_INIT_PROPERTYS(Entity);
75+
script::PyGC::incTracing("Entity");
7476
}
7577

7678
//-------------------------------------------------------------------------------------
7779
Entity::~Entity()
7880
{
7981
enterword_ = false;
8082
ENTITY_DECONSTRUCTION(Entity);
83+
script::PyGC::decTracing("Entity");
8184
}
8285

8386
//-------------------------------------------------------------------------------------

kbe/src/lib/entitydef/entity_mailbox.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
2424
#include "helper/debug_helper.hpp"
2525
#include "network/channel.hpp"
2626
#include "pyscript/pickler.hpp"
27+
#include "pyscript/py_gc.hpp"
2728
#include "entitydef/method.hpp"
2829
#include "remote_entity_method.hpp"
2930
#include "entitydef/entitydef.hpp"
@@ -63,6 +64,8 @@ atIdx_(MAILBOXS::size_type(-1))
6364
{
6465
atIdx_ = EntityMailbox::mailboxs.size();
6566
EntityMailbox::mailboxs.push_back(this);
67+
68+
script::PyGC::incTracing("EntityMailbox");
6669
}
6770

6871
//-------------------------------------------------------------------------------------
@@ -82,6 +85,8 @@ EntityMailbox::~EntityMailbox()
8285
EntityMailbox::mailboxs[atIdx_] = pBack;
8386
atIdx_ = MAILBOXS::size_type(-1);
8487
EntityMailbox::mailboxs.pop_back();
88+
89+
script::PyGC::decTracing("EntityMailbox");
8590
}
8691

8792
//-------------------------------------------------------------------------------------

kbe/src/lib/entitydef/fixedarray.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ You should have received a copy of the GNU Lesser General Public License
1818
along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
1919
*/
2020

21-
2221
#include "fixedarray.hpp"
2322
#include "datatypes.hpp"
23+
#include "pyscript/py_gc.hpp"
2424

2525
namespace KBEngine{
2626

@@ -51,6 +51,8 @@ Sequence(getScriptType(), false)
5151
_dataType->incRef();
5252
initialize(strInitData);
5353

54+
script::PyGC::incTracing("FixedArray");
55+
5456
// DEBUG_MSG(fmt::format("FixedArray::FixedArray(): {:p}\n", this));
5557
}
5658

@@ -62,6 +64,8 @@ Sequence(getScriptType(), false)
6264
_dataType->incRef();
6365
initialize(pyInitData);
6466

67+
script::PyGC::incTracing("FixedArray");
68+
6569
// DEBUG_MSG(fmt::format("FixedArray::FixedArray(): {:p}\n", this));
6670
}
6771

@@ -73,6 +77,8 @@ Sequence(getScriptType(), false)
7377
_dataType->incRef();
7478
initialize("");
7579

80+
script::PyGC::incTracing("FixedArray");
81+
7682
// DEBUG_MSG(fmt::format("FixedArray::FixedArray(): {:p}\n", this));
7783
}
7884

@@ -81,6 +87,8 @@ FixedArray::~FixedArray()
8187
{
8288
_dataType->decRef();
8389

90+
script::PyGC::decTracing("FixedArray");
91+
8492
// DEBUG_MSG(fmt::format("FixedArray::~FixedArray(): {:p}\n", this));
8593
}
8694

kbe/src/lib/entitydef/fixeddict.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
2020

2121
#include "fixeddict.hpp"
2222
#include "datatypes.hpp"
23+
#include "pyscript/py_gc.hpp"
2324

2425
namespace KBEngine{
2526

@@ -71,6 +72,8 @@ Map(getScriptType(), false)
7172
_dataType->incRef();
7273
initialize(strDictInitData);
7374

75+
script::PyGC::incTracing("FixedDict");
76+
7477
// DEBUG_MSG(fmt::format("FixedDict::FixedDict(1): {:p}---{}\n", (void*)this,
7578
// wchar2char(PyUnicode_AsWideCharString(PyObject_Str(getDictObject()), NULL))));
7679
}
@@ -83,6 +86,8 @@ Map(getScriptType(), false)
8386
_dataType->incRef();
8487
initialize(pyDictInitData);
8588

89+
script::PyGC::incTracing("FixedDict");
90+
8691
// DEBUG_MSG(fmt::format("FixedDict::FixedDict(2): {:p}---{}\n", (void*)this,
8792
// wchar2char(PyUnicode_AsWideCharString(PyObject_Str(getDictObject()), NULL))));
8893
}
@@ -95,6 +100,8 @@ Map(getScriptType(), false)
95100
_dataType->incRef();
96101
initialize(streamInitData, isPersistentsStream);
97102

103+
script::PyGC::incTracing("FixedDict");
104+
98105
// DEBUG_MSG(fmt::format("FixedDict::FixedDict(3): {:p}---{}\n", (void*)this,
99106
// wchar2char(PyUnicode_AsWideCharString(PyObject_Str(getDictObject()), NULL))));
100107
}
@@ -107,6 +114,8 @@ Map(getScriptType(), false)
107114
_dataType->incRef();
108115
initialize("");
109116

117+
script::PyGC::incTracing("FixedDict");
118+
110119
// DEBUG_MSG(fmt::format("FixedDict::FixedDict(4): {:p}---{}\n", (void*)this,
111120
// wchar2char(PyUnicode_AsWideCharString(PyObject_Str(getDictObject()), NULL))));
112121
}
@@ -116,6 +125,7 @@ Map(getScriptType(), false)
116125
FixedDict::~FixedDict()
117126
{
118127
_dataType->decRef();
128+
script::PyGC::decTracing("FixedDict");
119129

120130
// DEBUG_MSG(fmt::format("FixedDict::~FixedDict(): {:p}\n", (void*)this);
121131
}

kbe/src/lib/entitydef/method.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ PyObject* MethodDescription::createFromStream(MemoryStream* mstream)
197197

198198
// 设置一个调用者ID提供给脚本判断来源是否正确
199199
KBE_ASSERT(currCallerID_ > 0);
200-
PyTuple_SET_ITEM(&*pyArgsTuple, 0, PyLong_FromLong(currCallerID_));
200+
PyTuple_SET_ITEM(pyArgsTuple, 0, PyLong_FromLong(currCallerID_));
201201
}
202202
else
203203
pyArgsTuple = PyTuple_New(argSize);
@@ -212,7 +212,7 @@ PyObject* MethodDescription::createFromStream(MemoryStream* mstream)
212212
this->getName(), index, argTypes_[index]->getName()));
213213
}
214214

215-
PyTuple_SET_ITEM(&*pyArgsTuple, index + offset, pyitem);
215+
PyTuple_SET_ITEM(pyArgsTuple, index + offset, pyitem);
216216
}
217217

218218
return pyArgsTuple;

kbe/src/lib/pyscript/py_gc.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ You should have received a copy of the GNU Lesser General Public License
1818
along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
1919
*/
2020

21-
21+
#include "script.hpp"
2222
#include "py_gc.hpp"
23+
#include "scriptstdouterr.hpp"
24+
#include "pyattr_macro.hpp"
2325
#include "helper/profile.hpp"
2426

2527
namespace KBEngine{ namespace script {
2628

2729
PyObject* PyGC::collectMethod_ = NULL;
2830
PyObject* PyGC::set_debugMethod_ = NULL;
31+
KBEUnordered_map<std::string, int> PyGC::tracingCountMap_;
2932

3033
uint32 PyGC::DEBUG_STATS = 0;
3134
uint32 PyGC::DEBUG_COLLECTABLE = 0;
@@ -127,6 +130,8 @@ bool PyGC::initialize(void)
127130
flag = NULL;
128131
}
129132

133+
APPEND_SCRIPT_MODULE_METHOD(gcModule, debugTracing, __py_debugTracing, METH_VARARGS, 0);
134+
130135
Py_DECREF(gcModule);
131136
}
132137
else
@@ -187,6 +192,59 @@ void PyGC::set_debug(uint32 flsgs)
187192
}
188193
}
189194

195+
//-------------------------------------------------------------------------------------
196+
void PyGC::incTracing(std::string name)
197+
{
198+
KBEUnordered_map<std::string, int>::iterator iter = tracingCountMap_.find(name);
199+
if(iter == tracingCountMap_.end())
200+
{
201+
tracingCountMap_[name] = 0;
202+
iter = tracingCountMap_.find(name);
203+
}
204+
205+
iter->second = iter->second + 1;
206+
}
207+
208+
//-------------------------------------------------------------------------------------
209+
void PyGC::decTracing(std::string name)
210+
{
211+
KBEUnordered_map<std::string, int>::iterator iter = tracingCountMap_.find(name);
212+
if(iter == tracingCountMap_.end())
213+
{
214+
return;
215+
}
216+
217+
iter->second = iter->second - 1;
218+
KBE_ASSERT(iter->second >= 0);
219+
}
220+
221+
//-------------------------------------------------------------------------------------
222+
void PyGC::debugTracing(bool shuttingdown)
223+
{
224+
KBEUnordered_map<std::string, int>::iterator iter = tracingCountMap_.begin();
225+
for(; iter != tracingCountMap_.end(); iter++)
226+
{
227+
if(shuttingdown)
228+
{
229+
if(iter->second == 0)
230+
continue;
231+
232+
ERROR_MSG(fmt::format("PyGC::debugTracing(): {} : leaked({})", iter->first, iter->second));
233+
}
234+
else
235+
{
236+
Script::getSingleton().pyStdouterr()->pyPrint(fmt::format("PyGC::debugTracing(): {} : {}", iter->first, iter->second));
237+
}
238+
}
239+
}
240+
241+
//-------------------------------------------------------------------------------------
242+
PyObject* PyGC::__py_debugTracing(PyObject* self, PyObject* args)
243+
{
244+
debugTracing(false);
245+
S_Return;
246+
}
247+
190248
//-------------------------------------------------------------------------------------
191249

192250
}

kbe/src/lib/pyscript/py_gc.hpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,32 @@ class PyGC
5151
*/
5252
static void set_debug(uint32 flsgs);
5353

54+
/**
55+
增加计数
56+
*/
57+
static void incTracing(std::string name);
58+
59+
/**
60+
减少计数
61+
*/
62+
static void decTracing(std::string name);
63+
64+
/**
65+
debug追踪kbe封装的py对象计数
66+
*/
67+
static void debugTracing(bool shuttingdown = true);
68+
69+
/**
70+
脚本调用
71+
*/
72+
static PyObject* __py_debugTracing(PyObject* self, PyObject* args);
5473
private:
55-
static PyObject* collectMethod_; // cPicket.dumps方法指针
56-
static PyObject* set_debugMethod_; // cPicket.loads方法指针
74+
static PyObject* collectMethod_; // cPicket.dumps方法指针
75+
static PyObject* set_debugMethod_; // cPicket.loads方法指针
76+
77+
static bool isInit; // 是否已经被初始化
5778

58-
static bool isInit; // 是否已经被初始化
79+
static KBEUnordered_map<std::string, int> tracingCountMap_; // 追踪特定的对象计数器
5980
} ;
6081

6182
}

kbe/src/lib/pyscript/script.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
3535
#endif
3636

3737
namespace KBEngine{
38+
39+
KBE_SINGLETON_INIT(script::Script);
3840
namespace script{
3941

4042
#ifndef KBE_SINGLE_THREADED
@@ -43,11 +45,13 @@ static PyThreadState * s_pMainThreadState;
4345
static PyThreadState* s_defaultContext;
4446
#endif
4547

48+
//-------------------------------------------------------------------------------------
4649
static PyObject* __py_genUUID64(PyObject *self, void *closure)
4750
{
4851
return PyLong_FromUnsignedLongLong(genUUID64());
4952
}
5053

54+
//-------------------------------------------------------------------------------------
5155
PyObject * PyTuple_FromStringVector(const std::vector< std::string > & v)
5256
{
5357
int sz = v.size();

kbe/src/lib/pyscript/script.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ inline PyObject * PyTuple_FromIntVector<uint64>(const std::vector< uint64 > & v)
8888
return t;
8989
}
9090

91-
class Script
91+
class Script: public Singleton<Script>
9292
{
9393
public:
9494
Script();

kbe/src/lib/server/entity_app.hpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -459,31 +459,34 @@ bool EntityApp<E>::installPyModules()
459459

460460
// 注册创建entity的方法到py
461461
// 向脚本注册app发布状态
462-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), publish, __py_getAppPublish, METH_VARARGS, 0);
462+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), publish, __py_getAppPublish, METH_VARARGS, 0);
463463

464464
// 注册设置脚本输出类型
465-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), scriptLogType, __py_setScriptLogType, METH_VARARGS, 0);
465+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), scriptLogType, __py_setScriptLogType, METH_VARARGS, 0);
466466

467467
// 获得资源全路径
468-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), getResFullPath, __py_getResFullPath, METH_VARARGS, 0);
468+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), getResFullPath, __py_getResFullPath, METH_VARARGS, 0);
469469

470470
// 是否存在某个资源
471-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), hasRes, __py_hasRes, METH_VARARGS, 0);
471+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), hasRes, __py_hasRes, METH_VARARGS, 0);
472472

473473
// 打开一个文件
474-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), open, __py_kbeOpen, METH_VARARGS, 0);
474+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), open, __py_kbeOpen, METH_VARARGS, 0);
475475

476476
// 列出目录下所有文件
477-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), listPathRes, __py_listPathRes, METH_VARARGS, 0);
477+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), listPathRes, __py_listPathRes, METH_VARARGS, 0);
478478

479479
// 匹配相对路径获得全路径
480-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), matchPath, __py_matchPath, METH_VARARGS, 0);
480+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), matchPath, __py_matchPath, METH_VARARGS, 0);
481481

482482
// 获取watcher值
483-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), getWatcher, __py_getWatcher, METH_VARARGS, 0);
483+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), getWatcher, __py_getWatcher, METH_VARARGS, 0);
484484

485485
// 获取watcher目录
486-
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), getWatcherDir, __py_getWatcherDir, METH_VARARGS, 0);
486+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), getWatcherDir, __py_getWatcherDir, METH_VARARGS, 0);
487+
488+
// debug追踪kbe封装的py对象计数
489+
APPEND_SCRIPT_MODULE_METHOD(getScript().getModule(), debugTracing, script::PyGC::__py_debugTracing, METH_VARARGS, 0);
487490

488491
if(PyModule_AddIntConstant(this->getScript().getModule(), "LOG_TYPE_NORMAL", log4cxx::ScriptLevel::SCRIPT_INT))
489492
{
@@ -546,6 +549,8 @@ bool EntityApp<E>::uninstallPyModules()
546549
EntityGarbages<E>::uninstallScript();
547550
//Entity::uninstallScript();
548551
EntityDef::uninstallScript();
552+
553+
script::PyGC::debugTracing();
549554
return true;
550555
}
551556

0 commit comments

Comments
 (0)