美文网首页
vnr研究记录(一)

vnr研究记录(一)

作者: name_s | 来源:发表于2019-08-22 21:36 被阅读0次

    编程小白的随笔记录开始啦
    先来讲讲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作为网络请求库

    翻译流程优化的第一步先记录到这里

    相关文章

      网友评论

          本文标题:vnr研究记录(一)

          本文链接:https://www.haomeiwen.com/subject/uvqnsctx.html