Day 23 - 重覆呼叫shioaji.Shioaji()产生的记忆体问题

因为看到有人反应,重覆登出登入,会造成记忆体使用量增加,这实在是让人太好奇了,所以就想来实测一下。但因为反应问题的人也没有提供程序内容,所以只是自己猜可能的程序内容

测试程序及结果

测试程序范例:

import os, psutil, gc, time
import shioaji as sj
from dotenv import load_dotenv

load_dotenv('D:\\python\\shioaji\\.env') #读取.env中的环境变数

process = psutil.Process(os.getpid())
print(f'mem usage as start: {process.memory_info()[0]/float(2 ** 20)}kb')

for i in range(5):
    api = sj.Shioaji(simulation=True)
    print(f'({i})mem usage at api initial: {process.memory_info()[0]/float(2 ** 20)}kb')
    api.login(
        person_id='PAPIUSER01', 
        passwd='2222'
    )
    print(f'({i})mem usage at api.login: {process.memory_info()[0]/float(2 ** 20)}kb')
    api.logout()
    time.sleep(10) #登出後,等待10秒再进行登入,防止出错

del api
gc.collect()
print(f'mem usage after del api: {process.memory_info()[0]/float(2 ** 20)}kb')

上面用for in的方式重覆进行5次初始化、登入及登出动作,来测试是否有产生RAM使用量增加的情况,在测试时发现若登入的环境是测试环境,虽然RAM使用量有增加,但其实不明显。而上面这个范例,是用测试环境及帐号进行测试,若是正式环境,只需传入自己的帐号密码,并且在初始化时,不设定simulation=True即可。
测试结果如下(单位:KB):

程序点 windows&正式环境 windows&测试环境 ubuntu&正式环境 ubuntu&测试环境
start 33.98828125 33.84375 34.59765625 34.5
0-initial 38 37.89453125 37.98828125 37.84765625
0-login 126.1132813 39.3671875 72.94140625 39.03515625
1-initial 227.5351563 40.23828125 203.6210938 39.87109375
1-login 219.4492188 40.125
2-initial 409.7734375 41.18359375 225.5703125 40.3828125
2-login 471.53125 41.90234375 239.6914063 40.63671875
3-initial 591.7265625 42 264.2929688 40.63671875
3-login 642.1875 42.72265625 286.9375 40.890625
4-initial 775.7148438 42.84765625 328.703125 41.1484375
4-login 844.2929688 43.55859375 354.390625 41.40234375
del & gc 956.984375 42.75 494.125 41.52734375

由测试结果可以看到,的确这样的写法是会增加许多RAM的使用量,不过在Linux环境中,增加的量不像在Windows下那样夸张。而测试环境的部份,竟然差异不大,这可能要请开发团队看才能知道为何有这差异。

问题原因&解决方式

其实RAM使用量增加主要是因为重覆执行sj.Shioaji()进行初始化动作所造成,虽然执行login()後,RAM使用量也会增加,但并没有像执行sj.Shioaji()时增加那麽多。解决方式可分为下列2种:
1.sj.Shioaji()移至回圈或是function外层,避免重覆执行
2.在login时,传入fetch_contract=False,即不执行fetch_all_contract动作,预先抓所有的contract
我个人比较便好1,因为只需要将原本的程序做一点小调整即可。
第2种方式虽然也可以,但是Contract物件经常会被使用到,若指定fetch_contract=False,则无法透过api取得Contract内容,也就要考虑用object serialization先将Contract物件储存起来,要用的时候再做读取的动作。


<<:  [Day24]solidity合约内容讲解2

>>:  day23: currying

<Day6>你得先开个证券户

在做投资之前,首先最重要的事,当然就是得先去开一个证券户啦~~~ 什麽是证券户? 简而言之,一般我们...

Day 18 : 二分搜寻 Binary Search

生活上我们可能有遇过一些二分搜寻的例子。 例如以前如果有当过助教的经验,有时候我们在收学生作业时会作...

不只懂 Vue 语法:参赛初衷与文章方向

参赛初衷 今年的参赛题目是「不只懂语法:Vue.js 观念篇」。去年的这时候刚刚学 JavaScri...

Day30. Model 与关联 - preload, join, includes 一次厘清

今天我们会用部落格跟使用者的关系来讲解关联,首先先做设定,部落格跟使用者的关系为 使用者对应多个部落...

WFH 仪式感/ 场域转换新创 心得

<img src="https://miro.medium.com/max/700/0*4Pr...