编程小白的随笔记录开始啦
先来讲讲vnr的翻译速度问题,由于篇幅原因,本章先讲translate()函数调用形式和优化
首先上一个vnr的翻译函数调用栈:
#输出函数栈
import inspect
for ins in inspect.stack():
print 'Line = ' + str(ins[2]) + ', Chunk = ' + ins[4][0] + ', Method = ' + ins[3] + ', Path = ' + ins[1]
#函数栈输出结果
Line = 152, Chunk = for ins in inspect.stack():
, Method = translate, Path = py/apps/reader\../../../py/libs\baidu\baidufanyi.py
Line = 409, Chunk = ret = skthreads.runsync(task, abortSignal=self.abortSignal) if async and self.asyncSupported else task()
, Method = _translateTransaction, Path = py/apps/reader\../../../py/apps/reader/managers\_trman.py
Line = 493, Chunk = text = self._cache.get(text) or self._translateTransaction(text, tr, to, fr, async, keepsNewLine)
, Method = _splitTranslate, Path = py/apps/reader\../../../py/apps/reader/managers\_trman.py
Line = 580, Chunk = l = split(text, tr, to, fr, async, keepsNewLine)
, Method = _translate, Path = py/apps/reader\../../../py/apps/reader/managers\_trman.py
Line = 2346, Chunk = to, fr, async, keepsNewLine, align=align)
, Method = translate, Path = py/apps/reader\../../../py/apps/reader/managers\_trman.py
Line = 339, Chunk = r = tr(text, align=align, **kwargs)
, Method = translateAndApply, Path = py/apps/reader\../../../py/apps/reader/managers\trman.py
Line = 78, Chunk = return super(Application, self).notify(receiver, event)
, Method = notify, Path = py/apps/reader\app.py
Line = 78, Chunk = return super(Application, self).notify(receiver, event)
, Method = notify, Path = py/apps/reader\app.py
Line = 418, Chunk = returnCode = a.exec_()
, Method = main, Path = E:\shiyan\Visual Novel Reader\Library\Frameworks\Sakura\py\apps\reader\__main__.py
Line = 825, Chunk = ret = main()
, Method = <module>, Path = E:\shiyan\Visual Novel Reader\Library\Frameworks\Sakura\py\apps\reader\__main__.py
Line = 72, Chunk = exec code in run_globals
, Method = _run_code, Path = E:\shiyan\Visual Novel Reader\Library\Frameworks\Python\lib\runpy.py
Line = 174, Chunk = "__main__", fname, loader, pkg_name)
, Method = _run_module_as_main, Path = E:\shiyan\Visual Novel Reader\Library\Frameworks\Python\lib\runpy.py
从调用栈可以看出,在栈顶是我们的输出函数,往下是一个
ret = skthreads.runsync(task, abortSignal=self.abortSignal) if async and self.asyncSupported else task()
但显然在这语块中并没用出现我们的translate()函数,我们看看代码:
上面用了偏函数第一行的if判断是做字符串处理,我们后面再讲,我们看最后一行,是具体调用translate()函数进行翻译的地方,translate()在这是偏函数调用,所以先不管后边三元运算符是怎么判断的,我们直接进去看函数
runsync()函数一开头就有介绍:
Run in another thread, and then block and wait for return result
(在另一个线程中运行,然后阻塞并等待返回结果)
从翻译的结果返回就可以看的出来,说是在另一个线程中运行,但其实还是单例运行:
我们在翻译之前加一句时间输出:
dprint(time())输出结果为:
SKProfiler给我们提供了时间记录,很详细
我们来看看函数的调用顺序,若是并发操作,那么三个时间肯定要比翻译结果先输出
所以我们得出了拖慢翻译速度的原因:单例
试想,原本是一份文本,四个翻译,需要单例翻译四次,一次0.25秒,总和1秒
若是字符串里有4个空格类的字符,那么就要分成四份,四个翻译,单例翻译总和4*4=16次
也就是4秒的时间,拖慢了四倍,翻译质量也不见得能提高多少
上图的skevents.waitsignal()函数,实际上是堵塞了主线程,而不是新建的IO线程
但即使我们把这句注释,仍是单例运行
这里就是python2.7的锅了,pyqt和pyside里的QThread,也是受GIL影响的,不推荐在IO密集时使用多线程,因为会比单线程效率还要低(但在python3.4以上就能正常使用多线程)
所以在这,我们应该修改为真正的多线程并发请求
——————————————————————————————————————
—————————————————分割线——————————————————
——————————————————————————————————————
下面给出IO密集时,单线程与多线程的对比
代码对比
#计算1-1000000累加和
class MyThread1(threading.Thread):
def __init__(self):
super(MyThread1, self).__init__()
def run(self):
start = time.time()
i = 0
for ins in range(1000000):
i += ins
print (time.time() - start)
class MyThread2(threading.Thread):
def __init__(self):
super(MyThread2, self).__init__()
def run(self):
start = time.time()
i = 0
for ins in range(1000000):
i += ins
print (time.time() - start)
class MyThread3(threading.Thread):
def __init__(self):
super(MyThread3, self).__init__()
def run(self):
start = time.time()
i = 0
for ins in range(1000000):
i += ins
print (time.time() - start)
if __name__ == "__main__":
start = time.time()
t1 = MyThread1()
t2 = MyThread2()
t3 = MyThread3()
t1.start()
t2.start()
t3.start()
计算时间:
计算时间if __name__ == "__main__":
start = time.time()
for ip in range(3):
i = 0
for ins in range(1000000):
i += ins
print (time.time() - start)
计算时间:
计算时间IO密集时不推荐,但是IO等待时可以用多线程
例如time.sleep(),以及在网络请求等待时,都可以使用
s = u"高校一年生の桜庭理沙は平均的な少女。 ある日拾ったカードの力により魔法少女となり戦うお話"
class MyThread1(threading.Thread):
def __init__(self):
super(MyThread1, self).__init__()
def run(self):
for ins in range(6):
start = time.time()
print ('caiyun : ' + caiyunfanyi.translate(s))
print (time.time() - start)
class MyThread2(threading.Thread):
def __init__(self):
super(MyThread2, self).__init__()
def run(self):
for ins in range(6):
start = time.time()
print ('tengxun : ' + tengxunfanyi.translate(s))
print (time.time() - start)
class MyThread3(threading.Thread):
def __init__(self):
super(MyThread3, self).__init__()
def run(self):
for ins in range(6):
start = time.time()
print ('youdao : ' + youdaozhiyun.translate(s))
print (time.time() - start)
if __name__ == "__main__":
start = time.time()
t1 = MyThread1()
t2 = MyThread2()
t3 = MyThread3()
t1.start()
t2.start()
t3.start()
print (time.time() - start)
caiyun : 高中一年级的樱庭理沙是个普通的少女。 一个故事讲述了一个女巫和一个魔法女孩在一张卡片上战斗的故事
0.542000055313
youdao : 高中一年级的樱庭理沙是个普通少女。根据某天捡到的卡的力量成为魔法少女战斗的故事
0.593000173569
tengxun : 高中一年级的樱庭理沙是平均的少女。某天用捡到的卡片的力量成为魔法少女战斗的故事
0.634999990463
caiyun : 高中一年级的樱庭理沙是个普通的少女。 一个故事讲述了一个女巫和一个魔法女孩在一张卡片上战斗的故事
0.203000068665
youdao : 高中一年级的樱庭理沙是个普通少女。根据某天捡到的卡的力量成为魔法少女战斗的故事
0.228999853134
tengxun : 高中一年级的樱庭理沙是平均的少女。某天用捡到的卡片的力量成为魔法少女战斗的故事
0.303000211716
caiyun : 高中一年级的樱庭理沙是个普通的少女。 一个故事讲述了一个女巫和一个魔法女孩在一张卡片上战斗的故事
0.213999986649
youdao : 高中一年级的樱庭理沙是个普通少女。根据某天捡到的卡的力量成为魔法少女战斗的故事
0.230999946594
tengxun : 高中一年级的樱庭理沙是平均的少女。某天用捡到的卡片的力量成为魔法少女战斗的故事
0.131999969482
caiyun : 高中一年级的樱庭理沙是个普通的少女。 一个故事讲述了一个女巫和一个魔法女孩在一张卡片上战斗的故事
0.208999872208
tengxun : 高中一年级的樱庭理沙是平均的少女。某天用捡到的卡片的力量成为魔法少女战斗的故事
0.125
youdao : 高中一年级的樱庭理沙是个普通少女。根据某天捡到的卡的力量成为魔法少女战斗的故事
0.239000082016
tengxun : 高中一年级的樱庭理沙是平均的少女。某天用捡到的卡片的力量成为魔法少女战斗的故事
0.128000020981
caiyun : 高中一年级的樱庭理沙是个普通的少女。 一个故事讲述了一个女巫和一个魔法女孩在一张卡片上战斗的故事
0.203999996185
tengxun : 高中一年级的樱庭理沙是平均的少女。某天用捡到的卡片的力量成为魔法少女战斗的故事
0.138000011444
youdao : 高中一年级的樱庭理沙是个普通少女。根据某天捡到的卡的力量成为魔法少女战斗的故事
0.240000009537
caiyun : 高中一年级的樱庭理沙是个普通的少女。 一个故事讲述了一个女巫和一个魔法女孩在一张卡片上战斗的故事
0.203000068665
youdao : 高中一年级的樱庭理沙是个普通少女。根据某天捡到的卡的力量成为魔法少女战斗的故事
0.240999937057
第一个请求需要初始化,所以比较慢
从上面可以看出,在python2.7中,网络请求也可以进行并发操作、
但是不能使用requests作为网络请求库,requests是一个同步库,异步网上貌似都推荐aiohttp,但我查了查,aiohttp最低支持python3.4,python2.7明显不能用
所以只能另辟蹊径,使用urllib+urllib2作为网络请求库
翻译流程优化的第一步先记录到这里
网友评论