Windows,知微
Windows 编程

Mysql 语法分析

千条语句大概在11毫秒左右,另外文法星号可以自动提取出来。比如创建数据库语句,定义好文法,可以自动提取出数据库名字。

微信截图_20200305163818.png


源码 支持Mysql注释符解析

function getMysql(j){function q(P){return"[object String]"==Object.prototype.toString.call(P)?P.toLowerCase():P}function w(){""!=B&&z.push(B),B=""}var y=j.replace(/--\s[\s\S]*|--\s[\s\S]*[\r\n|\n]|\/\*(.|[\r\n|\n])*\*\/|#[\s\S]*[\r\n|\n]|#[\s\S]*/i,""),z=[],A=[],B="",C=["'","\"",";"],D=[" ","\r\n","\n","\r"],E=[["create","database","*",[["\u6570\u636E\u5E93\u540D\u79F0"],1]],["use","*",[["\u6570\u636E\u5E93\u540D\u79F0"],2]],["drop","database","*",[["\u6570\u636E\u5E93\u540D\u79F0"],3]]];for(i=0;i<y.length;i++){var F=y.charAt(i);-1===C.indexOf(F)?-1===D.indexOf(F)?B+=F:w():(w(),z.push(F))}for(w(),E.sort(function(P,Q){return Q.length-P.length}),i=0;i<z.length;i++){var G=i;for(k=0;k<E.length;k++)if(z.length-i>=E[k].length-1){var H=E[k].length-1,I=0,J=[];for(n=0;n<E[k].length-1;n++)0==function(P,Q){return"*"==P&&"*"!=Q?0:"*"==P&&"*"==Q?-1:q(P)==q(Q)?0:-1}(E[k][n],z[i])&&(i++,I++),"*"==E[k][n]&&J.push(n);if(I==H){var K="",L=0,M=[];for(m=G;m<i;m++)-1!==J.indexOf(L)&&M.push(z[m]),K=K+z[m]+" ",L++;K=K.substring(0,K.length-1);var N=[E[k][E[k].length-1][1],K,M];A.push(N),i--}else i-=I}}return 0==A.length?j:A}
let res =getMysql("Create database ku1 #DWADWADAWJKHJK\r\n#DWADWADAWJKHJK\n-- DWADWADAWJKHJK Create database ku2");
console.log(res);


对某软件的编译分析

在Window上对它进行了行为分析。发现编译的时候主要是进行了3个操作。

1、检测配置文件语法

2、检测页面配置语法

3、执行代码编译脚本

测试发现前面2条可以省略,究其原因是因为它也是使用的第三方插件实现的检测,不是它的编译主要逻辑,所以需求上可以去掉。主要是执行代码编译脚本。

发现脚本后直接执行了一下,发现报错。原因是没有对进程信息进行填充。所以手动填充了一下,这里没有看出来它是怎么进行进程填充的,后续有时间再分析吧(注1)。修改编译脚本测试结果如下。

1、直接运行

WechatIMG33.png

2、编译压缩

WechatIMG44.png

未完待续:关注微信小程序获取访问密码 (文章ID:1700)或小程序在线阅读

redis 死循环为什么CPU很低?

redis的事件循环代码

void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
        aeProcessEvents(eventLoop, AE_ALL_EVENTS);
    }
}

让我不理解的是,这是一个死循环,但是CPU占用很低。所以就看看代码学习一下。由于我只需要时间事件(processTimeEvents)。所以我将aeProcessEvents删掉了一些代码,只保留时间事件。然后CPU暴增。

微信图片_20190918182652.png

可以看到CPU从0.0涨到了90.3于是往上回溯代码。最终发现其中一个比较关键的:aeApiPoll函数。

网上有一段话:aeProcessEvents 都会先 计算最近的时间事件发生所需要等待的时间 ,然后调用 aeApiPoll 方法在这段时间中等待事件的发生,在这段时间中如果发生了文件事件,就会优先处理文件事件,否则就会一直等待,直到最近的时间事件需要触发。跟进去会发现是一个select,它是用来等待文件描述词(普通文件、终端、伪终端、管道、FIFO、套接字及其他类型的字符型)这些的改变事件。

在传递的时候会将tvp传入进来,tvp是最近发生的时间,也被设置成了select的过期时间,所以如果没有发生文件事件,然后又select又过期了,自动会走如下代码

    if (retval > 0) {
        for (j = 0; j <= eventLoop->maxfd; j++) {
            int mask = 0;
            aeFileEvent *fe = &eventLoop->events[j];
            if (fe->mask == AE_NONE) continue;
            if (fe->mask & AE_READABLE && FD_ISSET(j,&state->_rfds))
                mask |= AE_READABLE;
            if (fe->mask & AE_WRITABLE && FD_ISSET(j,&state->_wfds))
                mask |= AE_WRITABLE;
            eventLoop->fired[numevents].fd = j;
            eventLoop->fired[numevents].mask = mask;
            numevents++;
        }
    }

所以这里的等待就会造成while的一些时间片的释放,然后会降低CPU。

知微:Switch与If误区

最新想写一些关于编程细致末梢的文章,叫做知微。看文章需要有一定的逆向基础与汇编知识。如果不会的话,不建议阅读。以免给你灌输了错误的思想,而你无法发现。知微相关的文章不保证正确性,只是对发现或者知识点的一种证明。

大概很久以前,对于switch和if。某视频里面说了一句,switch比if要快。于是这个概念就一直记忆到现在。每次碰到这个问题,我基本上都会告诉别人switch比if快。但是为什么快?怎么快的?估计很大一部分人就不知道了。或者说没有听过它俩谁快的说法,代码的编写更因该关注一些细节。毕竟大的方向,框架,算法逻辑什么的,你不一定会写。小的地方你又不了解。那你只是个Copy+C,Copy+V的选手,也无法进步。

同样的代码有两个版本:release 和 debug。这里拿debug来说,为什么拿debug来说,这有涉及到这两个版本的优化问题。可自行查阅相关编译器、解释器的说明。注意它俩并非是名称上的不同。

来看一下两个判断代码:

switch.png


if.png

然后来看一下汇编代码

debug-switch.png

debug-if.png

汇编代码关键的地方我已经备注了,可以发现if语句是每条都会进行判断,有一定的浪费,而switch通过数组直接会索引到相关的printf语句,是比较快的。