最新要闻
- 世界看热讯:流氓APP再见!26条新规严管移动应用:不得欺骗误导用户
- Win11 22H2“Moment 2”更新快了:将在未来几周推送
- 每日讯息!男子醉驾被查也不让新手妻子开车:为了不要出现更大的事故
- 【全球新要闻】为迎接中国游客!韩国旅游业也是拼了:推中文菜单、背汉语、招募中文职员
- 手一抖被迫看广告!工信部通知:禁止高灵敏度“摇一摇”
- 当前资讯!宜兴购房补贴本科生可以申请吗?
- 无关风月是什么意思?无关风月我题序等你回是什么歌?
- 小盆友是什么意思?小盆友生日祝福成语有哪些?
- 这款MOD可以让《原子之心》双子舞伶露脸:好看吗?
- 天天播报:中兴发布小方糖路由器:双千兆设计 首发99元
- 考验信仰、财力的时候到了!丰田加价神车新一代埃尔法曝光
- 13代酷睿CPU热卖 Intel承诺员工薪酬会涨回来:基本工资100%满血
- 每日消息!形似比亚迪仰望U8 奇瑞捷途旅行者官图发布:保时捷前总监操刀
- 电视剧红狐荣乡君是什么人?红狐电视剧演员表介绍
- 刻在我心底的名字是哪部电影的主题曲?刻在我心底的名字歌词是什么?
- 速读:财政部:截至1月末,全国地方政府债务余额357018亿元
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
焦点滚动:学习swoole之前,你需要知道的几件事
学习swoole需要的前置知识
学习一项新的技术,最重要的就why、what、how。
【资料图】
这门技术是什么,为什么用它,要怎么用它。这篇文档的作用就是为了解释what与why。
php-fpm与swoole的异同
- 常驻内存
- php-fpm模式为什么慢?
- swoole的运行方式
同步与异步
- 什么是同步
- 什么是异步
cpu上下文切换事件循环--异步是如何实现的总结
php-fpm与swoole的异同
常驻内存
一个请求通过nginx转发到php来运行,中间是通过php-fpm来沟通连接的,通过一种叫cgi
的协议来通信。
在php-fpm还未出现之前,php一般都是通过php-cgi
这个php官方组件来与web server进行通信的,它的特点是每次运行都需要重新加载一次php.ini中的配置,并且每有一个请求都会重新启动一个进程来执行,执行完毕后再销毁掉。
这种方式每次都会重新解析php.ini、重新载入全部扩展,并重新初始化全部数据结构,这无疑是对cpu性能的浪费行为,于是就出现了fast cgi
。
fast cgi
的应用体现便是php-fpm。通过一个master进程管理多个worker进程的方式,在主进程启动时便将php.ini中的配置等信息载入内存,worker进程创建时会继承master进程的数据,并且worker进程处理完一个请求后不会销毁,而是继续等待下一个请求。所以只需要一次加载,php.ini与扩展和初始化数据这部分的性能便被节省出来了。虽然php.ini的配置初始化被节省掉了,但是我们平时使用的laravel等php开发框架中同样有冗长的ioc容器初始化,依赖创建的过程,这个问题php-fpm就无能为力了。
那么说完了php-fpm,这些和swoole又有什么关系呢?相同点就在于,swoole也是常驻内存的,也是一个master管理多个worker进程,所以也节省掉了多次载入php.ini等配置的消耗。
并且,由于swoole本身就是一个PHP扩展,它的启动是在php脚本内开始的,因此可以看做是php开发框架的一部分,那么php框架初始化的那一系列重复初始化便同样被节省掉了。
这便是swoole高性能的原因。
swoole在宣传上写的是为了解决传统php-fpm模式并发慢的问题而诞生的,那么就带来一个问题:
php-fpm模式为什么慢?
php-fpm模式是以多进程方式来运行的,一个master进程创建并管理多个work进程。master进程只负责接收请求和返回响应,剩下的运行工作交给work进程来执行。
也就是说每一个请求都对应一个work进程,同一时刻,服务器上有多少work进程,这台服务器就可以处理多少的并发。这么一看是不是觉得php-fpm的并发能力特别差?假设不考虑服务器配置
问题,默认的400个进程数同时就只能支持400的并发。实际情况肯定没有这么差,假设很多的脚本只需要0.001秒就处理完成了,如果所有的请求都可以快速处理的话,那么我们可以说1秒钟的并发数就等于400*1000=40万的并发。
这么一看是不是觉得php-fpm的性能也没这么差了?
但是,如果你的业务数据量很大,mysql的查询效率不高,每次请求都需要花费1秒钟的时间才能返回响应的话呢?那么每秒钟的并发数就从40W又下降回400了。
而swoole,就是为了解决这个问题所开发出来的一个php扩展,它使得每个worker进程不会因为1秒钟的io阻塞而白白让cpu浪费1秒钟的性能。
swoole的运行方式
按照刚刚的那个例子来解释的话,swoole的处理方式就是在一个worker进程开始进行mysql io查询的时候就将这个请求任务暂时挂起,立马开始执行下一个请求,然后等到第一个请求中的mysql io数据返回之后,再切换回第一个请求中继续执行代码返回响应。这样一来,对于cpu来说,它一直在执行代码,没有因为请求中mysql的1秒io耗时处于空闲状态。
那么,既然那1秒的io耗时没有对cpu产生影响,那么对于服务器来说,每一秒钟的并发数和之前一样仍然是40W,只不过由于每个请求还是有1秒的耗时,所以单个请求的响应时间依然是1秒钟,但是对于cpu来说,它每秒处理的请求数量并没有减少,因为对于cpu来说一个请求的io耗时是1秒,1000个请求的总耗时依旧是1秒。
同步与异步
什么是同步
我们平时编写的php代码就是同步代码。php解释器一行一行的编译运行我们的代码,碰到数据库查询,或者第三方接口调用,或者系统磁盘读写。这些不归php当前进程管辖的部分都是io操作,它们可能是磁盘io,可能是网络io。而同步的代码一旦碰到这些io操作,它们就会停下来等待,等待mysql返回查询结果,等待第三方接口返回响应,等待linxu文件系统返回磁盘读取结果。在等待的过程中,cpu的性能就被浪费掉了。
什么是异步
异步代码就是说代码在运行到一个需要等待的io操作时,不在原地傻等,而是继续向下执行其他代码,等到io操作有返回结果通知的时候再回过头来执行处理逻辑。
一个简单的例子就是js中的Ajax,下面这个例子当中,js把Ajax请求发送出去就开始执行下一行代码了,所以是先alert 2,然后等到Ajax响应返回再执行回调函数alert1。
$.ajax({ url:"http://www.test.com/get_data", success: function (result) { alert(1); }});alert(2);
对于生活中的例子来说,异步就是一个人同时使用洗衣机洗衣服与使用电饭煲做饭,假设洗衣机洗一次衣服要40分钟,电饭煲煮饭也需要40分钟,那么这两件事都完成需要多长时间呢?
是的,也是40分钟(最多多出一些把衣服和米分别放进机器的可以忽略不计的时间),因为人把衣服放进洗衣机就可以去做其他事了,不会守在洗衣机旁傻等,可以去开电饭煲了。而洗衣机洗好衣服以后,会有滴滴声提示人衣服已经洗好了。
回到一开始那个swoole并发数的例子,那些需要1秒钟来查询mysql数据的请求,它们的那1秒io操作也没有让cpu进行傻等,所以对于cpu来说,io操作已经无法影响它的并发数了,因为它始终在工作,并没有浪费等待时间。
解析一下,如果使用异步的方式,那么会有两个比较关键的点:
- 发起io操作,添加回调函数
- 等任务完成后执行回调函数
异步编程完全没有浪费cpu一点性能,那如果所有的io耗时操作都用异步操作会怎么样呢?了解node.js的朋友可能经常听见一个词回调地狱
。
前端开发中很少会有人在Ajax中嵌套Ajax,但是如果你想通过异步的方式来提升代码的性能,那么不可避免的,只要你的程序中有多个io操作,那它们就会向下面这段代码一样变成层层嵌套,很快这段代码就变得不可维护了,甚至是修改的时候都会让人十分头疼。
login(user => { getStatus(status => { getOrder(order => { getPayment(payment => { getRecommendAdvertisements(ads => { setTimeout(() => { alert(ads) }, 1000) }) }) }) })})
而swoole的出现,就是为了解决同步代码浪费性能的问题,让同步执行的代码变为异步执行,同时使用协程降低异步回调编程时的心智负担。
cpu上下文切换
现在的电脑,一边写代码,一边查文档,一边听音乐都是很常见的,因为cpu 的核心数很多可以同时做好几件事。但是你在一开始学习for循环的时候一定听老师说过,当年的单核cpu写循环一定要小心,因为一旦出现死循环了,那么整台电脑都会卡死只能重启了。
cpu在执行代码的时候是同步的,所以理论上来讲同一时刻只能做一件事,哪怕不进行死循环,按理说之前的老电脑也没办法做到同时写代码与查文档以及听音乐这些事才对,并且就算是现在的四核八核cpu,那我也是可以同时开十几个网页,同时播放视频的。
让单核cpu同时运行多任务的魔法就是上下文切换
了,主要的原理就是cpu在同时进行玩游戏与播放音乐时,先运行一会游戏,然后马上切到音乐程序上运行一会,不断地在这些应用之间来回切换运行,因为cpu的计算速度是远超人脑反应时间的,所以在人类眼中,这些应用就像是在同时运行一样。
那到底什么是上下文
呢?就是程序运行中所需要的数据,包括存储在内存中的,以及cpu多级寄存器中的这些数据。在线程与进程切换的时候,需要把这些数据保存起来,等到它们恢复运行的时候再把数据读取回进程来运行。
本文主要是介绍swoole的,swoole的重点在于异步与协程,为什么要提到上下文切换
呢?因为不论是多进程、多线程还是协程,它们本质上都需要用到上下文切换
来实现的。
多进程模式,是由系统来决定每个进程的运行分片时长。而多线程由于它们一定有一个父级进程,所以每个线程的运行分片时长则是由进程来决定的。这也是为什么多线程语言的教程里都会提到不是线程开的越多越好的原因,多线程会有线程争抢和系统调度的开销。同时,由于cpu同一段时间内运算速度的总量是固定的,所以线程只需要尽量把cpu空闲的算力占满就好,开过多的线程反而会因为增加系统线程调度开销造成业务部分线程性能的下降。
那么协程与多线程多进程又有什么不同呢?通过实例来对比:
- php-cgi便是多进程的一种体现,每个请求对应一个cgi进程,带来的缺点是进程频繁创建销毁的开销以及每次都需要加载php.ini配置的性能浪费。
- php-fpm多进程模式的改良,通过master/worker的模式,让多进程少了重新加载配置与频繁创建销毁进程的开销。
- 假设php有多线程,省略多次php.ini的加载,省略多次开发框架初始化,相应的带来线程调度开销,多线程抢占式模型需要注意数据访问的线程安全,需要给数据加锁,并带来锁争抢与死锁问题。
- 协程,省略多次php.ini加载,省略多次开发框架初始化,由于协程是用户态的线程,所以由代码来控制什么时候进行切换,没有线程调度开销。并且swoole以同步的方式编写异步代码,协程的切换由底层调度器自行切换,开发者无需关注线程锁与死锁问题。
swoole的协程切换是基于io来调度的,也就是说它只会在遇到io操作的时候才会进行切换,通过节省io等待时间来提高服务器性能,因此swoole的协程是无法进行并发计算的。不过遇到需要并行计算的场景,swoole也提供了多进程的运行方式,如果需要多进程协同操作同一个数据,就需要加进程锁了。
事件循环--异步是如何实现的
现在我们已经知道多进程,多线程,协程都是异步的编程方式了,那么异步是怎么实现的呢?这是一个大问题,先从最基础的看起,基础异步编程就是异步回调模式,也就是在执行任务的同时传入一个回调函数,等到任务执行完毕,回调函数自然而然的就开始运行了。类似js的Ajax一样,发起一个Ajax请求的时候便是发起了异步任务,同时在$.ajax方法的第三个参数传入一个匿名函数,等到后端返回响应以后再继续执行回调函数中的代码。
那么就出现了一个问题,是谁来通知当前进程异步任务已经完成了的呢?
做过im通信朋友都知道,两个客户端的对话除了发送消息,最难实现的还是接收消息,因为需要服务端主动做推送。如果不使用WebSocket的话,要实现服务端推送就只能使用长连接+轮询的方式了。接收消息的那一方客户端需要每隔一段时间就请求一次服务器,看看有没有消息发送给自己。对于异步回调来说,它的实现方式也是有异曲同工之处。
处理异步回调的部分叫做事件循环
,可以理解为每个进程有一个死循环,不断的查看当前有没有待执行的任务、已经执行完需要通知的回调。当我们进行异步任务调用的时候,就是向这个循环中投递了一个任务与对应的回调。当任务完成的时候,循环便把任务从监听数组中去除,并执行回调。
下面来看一个简单的事件循环的例子。
可以看到,EventLoop类中维护了一个event数组,用来存储需所有需要监听的事件。在调用addEventHandler
方法时,则需要将事件的类型、参数,以及回调函数一同传入。
当调用run
方法时,这个循环就被开启了,可以看到run
方法中是一个while死循环,用来不断的检测是否有已完成的任务。而while循环内层的foreach则是为了查看所有事件中是否有已完成的单个任务。
而processTimers
与processIOEvents
方法则代表了swoole中典型的两种事件,io事件与定时器。由于linux系统中万物皆文件的特性,很多看似是网络io的功能,其实都要用到文件系统来实现,所以processIOEvents
方法需要传入fp文件指针以及read与write两种读写事件。例如假设我们投递的是读取事件,那么就调用fread函数来读取文件,并把读取到的数据传递给回调函数来执行。这就是一个事件循环的回调过程了。
event_handlers[$event_type][] = $handler; } public function run() { while (true) { foreach ($this->event_handlers as $event_type => $handlers) { switch ($event_type) { case "timer": $this->processTimers($handlers); break; case "io": $this->processIOEvents($handlers); break; // 可以根据需求添加更多事件类型 } } } } private function processTimers($handlers) { $now = time(); foreach ($handlers as $timer) { if ($now >= $timer["time"]) { $timer["callback"](); if ($timer["interval"]) { $timer["time"] = $now + $timer["interval"]; } else { unset($this->event_handlers["timer"][array_search($timer, $handlers)]); } } } } private function processIOEvents($handlers) { foreach ($handlers as $io_event) { $fp = $io_event["fp"]; $callback = $io_event["callback"]; $events = $io_event["events"]; $read = in_array("read", $events); $write = in_array("write", $events); if ($read) { $read_data = fread($fp, 8192); if ($read_data) { $callback($read_data); } else { unset($this->event_handlers["io"][array_search($io_event, $handlers)]); fclose($fp); } } if ($write) { $callback(); unset($this->event_handlers["io"][array_search($io_event, $handlers)]); fclose($fp); } } }}// 使用示例$loop = new EventLoop();// 添加定时器$loop->addEventHandler("timer", [ "time" => time() + 5, "interval" => 0, "callback" => function () { echo "5 seconds have passed\n"; },]);// 添加 IO 事件$fp = fopen(__FILE__, "r");$loop->addEventHandler("io", [ "fp" => $fp, "events" => ["read", "write"], "callback" => function ($read_data = null) { if ($read_data) { echo "read data: $read_data"; } else { echo "io event has occurred\n"; } },]);// 启动事件循环$loop->run();
在理解了时间循环以后,那么事件循环与swoole与多进程、多线程、协程之间有什么关系呢?
没错,无论是多进程、多线程还是协程,它们底层都依赖事件循环来实现异步,例如进程与线程之间切换的时候如何通知对应的进程与线程?依赖系统级事件循环。例如协程之间多个协程的切换要如何通知对应的协程?也是依赖事件循环。不过swoole为了降低上下文切换带来的消耗,没有依赖系统级事件循环而是自己实现了一套,swoole的协程上下文切换都是内存读取,避免了cpu寄存器、堆栈以及系统内核态与用户态之间的切换,因此切换开销极小。
总结
说了这么多概念,那么swoole到底是什么呢?它融合了php-fpm的结构模式,优化了单进程的性能浪费,弱化了多线程的调度开销,屏蔽了异步回调的复杂逻辑,是一个常驻内存的高性能web扩展。
做一个不严谨的类比,你也可以认为swoole是一个语言层面实现的php-fpm,毕竟swoole也支持完全的多进程模式,这种模式下与php-fpm的运行方式大同小异。不过由于在语言层面便常驻内存了,所以带来的福利便是在启动php脚本的开发框架时,只需要一次载入便保存在内存中了,避免了php-fpm每个请求都重新初始化框架的性能浪费。那么同样的由于服务常驻内存了,所以哪怕是在开发过程中,代码相关的改动都需要重启一下swoole服务。
而swoole的架构,对应下面这张图,便是master、manager、worker的结构,在swoole服务启动时,master进程便fork出manager进程来对worker进程进行创建和管理,master进程自己则通过reactor线程来接受与分发请求,master进程接收到的请求通过reactor线程直接发送到worker进程中,而worker进程负责对请求进行具体的处理。如果开启了协程模式,并且代码也是以协程的方式运行,则一个worker可能会一段时间内(例如1s)处理多个请求。因为每个请求遇到io等待时,worker便切换协程直接开始处理下一个请求了,直到io任务返回结果,worker再切换回上一个请求将响应返回给master进程。
swoole对性能的提升带来的代价是编程思维的转变,因为常驻内存了,所以编写业务代码时,对内存变量的使用就需要更加小心,避免造成内存泄露。因为基于异步编程,所以要理解异步的思想,避免写出同步阻塞的代码。
焦点滚动:学习swoole之前,你需要知道的几件事
世界看热讯:流氓APP再见!26条新规严管移动应用:不得欺骗误导用户
Win11 22H2“Moment 2”更新快了:将在未来几周推送
每日讯息!男子醉驾被查也不让新手妻子开车:为了不要出现更大的事故
【全球新要闻】为迎接中国游客!韩国旅游业也是拼了:推中文菜单、背汉语、招募中文职员
手一抖被迫看广告!工信部通知:禁止高灵敏度“摇一摇”
当前资讯!宜兴购房补贴本科生可以申请吗?
焦点关注:ChatGPT的隐私安全问题及隐私保护技术
无关风月是什么意思?无关风月我题序等你回是什么歌?
小盆友是什么意思?小盆友生日祝福成语有哪些?
这款MOD可以让《原子之心》双子舞伶露脸:好看吗?
天天播报:中兴发布小方糖路由器:双千兆设计 首发99元
考验信仰、财力的时候到了!丰田加价神车新一代埃尔法曝光
13代酷睿CPU热卖 Intel承诺员工薪酬会涨回来:基本工资100%满血
每日消息!形似比亚迪仰望U8 奇瑞捷途旅行者官图发布:保时捷前总监操刀
电视剧红狐荣乡君是什么人?红狐电视剧演员表介绍
刻在我心底的名字是哪部电影的主题曲?刻在我心底的名字歌词是什么?
win7快速启动栏在哪里?win7快速启动栏怎么使用?
东芝ac100怎样刷系统?东芝ac100安卓笔记本多少钱?
超长待机智能手机有哪些?超长待机智能手机排行榜
三星GALAXY i5700什么时候上市的?三星GALAXY i5700怎么关机?
世界热头条丨谷歌邮箱注册
环球观察:Prometheus插件安装(NodeExporter)
焦点热讯:Redis高频面试题总结
速读:财政部:截至1月末,全国地方政府债务余额357018亿元
聚焦:威马员工在线讨薪 吉利副总裁:我这里缺人、可以考虑下
全球看点:一箱油续航轻松破千公里 五菱凯捷混动铂金版上市:12.98万起
摩托罗拉rizr纵向卷轴屏手机亮相:屏幕可伸长
国内能买到!ZERO SR-X概念电动摩托发布:110马力、能跑300公里
当前关注:送冰极洁面霜:妮维雅男士控油补水洗面奶24.9元大促
天天热推荐:Mysql 自定义目录安装
世界资讯:武汉Java培训班哪家好?大家都要怎么挑选
全球速看:SQL行转列、列转行(SQL Server版)
世界视点!南京Java培训班哪家好,什么样的可选
什么是潮吹
担心的事儿发生了:已有企业在用ChatGPT取代员工
每日热门:iPhone 15 Pro Max与14 Pro Max对比:明显更厚了!妥妥半斤机
纳智捷当街加油 车主现身说法:从郑州到广州加了5次
环球速递!半价大促:五芳斋豆沙青团6枚9.9元发车 清甜绵软
全球最早上映!任天堂《超级马力欧兄弟》大电影内地定档4月5日
世界最新:总结SpringBoot1.x迁移到2.x需要注意的问题
全球短讯!Spring Boot 实现日志链路追踪,无需引入组件,让日志定位更方便!
代理设计模式还不会?2分钟搞定
【世界报资讯】河南省通许县:“中国酸辣粉之都”正式揭牌
天天热门:微信下重拳:上万个群被封杀 此类行为千万别做
环球微头条丨程序员20年喝近2吨可乐屡患结石 几乎天天喝
联想推ThinkPad Z16 Gen 2笔记本:锐龙7000系列 可选4K+屏
双子姐妹、冰箱很带感 《原子之心》游戏已被破解:俄罗斯自己黑客干的
还敢生吃?日本即将核污水倒入大海 降低水产品氚活度分析精度
世界观天下!老外首次用上徕卡影像!小米13/Pro国际版发布:999欧元起
全球看热讯:9岁女演员获柏林电影节最佳主角:史上最年轻获奖者
今日热门!高三女生因百日誓师热血发言表情被网暴 父亲怒回应:我们的骄傲 请尊重
《流浪地球2》导演郭帆让学生们不要用ChatGPT写作业:老师分辨不出来
读Java性能权威指南(第2版)笔记03_ Java SE API技巧中
美国铁路烂到家:“毒列车公司”再次发生脱轨事故 问题没法解决
【世界速看料】昔日手机巨头换新!诺基亚换全新Logo 刷新认识:网友直呼爷青结
每日热议!残损货币及不宜流通货币常识_不宜流通人民币与残损币区别
AMD RX 7900显卡价格在中国崩盘了!两个月暴跌1400元
世界滚动:不完整的爱情
每日动态!怎样提高空间想象能力 如何提高空间想象能力
全球速看:量化交易基础 - 10 - 拟合
全球速读:Kafka简单介绍和安装
当前快讯:委员蒋胜男建议对8小时工作制加强监督:你一天干几小时?
CentOS7安装nvm和node
局域网实现PC、Pad、Android互联
世界速讯:三大范式
项目中并发修改可能存在的问题
环球快资讯:暴力涡轮风扇RTX 4090再次现身:噪音令人崩溃
全球快讯:国产本田E?众泰江南U2纯电轿车正式上市:5.88万起
今亮点!“中国蛇王”凉了?老牌国货隆力奇人去楼空”上热搜 曾连续11年全国销量第一
今日热闻!Java面向对象进阶第四天(常用API)
Codeforces Global Round 15 CF1552 A~G 题解
每日热文:八方点赞!姆巴佩、莫德里奇等多人点赞C罗社媒动态
世界快报:零下50℃室外玩电脑 显卡都冻傻了:核心温度167万摄氏度
【速看料】能用沐浴露洗头吗?可以是可以 但最好别
天天动态:国内首个类ChatGPT模型:复旦大学团队称MOSS将于三月底开源
观速讯丨国产八核CPU!诺基亚发布G22:小白都能自己修
全球快看:解决IDEA无法识别SpringBoot项目
方敏仪
享年86岁 电影美术大师杨占家去世 手绘媲美CAD制图
世界快资讯:《流浪地球》地下城成真?我国地下基础设施监测技术实现新突破
【环球时快讯】易烊千玺 我们还会在一起吗?_对于易烊千玺 我们还会在一起吗?简单介绍
世界观察:卡罗拉车主试驾完比亚迪唐DM-i之后 丰田信仰瞬间崩塌
80后夫妻攒300万“提前退休” 不生孩子这些钱够了?网友吵翻
一加Buds Pro 2新配色“云峰白”亮相:打磨难度拉满
头条:Linux极简入门系列(二):Linux的目录结构和常用操作
【速看料】Linux vim
当前动态:Vue2 里如何优雅的清除一个定时器
天天通讯!推特进一步削减开支:马斯克挥刀裁掉50名员工
快播:上映10天:《中国乒乓》票房终于破9000万大关
关于数据分析中的绘图分析的学习报告
LWIP学习记录---ARP协议(2)ARP数据包发送过程
go A*寻路记录
59.类的自动转换和强制类型转换
不是“空中楼阁”:努比亚Pad 3D搭载全球最大Leia 3D内容生态
【报资讯】男子车停路边去吃烧烤 回来瞬间崩溃:路边已装上护栏
【独家焦点】作文游西湖300字(精选40篇)
千里托运奔驰GLC被淋满牛粪 女子崩溃:花1900元洗了5遍
【世界速看料】情侣打车3小时后跑单拉黑司机 司机:246元车费没了
世界资讯:微软承认向无法升级的设备推荐Win11:已进行修复