2024-07-25 00:00:00
下了飞机,我沿着通往停车场的道路走去,同时打开手机叫网约车。每次在机场叫车,貌似都需要跟司机沟通一番确认上车地点,软件的上车指引貌似只是一纸友好但过期的提示,并不具备实际参考价值。没过多久就有司机接单,很快一个电话打来,司机让我到另一层等他,我毫不犹豫地答应,径直朝向约定地点走去。当车到达,我把行李放入后备箱,像往常一样打开后座门坐了上去。
“师傅,不走高速哈,其他随意”,我说。
“好的,这一路没有高速,只有些高架”,他回答,“如果你在浦东叫车,那边可能有”。
“浦东啊,我前几个月来过一次,当时是从浦东机场出发的,那边可远了”,我抱怨道,“后来,我都注意选到虹桥机场了”。
我沉默了一会,继续说道:“浦东的客流是不是比虹桥少一些,毕竟远离中心市区嘛”。
“其实也不少,我们也能接到不少单。那边虽然远,但我更愿意接,赚的会更多一些”。
“是的,路途远价格就会高些”,想着师傅这么晚接我的单,于是我鼓励到:“师傅,你这么晚还跑车,家人肯定也挺心疼你吧”。
“就我一个人在这边,家人都在老家呢。对了,等你回去的时候可要注意,从哪个机场出发,别走错了,不然可就麻烦了”。
“好的”。
平时外出,我都会主动给家里报平安。在给家人回复完消息后,我又主动与师傅搭话:“上海的高架桥挺多呢,还有地道,车开着也不会堵吧,感觉比北京要好很多,经济也比北京有活力”。
“是啊,这里的路,建设的很好,到哪都方便”,他说道,“北京是首都嘛,上海还是比较多搞经济的人儿。但是啊,这两年也没以前好了啊。社会上那么多公司,又是裁员又是降工资的。就拿我们自己说,这半年赚到的也比原来少了很多”。
我说:“确实,我也有听说,好像滴滴提升了不少抽成比例吧?”
“是的,比如平常你付 100 块钱的单,我们能拿到 80 块,今年可能就只有 70 喽,尤其今年过完年之后,这不就是压榨我们司机嘛”,从话语中能听到师傅对现实的无奈,但他仍在坚持。
“经济不好,大家就都卷起来了,同行互相卷,平台卷司机”,由于聊的比较投机,我继续说到,“现在,不仅滴滴抽成,你们内部也有危机感吧。前段时间新闻不是提到萝卜快跑嘛,也会抢走大家一些饭碗吧”。
“是啊,那萝卜在武汉多火啊,抖音上天天刷到。不过说回来现在道路这么复杂,你说我们都开不明白,他机器还能开明白咯”,师傅继续说道,“你看新闻不是也说两个萝卜在转弯的时候互相卡住了嘛,一动不动,给路上堵得哦。“
师傅继续,“人还能听交警的话,那萝卜哪会听啊?路上要都是萝卜,那得乱套了。我看啊不太行,这开车还是需要人”。
“但现在电车真的很便宜,你觉得呢”,师傅谈兴正浓,开始饶有兴趣地给我介绍车市行情:“你看前阵子,比亚迪那车一出降价消息,价格就低了不少!依我看,其他车企啊都得跟着降。电车以后肯定会越来越便宜,大家都能买得起车”。
我突然有个疑问,便向师傅问道,”师傅,你说这路上跑的有多少是新能源车呢?”
“一百辆里,至少得有五、六十辆吧”。
“那还挺多的。北京虽然也有新能源车,倒没这么多。可能因为天气冷吧,电池不经扛?”
“是的,天气冷,电池掉电起来非常快,电车还是南方多些“。
我继续追问师傅:“话说,电车你考虑过蔚小理吗?相比比亚迪,他们的车型应该会更便宜些吧,性价比更高?”
“比亚迪也不贵呢,而且质量多好呀。你看这次他们降价,又便宜了不少“,说到这,师傅扭了下身子,继续说道,“要说贵啊,还得是保险”。
“我之前倒是有了解过,好像是因为新能源车更容易出事故,再加上发展起来时间还太短,所以保险定价也比较困难?”
“事故确实多,发生得也快啊。就像上一次我在路上开车,眼看着前方一辆车冒烟了,就开一会到跟前的功夫,那车已经全部烧起来了,你说这多严重啊!”
我紧握着收集,听着师傅的描述,仿佛能看到那些惊心动魄的场景在眼前一幕幕上演。
师傅似乎还有很多经验继续分享,“不仅是容易着火,平时啊你一个不注意,保费都会往上涨点。我去年续保费用涨了 20%,当时业务员也很纳闷,后面一查发现是违章、扣分啊这些,影响最终的价格”。
“但这保费啊,就算再涨也得买呀。这年头,你要不上保险,哪敢开车往路上跑啊。万一撞到人,误工费、住院费、治疗费这些各种算在一起,哪赔的起啊“,他说着说着有些激动,”你知道我们最怕什么吗?”
我摇摇头,表示不知道。
“最怕那些跟你耗着的。遇到个事故,就算不是你的责任,人家是弱势群体,你都得搭进去好些时间和精力,还有赔偿。就说去年那会吧,我的车直接被交警扣押了一周多”。
我问道,“你当时遇到什么事了吗?”
师傅说:“当时在小区里,我开的很慢,突然不知道从哪个缝里窜出一辆电瓶车,‘咣’地一下撞到我车上。你说明明是他没看路撞上来,检查后也没发现什么大问题,但他就是躺着不肯走。最后没办法,我只能报警。警察来了后,了解了一下情况,直接把我车拖走。后面赔了钱,才把我的车拿回来。”
我又疑惑道,“按理说,这事故也不是你的责任啊,为什么交警要扣你的车?”
“不管谁的问题,你们之间没有协商好,交警就会先把车拖走,权当个抵押物吧”,他带着些许抱怨的语气说道,“必须等到双方协商好签完字,才能把车拿走。要是没法达成协议,对方还可以让你的车继续往后拖个十天八天的。车扣一天,我就少赚一天的钱,我在上海也要生活下去啊。你说,我哪拖得起呀?”
我安慰道:“有人就故意碰瓷,没事也说有事”。
“是啊,但你保不准会遇到什么样的人。现在买保险了,遇到事故就交给保险公司去处理了”,他说道。
“还好有保险”,我感慨道。
“有了保险,也没太多改善啊,一样攒不下钱”,师傅感慨道,“你就说,我这一年跑车下来,也能赚个十几万不少了,要是在老家干活,一个月也就三四千,但还是攒不到钱啊”。
此时,路程已经好一会了,窗外的风景在多个高架桥和隧地道之间切换,一会明亮,一会阴暗,快速切换的光景让我时而可以放空发呆,给大脑一阵小憩。
车辆向前,貌似不再有地道了,具有经典上海街景的马路映入眼帘,两边整齐排列精致且小巧的楼房,在外饰灯光的映衬下还挺好看。即便如此,我还是感觉有些不对,说不上哪来的一股隐隐压抑感,突然,我想到,是对师傅印象的那种忸怩与割裂感,对的,就是这种不太真实的割裂感。
一个深夜这么努力跑车赚钱的师傅,对乘客出行给出热心建议,对新能源车行业也有自己的学习与了解,对激烈的市场和经济不好的大环境有所提防,同时还不忘配置保险保障家庭,怎么还会感慨攒不到钱呢。他的热情、努力与那份真实感,怎么都让我无法将他与那种赚到钱就去大手大脚消费、月光的人联系在一起。我心里犯着嘀咕, 而此刻,师傅开始主动搭话。
“我平时除了睡觉、跑车,也没啥开销,赚到的钱都往家里寄。你知道,我 88 年的,活到现在这个岁数,养家糊口啊开销很大,我这生活啊已经不是为自己而活了“。
我突然明白,原来师傅的钱都用在了家人身上,那确实花钱。还记得同事经常说,养娃就是个无底洞,师傅将花销都花在了孩子身上,那想必也是幸福的烦恼吧,我一阵释然。
师傅继续说道:“上有老下有小的,今天女儿要上个补习班,明天儿子要去学个兴趣课程,到处都花钱,就跟流水一样”。
我轻松应答道:“是啊,养孩子嘛,为了孩子定位茁壮成长,还有上学,都很花钱的”。
师傅继续:“小时候,我就在读书上吃过亏,现在不想他们再吃亏了,我多跑车,让他们可以多学一些吧”。
“可怜天下父母心啊,孩子长大后会明白你的好的”,我说道。
“倒不奢求他们将来如何回报我们,现在社会上那么多不孝顺的新闻,见怪不怪了。为他们付出了这么多,要真等我老了,他们不管我了,我也不能怎么办”,师傅补充道。
“是啊,这就是单纯的付出与爱,是不求回报的”,此刻的我由于对亲子教育没有太多经验,也不太想聊,于是借着上有老下有小的话题,我开始向「上有老」延伸,但没想到接下来引出了非常沉重的话题。
我对师傅说道,”孩子嘛,至少还有个盼头,就是不求他们孝顺回报,但这么一天天看着他们长大,也算有所慰藉。但是家里的老人啊,这事就不那么好处理了“。
听了我的话,师傅似乎没有那么主动想接话,由于我对父母养老这个话题也很敏感,所以每当有机会,我都会拉着人一起聊聊,于是我继续说下去,”父母啊随着年龄增长,不管是生病还是养老陪护,都需要花精力、花钱,有的时候这些事情才让人烦恼“。
师傅向前挺了挺身子,然后回复到,“可不是嘛,父母这一病,不停地吃药、治疗,每个月那么多钱,压力很大“。
师傅的声音突然低沉下来,他紧紧握住方向盘,一字一句的吐露着:“我妈每天都在吃药,每个月花很多钱在买药上,但依旧在病痛中度过,已经很久了。花费这么多,但还是没法好,而我们也不能多做些什么,除了多赚些钱“。
“她得了癌症,熬到现在有三年了”,他补充道。
我的转过头,看着窗外快速略过的夜景,试图平复自己的情绪,但师傅的话语却像一根针,深深地刺入我心底。昏暗的夜晚,只能靠着不断来往的车辆折射的灯光,隐约看到师傅的身影,此刻,我透过后视镜扫了师傅几眼,发现他的眼眶已有些湿润,闪着微光。此刻,我想安慰他,却发现任何言语都显得是那么的苍白无力。
只见师傅眼眶越来越红,他深吸一口气,仿佛在平复自己的情绪,然后继续说道:”你说做子女的哪能不管呢,但这三年来,不停地检查、更换治疗方案、换药治疗,花了很多,她每次忍着病痛的样子,让我看到真是如刀割一样。但我们已经尽力了“。
“是啊”,我憋出两个字回应师傅。
师傅继续说道:“我们家,我到上海来赚得多些,我爸在家打工,我老婆也在家打工,为了孩子和我妈,不停地攒钱,又哗哗的花出去,你说哪攒的下钱呐”。
“三年前她刚确诊癌症,当时每个月的钱还少些,但每隔两个月旧的检查一次,一次六七千,还要不断地买药。刚开始药便宜,后来药不管用了,医生就让我们换药吃,不断的换药,价格也不断上涨。上个月医生又跟我说之前的药不管用了,要换另一种药试试,一个月一两万。药越来越贵,也得继续吃着啊,她治疗着痛苦,但治不好,我们也难受。“
这时我想起了医保,于是忙问师傅:“你妈有买医保或者农村保险之类的东西吗,那个应该可以分担一些支出费用?”
“买啦。早几年,有个上门卖保险的,当时就给他们买了,赔了七八万吧,但要早知道,当时就该多买些,那样可以赔得更多。医保嘛,期初还能报一些,但后来不断加药、换药,那些进口药都不在里面,是不能报销的”,师傅一口气说了很多,但明显还没说完,他清了清嗓子,继续说道:“我妈是真遭罪,就这么一直扛着,扛了三年了,不知道还能撑多久了。我们真的尽力了”。
看到师傅的眼眶明显有些红润,我平静的说道:“你尽力了”,我不知道自己的表述是否恰当,于是停顿了一会,才继续说道:“可能努力改变不了结果,但至少让自己不留遗憾吧”。
”你说尽孝吧,我们也一直在努力,但就没个希望。过个一阵,就听到医生说这个药效没啥效果了,需要换新的药。你说就我们县城,大家都是一个月三四千的收入,我在上海还能赚不少钱,这要换其他家里可能早就放弃了“,师傅的声音开始颤抖,”我朋友经常说我太拼了,为了父母,为了孩子,我也得继续拼搏啊!”
“尽力而为,不留遗憾”,我说道。
“生活就是这样啊,但不还得继续努力嘛,总不能就这么放弃了。我妈都那么坚强,我也要继续努力。话说回来,我还是挺喜欢上海的,我能在这赚不少,让他们活的好些……”
车快到酒店了,司机放慢了开车速度,直到把车停在酒店大厅旁。他还在说,似乎没有喊我下车的意思,我也就继续听着。
“还是要买保险啊,有机会多了解些,这还是很有用的”,“多谢师傅,加油!”
这是我跟师傅最后的对话,此后我便下车,径直走向酒店。师傅也开车离去,继续他的人生旅程。放下行李后,我直奔健身房。跑了半小时步,我的心情好似才没有那么堵了,多亏运动帮我发泄一番。
就是这么一次再普通不过的打车经历,两个青年相互交换了各自生活中一个又一个的故事,这是每个普通人都会遇到的日常,也是每个普通家庭都可能会面对的生活难题。
虽然他口口声声说不再为自己而活,但我仍能感受出,他对自己奋斗目标的在意与上心,对平淡、幸福生活的向往。我跟师傅这辈子可能也不再会有机会见面,不知道他的家庭生活未来会去向何方,他的母亲病情会如何发展,他的两个孩子长大会做什么工作。
但我想,我应早已知道这些答案。这样一个个真实而努力的身影,每天都在我们周围发生,他正是千千万万个普通人的缩影。
为了赚钱补贴家用深夜跑滴滴的司机;
不论刮风下雨仍坚守岗位的建设工人;
牺牲自己睡眠坚守夜班以保障城市基本运转的服务人员;
起个大早为了路面清洁的环卫工人;
精心备菜在食堂为大家准备放心食物的厨师;
以及,每一个为生活努力的你我。
为每一个认真生活、奋斗拼搏的身影加油,愿每一个像他般努力、坚持且热爱生活的人,都能幸福。
2024-06-27 00:00:00
在当今科技领域,大型语言模型(LLM)和生成式人工智能(AIGC)已成为引领潮流的热门话题。它们的出现不仅颠覆了我们对传统人工智能的认知,还为各行各业带来了前所未有的变革。然而,随着这些技术的广泛应用,如何有效地将这些强大的 AI 模型集成到实际应用场景中,成为了一个亟待解决的问题。在如此背景下,一个名为 AI Gateway 的概念近期被大家所了解,作为一种连接 AI 技术与各类应用的关键平台,它又为当前火热的 AIGC 带来了什么?
本文将详细介绍 AI Gateway 的概念、功能,并通过丰富的应用场景展示其在实际应用中的巨大潜力。通过阅读本文,相信你会对 AI Gateway 有一个全新的认识,并为你在广阔的 AI 世界中探索工具箱增添一个新的技术,那么我们就开始吧。
提及工业界的实践,要追溯到 Cloudflare 在去年 11 月推出的 AI Gateway 测试版了,Cloudflare 在发布时表示,AI Gateway 可以使 AI 应用更具可监测性、更可靠、可扩展性更强。所以我们首先来回答这个问题,什么是 AI Gateway 呢?
AI Gateway 也被称为大模型网关、AI 网关,是一个用于部署和管理人工智能(AI)模型的平台,在开源社区有对应技术实现。它为用户提供了一种方便的方式来部署和管理 AI 模型,无论这些模型是预训练的模型,还是用户自己开发的模型。AI Gateway 还提供了一种方式,让用户能够在需要的时候轻松地调用这些模型,例如在进行数据分析或开发新的 AI 应用程序时。此外,AI Gateway 还提供了各种工具,可以帮助用户监控模型的性能,以及进行模型的优化。
当然,除了上述功能外,AI Gateway 的特点不仅限于些,它还提供了高度的灵活性和可扩展性,用户可以根据自己的需求选择部署模型的规模,以满足各种业务需求。用户也可以根据自己的需求,调整模型的参数,以满足特定需求。
此外,由于具有对模型的权限管理及实时监控功能,加上可以缓存、重试、调整模型调用优先级等优化措施,AI Gateway 还可以保护数据隐私,稳定、高负载、安全的运行。
虽然两者不如雷锋和雷峰塔之间的巨大区别,但除了都是某种形式的关卡外,两者在服务对象、应用场景以及主要功能上,都存在不少差异。
如上文所描述,AI Gateway 是一个 AIOps 类平台,作为服务和推理提供者之间的代理,无论模型位于何处,为管理和扩展生成式 AI 工作负载提供了统一的接口。相比之下,Gateway,即传统网关,则更多地用于网络连接和数据传输,是网络连接到另一个网络的“关口”,实现网络互连,是最复杂的网络互连设备。
简单来说,AI Gateway 专注于 AI 模型的集成和管理,而传统网关则侧重于网络连接和数据传输。
大部分朋友接触 AIGC 应该都是从 chatGPT 开始的,因此,当了解到 AI Gateway 之后,难免不产生疑问,为什么我不直接用大模型呢,还要多走你调用一层?当然,chatGPT 作为一个人工智能对话程序,能够借助自然语言实现人机对话,对终端消费者已经够用了,然而,AI Gateway 作为一个 AI 模型的集成于管理平台,对于开发 chatGPT 这类服务的开发者来说,可能更具吸引力。
AI Gateway 和直接使用大模型之间的主要区别也在于 AI Gateway 提供了一种集中化的接口管理机制,使得应用程序能够更高效、安全地调用多种大语言模型,而直接使用大模型则涉及到与模型的直接交互,会涉及更多的技术细节和复杂性。此外,AI Gateway 还有以下几方面的特点,使得其相比直接使用大模型更具优势。
首先,AI Gateway 作为连接服务和推理提供者之间的代理,无论模型位于何处,为管理和扩展生成式 AI 工作负载提供了统一的接口,这便允许我们通过统一的调用方式,根据自身需要在多个大语言模型之间切换调用,以获得我们的需要。
其次,缓存 API 调用让 AI 应用开发成本更加可控与便捷。通过 AI Gateway,可以对 API 调用进行缓存,这在行业高速发展期,面对 API 调用次数快速增长的背景下,可以快速地节省成本开销以控制研发成本。
AI Gateway 也可以组合一系列技术和策略确保数据隐私,包括加密、访问控制、审计日志等,以保护用户数据不被未授权访问或滥用,达到保护数据隐私的目的。
此外,还有一些 AI Gateway 实现可以通过严格的用户认证和基于角色的访问控制(RBAC)系统,确保只有经过授权的用户才能访问和修改数据模型。这种访问控制机制是防止未经授权人员访问 AI 数据模型的关键。
AI Gateway 的应用场景广泛,适用于多种人工智能应用场景,包括自然语言处理、文本生成、语音识别等,无论是个人开发者还是企业级应用,都可以从中受益。相比之下,AI Gateway 可以帮助开发者更好的管理 AI 应用及监控,同时更便捷、高效的实现对多种大语言模型的有效整合与调用,从而满足用户在各类 AI 场景下对于模型选择、策略配置以及数据安全等方面的专业需求。
作为仍在快速发展期的一项 AI 技术平台,AI Gateway 的未来仍有很多可能:
AI Gateway 在连接 AI 与各类应用中起着至关重要的作用。作为一个崭新的技术平台,它不仅提供了一种简便、高效的方式来集成和管理 AI 模型,同时也在实现 AI 技术与各类应用的无缝对接上发挥了巨大的作用。无论是自然语言处理、图像识别,还是语音合成和推荐系统等各种场景,AI Gateway都能大大提高 AI 技术的应用效率和便利性,从而推动 AI 技术的广泛应用和快速发展。
面向未来,不论是更大范围的 LLM 支持、更精细的查询加速与缓存机制建设、更全面的应用监控与安全防护策略,还是应用层更便捷的操作和低使用门槛,都是 AI Gateway 可以继续努力的方向。
2024-01-27 00:00:00
今晚打车,司机停在一个靠近上车点拐弯口的路边,一直没开进来,期间他一直跟我站内信确认“出来了吗”,我和往常一样,快速回复说我就在定位点等他。回复完,貌似司机也没有动弹。
过了一阵他发来消息,问我能不能出去找他。他给我的理由是门口不让他开车进来。由于天气特别冷,我不太想动,于是文字回复他,“车子需要绕商场一圈才能进来,入口那是单行道”。回复完,对话框又陷入了沉默。
其实没有啥事,但我就是有点急,于是主动问他,到底是我出去找他还是他开进来,我说我可以出去,让他告诉我上车点。隔了一阵,他回复我,“我进来找你”。
由于绕行进来的这段路在下班点很堵,于是我又回到了室内大厅,那里会暖和点。期间我还在跟家人打电话,聊天过程中我带着一丝抱怨的语气提到,今天这师傅感觉对路不熟使我在外面等了很久,冷死了。
/
我期间也有一丝疑惑,司机跟我文字沟通这么多,为什么没直接打电话直接问我呢。过了好一会,车终于来了,我照常报了一下手机尾号,就全程沉默,直到快下车。
我发现临近目的地,司机还没有要停的意思,于是我赶紧说已经到了,但他似乎没听到,车仍旧向前多开了一会儿。
收拾好行李,正当我开门下车时,我发现他半侧着转过身来,双手合十,面带微笑,反复对我点头示意。
啊,我才反应过来,原来他是一个聋哑人。
/
在互联网企业工作久了,貌似自己的耐心都被削弱了不少,针对一些看似不寻常、不高效的事情,我甚至会在缺少观察和理解的前提下,直接下意识的设定立场与抱怨,不知道司机师傅有没有感觉到我的不耐烦。
从防止资本无序扩张、加速信息茧房、奶头乐理论到拉大贫富差距,互联网企业这些年一直没落得个好名声。但我想,他确实通过不断推出创新产品,给人们的生活带来便捷,从线上聊天、手机购物、扫码支付到方方面面,这都在深切的改变着我们的生活。线上打车不就给予了先天残障人士另一种更体面、适当、不风吹日晒的赚钱方式吗?
所以,互联网还是挺好的。
2024-01-03 00:00:00
在上个月,由于客户反馈客户端卡死现象但我们远程却难以复现此现象,于是我们组织了一次现场上门故障排查,并希望基于此次观察与优化,为客户端开发提供一些整体的优化升级。当然,在尝试过程中,也发现了不少适用于通用前端项目开发的一些故障排查与性能评估的手段,于是总结此文,希望可以对读者有所帮助。
需要注意,在本文中所指的客户端均指通过 electron 开发出来的客户端应用,所以本质上还是属于前端应用开发范畴,关于 electron 框架的介绍可以参考 https://www.electronjs.org/
在客户那边,反馈过来的现象表现为“系统 CPU 资源未被占满,但客户端在操作一段时间后便卡死无法响应”。起初,我们根据用户的描述尝试在本地复现,但却没有收获;此外,由于客户的网络限制,也不方便频繁的远程连接以方便我们查看现场现象。
考虑到可能是机器部分配置较差(比如显卡)或者网络、机器自身运行软件过多等原因,而我们的开发机器由于要支持本地编译与调试,一般都是顶配机器,于是我们尝试让本机变慢,以模拟复现其现象,简单来看,存在如下几个思路:
来到客户现场,作为首要尝试,当然是通过 top
、netstat
或者 cat /proc/cpuinfo
等命令来查看系统的 CPU、内存与网络的运行状态,但不出所料,这些信息在当前看来并没有太大异常。
由于从系统本身的一些状态上没能找到突破口,我们将目光转向客户端本身,希望在更小的范围内定位问题所在。通过 devtools 查看 netowork、performance 以及 DOM 渲染状态,我们只能发现貌似有些响应耗时过长的接口调用以及较长时长的 long task 任务,这当然需要我们进一步排查。
说到调试排查,首推的当然是 console.log 大法,为了让 log 打印复用,一个简单的技巧是写一个 HOC,以节省在每个地方都写一遍 debug log 的代码:
export const debugRender = <T=any>(BaseComponent: FC<T>) => (props:any) => {
console.log(`Rendering ${BaseComponent.name} at ${performance.now()}`);
return <BaseComponent {...props} />;
}
通过添加一些基于经验的断点信息打印,我们发现一些 Modal/Drawer 的显示/隐藏会较为明显的加重页面卡顿甚至到卡死现象上,通过排查代码实现以及查看对应 UI 库的 API 实现,会发现其中 Modal/Drawer 等组件上在隐藏时触发了其对应 DOM 节点的卸载,而在显示时又会重新渲染与插入,由于这些任务都需要在浏览器的渲染进程执行,而当 DOM 节点过多时频繁的节点装载与卸载便会对页面渲染效率产生影响。
于是,第一步便是定位到主要的几个组件,避免其在隐藏时执行 DOM 卸载(保留节点),通过这一步改变,我们直接消除了卡死现象。
为了更好的模拟卡顿现象,我们可以通过 chrome devtools 中 performance tab 中的 CPU throttling 配置来模拟卡顿:
在 Windows 高配版机器上,我们先将 CPU 降低配置 4x 情况,然后录制一段操作,从下图中可以看出有明显的任务执行耗时过长 & CPU 占用过高的现象:
以耗时最长的任务中占用时间最长的活动为例,我们搜索一下该关键词可以查到一个讨论 https://stackoverflow.com/questions/39916356/reacterrorutils-invokeguardedcallback-in-react-fires-event-repeatedly-in-ie-brow,简单来说,我们可以尝试优化点击事件不进行冒泡来减少事件的触发,例如:
event.stopPropagation();
通过优化该事件,我们可以一定程度上对事件在 DOM 上的传递 & 调用进行优化,但说到交互事件模型,我们在实际优化尝试时,也需要对 Web API 有些了解,以防用错 Web API 而南辕北辙,比如一个常见的面试题就是对比 Event 上暴露的两个 API stoppropagation
与 stopimmediatepropagation
的用途区别,可别用错了。关于此细节可以参考回答 https://stackoverflow.com/questions/5299740/stoppropagation-vs-stopimmediatepropagation
但假如我们需要针对不同事件切换不同的 API 该怎么办呢,这里可以简单写个函数封装一下,再加个类型守卫来实现,比如如下的伪代码通过传入一个点击回调事件,而后在实际事件触发时通过判断 Event 类型从而调用不同 API 以达到优化效果:
const isMouseEvent = (event: Event | MouseEvent): event is MouseEvent => 'stopImmediatePropagation' in event
export const stopPropagationWrapper = (handleClick: Func) => (event: Event | MouseEvent) => {
if (isMouseEvent(event)) {
event.stopImmediatePropagation();
} else {
event.stopPropagation();
}
handleClick(event);
};
我们继续针对卡顿问题的调用情况进行梳理。从录制的执行队列中选取较长的一个 long task 进行分析,可以看到在模拟卡顿时排名靠前四的调用任务分别如下:
其中 fsync 函数调用时间占第一,而拆分 fsync 的活动调用可以看到主要调用了 fsyncSync:
此处未对 fsync 进一步分析以确定优化策略,但对于 fsync 的作用可以参考如下一段描述:
fsync 函数只对由文件描述符 filedes 指定的单一文件起作用,并且等待写磁盘操作结束,然后返回。fsync 可用于数据库这样的应用程序,这种应用程序需要确保将修改过的块立即写到磁盘上。
这说明应用中有可能有数据库读写操作,也可能有文件读写操作,所以如果要进一步优化的话可以从这个方面展开,囿于时间限制,我们继续探索可行的快捷优化方案。
在最初解决卡死问题时,我们看到了过多的 DOM 卸载/挂载现象,但回到前端框架本身,我们也可以用一些常规的手段来减少组件不必要的 rerender,这些方案通常通过仔细阅读 React 文档便可以略知一二,比如在必要的地方增加 memo 以减少不必要的渲染执行,一个示例代码如下:
import {
FC,
memo,
} from 'react';
const Detail: FC = ({}) => {
return (
<div>Detail</div>
);
}
export default memo(Detail);
此外,还有什么写法可能会影响 Web 应用的性能呢?闭包。
我们检查了客户端代码仓库里的两个列表文件,发现其中组件包含过多闭包变量,大多数写法是在一些函数定义中直接从上层作用域引用了一些变量进行操作,而不是通过参数传入函数,这样的数据/函数在使用后无法及时释放内存空间,可能会对内存存在持续占用的现象,因此,这也是优化的方向之一。
在一些 long task 任务的分析中,我们还可以具体定位到代码来进行优化,这里再举一个例子。
通过录制卡死情况下的堆栈调用情况,可以发现有一个 2.7s 任务中包含很多活动,如 Minor GC、react event、fsync、ReactElement 等等,其中 mergeProps 函数调用耗时250+ms。
针对这些函数调用,有些可能是 React 内部实现 API,有些可能是 UI 库 API,所以要想一一优化,也需要逐个分析,看是优化代码的调用与响应方式,还是合并组件 props 的传递与调用。
此外,通过监控 layers 变化情况,也会发现一些 slow scroll rects,这在 chrome 中都会通过红色区域以标注出来,通过定位这些在滚动中可能会造成缓慢的区域并检查代码,也有提升应用性能的可能性,因此,也是优化方向之一。
比如针对我们的场景,通过调整 layer 布局,可以看到虽然 layer 层级很多,但是主要的 slow scroll rects 区域还是集中在主内容区,即分页列表本身。
本来,为了可以针对这些数据进行持续的分析,想从 performance 中将数据下载下来,以便之后有空时继续调试,但由于 Electron 的某些限制或者说是错误,我们目前无法保存 performance tab 下的性能数据到本地以便进行更深入的分析和查看。如果有涉及到 electron 开发的场景,需要注意下这个问题。问题现象详见 issue https://github.com/electron/electron/issues/39818
为了提高客户端的性能和用户体验,我们进行了一系列的优化措施。首先,我们分析了卡死现象,包括客户端出现卡死时的 CPU 占用率/JS 堆栈/DOM 节点数情况、虚拟机运行状态等。然后,我们尝试了一些优化措施,如去除Modal/Drawer的 unmountOnExit 配置等。接下来,我们梳理了卡顿问题调用情况,分析了排名靠前的四个调用任务。为了减少组件不必要的rerender,我们在必要的地方增加了 memo。此外,我们还提到了组件中包含过多闭包的问题,以及右键菜单卡顿问题的排查。
由于客户端需求迭代过快,在前端技术上没有做较多的数据监控、性能评估等建设,这都对我们评估用户体验与定位问题产生了影响;此外,由于生产工具链的不完善,在生产环境进行定位与调试都给我们带来了比较大的挑战与时间消耗,这也会是我们持续要跟进与解决的一些开发链路的效率提升工作之一。
通过这些优化,我们希望能够解决客户端卡死问题并改善卡顿现象,并提高用户的使用体验。当然,从具体效果上来看,我们确实在如下两个方面进行了改善:
以下为优化后效果采样图:
通过分析与优化尝试,我们解决了客户端卡死问题,并改善了卡顿现象,但其中暴露出一些编程规范与用法不够优雅的问题还需要在日常中持续完善,这也是这次优化未尽事宜,需要在未来不断排期以彻底解决。
当然,此中涉及到的一些调试与问题定位方法,也不仅局限于客户端的问题排查,而是通用 Web 应用性能评估时调试可以用到的手段,而更深入的研究则要开始涉猎到框架代码等内部函数调用的地方了,这也是本文未涉及部分,有待后续继续研究与定位。
2023-12-24 00:00:00
这一年里充满了各种变化,也有不少东西值得记录,比如令人满意的健身打卡,逐步调整的投资仓位,以及通过阅读学习和出行游玩收获的喜悦。
但当我准备动笔记录今天的忙碌故事时,却突然感到思绪断片,不知从何说起。他们就像一段段孤立的片段,突然间收起了各自本该伸出的突触,毫无关联。让我努力编织下,希望可以拼凑出一个完整的年度回忆。
虽然本就没几年经验,但在我的投资生涯里,很早便认可了“投资是自我认知的变现”这一投资信条。面对年复一年地亏损,我一直保有谦逊的态度,认为这是我对事物认知不够的结果,也是我所需要交的学费。年复一年,而我却越挫越勇。每当我收到工资时,我首先想到的是”我有钱可以增加投资了”,直到钱花光,然后我又开始努力工作,等待下个月的薪资。不断地增加投资,不断触及新低,让我不禁感叹,我自己就是那个最健康、拥有永续现金流的优质资产(在中年危机被裁员之前)。
在不断学习的过程中,我尝试过使用美林时钟来辅助我在当前世界的变化中调整不同资产的投资比例;通过关注恐惧贪婪指数、北上资金动向以及全市场成交量来控制我的资金进出节奏;还构建了自己的价值评分系统,用于评估购买资产和确定应对策略。可惜,直到最后都逃不过“一顿操作猛如虎,最后像个二百五”。
但这并没有阻止我对投资越来越沉迷。今年,在各种空闲时间里,我仍然花了大量时间阅读书籍、观看纪录片与调整资金进入策略,也主要补齐了对2008年金融危机及欧债危机期间世界各国发生的事情与各大央行的应对策略,而对这些历史事件的了解,也让我对当前发生的许多时事有了更敏锐的感触。当然,最深刻的印象仍然是通过真金白银的投入去理解和观察这个世界究竟是如何运行的。
尤记得刚接触投资不久,我便困惑于两个问题,他们是如此明显但我却找不到答案,以至于我开始怀疑自己的信息检索能力。
“为什么有很多关于价值投资的声音都在介绍通过定投降低风险与长期持有,但却很少提及何时卖出与落袋为安?”,这让我很不解,涨的再多,没有在合适的时机卖出,也没法落袋为安啊。而后来,随着“核心资产”泡沫的狂欢在2021年春节后戛然而止,伴随着飞流直下三千尺式的暴跌,那些宣扬十年定投赚十倍之类的响亮声音也从市场上消失了。我逐渐开始明白,这并不是因为市场没有这类声音,而是我一直追逐的都是“跟风”和“主流”,而不是真正的“价值”。
另一个问题,从我开始规律地研究公募基金定期报告以来,无论是谈到跨过刘易斯拐点带来的挑战,漫长的三年疫情带来的创伤,还是面对欧美的科技封锁与孤立,基金经理们貌似都一直坚定地看好中国。我很好奇,这个国度究竟有什么是世界上其他国家所无法企及与不可替代的吗?后来我发现,原来股市是不可以做空的。
再后来,我所遇到的问题也越来越多,但一个个也在不断的探索与学习中得到了解答。虽然我相信权益类资产在长期来看会是最有吸引力的投资标的,但离钱越近的地方聪明人也就越多,这就意味着我需要长期投入、学习与进步。投资就如同生活的投影,预设目标,不断努力、尝试,达到目标、总结与规划,如此反复,而这也是他一直吸引我的原因所在。
一本书可能很厚,但一纸书页很薄。每一次翻页都如同一程短暂的摆渡、一场微小的跋涉,身后欧律狄刻的目光仍未消散,远望伊西斯的面纱已然显影。
这是在今年世界读书日,给读者推送我的书摘时,从豆瓣上摘抄的一句话。以前,不论是地铁通勤,还是周末进城,抑或是出远门见朋友,我都时常手捧一个 iPad 会看上几页,就这么零零星星地,每年能看上几十本书。但今年因为运动打卡挤占了原有的时间,加上工作强度增加,以及频繁跑医院,少了很多碎片时间,分配给读书的时间也有所减少。有鉴于此,周末没事时,我时常花上整个整个的半天,用来阅读。期间去过几次图书馆,一呆就是一个下午,除了接水也不起身。安安静静的,啥也不做,就盯着屏幕,希望从字里行间收获快乐。
虽然从时间上相比去年有明显减少,但今年的收获仿佛更加实在,说说几个比较贴切的例子吧。想起年初去医院看病,为了治疗痤疮,前后一共吃了好几个月的药。后来,在阅读《皮肤的秘密》时,我对许多现象以及对待皮肤问题的方式有了新的领悟。当我们的皮肤状况变差时,真的需要那么多昂贵的护肤品来挽救吗?也许不是,也许只需要一些药膏就能解决大部分问题。当然,更重要的是我们不要过度清洁皮肤,保持规律的作息习惯。
当然,由于对身体机理运作以及病菌原理感兴趣,我又淘到了一本《我们为什么生病》。在阅读时,不仅有“疾病不是因为我们弱,而是这个世界有些东西变化太快了”的感慨,还在豆瓣偶遇到张一鸣同学的书评“其实进化论强调:你看到的是结果”。阅读之后,虽然对于癌症、衰老、过敏以及身体机理应对自然变化的机制有了更多了解,但更现实的是,我逐步认识到了时间对世间万物的一视同仁:不论君王庶民,我们都无法与之对抗。在时间面前,我们无论做些什么都无法避免衰老、死亡,而这引发我对生命存在的意义更具象的追求。
经济类书籍每年都必不可少。对经济危机与大萧条研究颇深的伯南克在《行动的勇气》中详细描述了自己在美联储工作的那段经历,从房地产泡沫破裂到雷曼兄弟的大坝决堤,及其引发的全球金融系统崩溃等事件,事无巨细,同时也花了很大篇幅揭示他与保尔森、盖特纳一起协力、果断扑火的各种努力。从全球合作到最终退出量化宽松政策,伯南克感慨到自己还是做了不少努力并卓有成效,他最后为美联储在危机之后所作的努力总结道:
我意识到金融冲击往往是不可预测的,因此还鼓励幕僚们寻找金融体系的结构性弱点,想办法使它更有弹性。这个想法已经体现在了我们的许多改革中,比如要求更高的银行资本充足率,提高银行体系吸收损失的能力。
每当阅读此类书籍,都会让我对世界上各种复杂、高级别的组织更加了解,而满足这些好奇心也是促使我坚持阅读的一大动力。为了前方的未知与愉悦,直到最后一页。
作为一个准奔三青年,我仿佛变得越来越怀旧了。还记得从上大学之后开始就再也没看过快乐大本营这类综艺节目了,但今年却一股劲又盯上了很多芒果台的综艺,而且还是反复观看。从时光音乐会到声生不息,从宝岛季到家年华,我发现我非常偏爱音乐类节目。很多耳熟能详的老歌,再配上我“听歌很少关注歌词,而只享受旋律”的习惯,当那一阵阵旋律响起时,仿佛把我又拉回到那些历历在目而有印象深刻的故事中。
今年养成的习性不仅怀旧,而且养老。今年我还尤其喜欢逛公园,奥森、颐和园、北海公园、圆明园、什刹海以及各色大大小小的北京园子都被我逛了个遍,一是趁着天气晴好看看应季花景,再者也是与许久未见的朋友散心聊天、联络感情。
当然,除了养老之外,我还异常养生。我跟朋友说起我每天的生活时,他们都觉得我已经是个新时代的合格健康老头了。每天上班第一件事便是到茶水间泡一杯热茶,按时吃饭,以及没有意外时会规律的去健身房转转练练,晚上也尽量避免熬夜,一有点啥问题也会跑到医院抓个医生问个究竟。周末呢,要没啥事,就到楼下超市买个菜回来做饭,虽然不是什么复杂菜品,但那些健康而平淡的家常味道,已经让我感到非常满足。
刚说到今年经常跑医院,如何形容这个经常呢,我统计了一下截止今天的医保支出,一年23000+,这还是在没有什么大病的基础上的花费。仿佛年龄越大,就越怕死,今年的我,时常因为一些小毛病而频频往医院跑。虽然确实有一些值得一看的小病,在遵循专业医师的建议与处方下,也让自己变得稍微健康一些、好看一些了,但不可否认,还是有一批是来自“怕死焦虑”的变现。上个月我刚体检完,报告上标红了五六项,我辗转反侧,无法理解为什么坚持锻炼的我还有这么多毛病,于是,几个三甲医院一顿约,主任副主任医师一起抢,我一定要搞出个究竟来。不过到头来,好几个科室的医生面对来自我“如果这不是问题,那为什么我有别人没有”的有罪推论式发问,都不耐烦的回复“不要过度焦虑,这些只是个人差异,而不是病症”,终究还是让我宽心了不少。
说到健身,最让我自豪的便是今年里在大部分时间我都持续着高强度的锻炼节奏。从每天游泳打卡,到下班后跑步,以及在同事的辅导下开始器械训练,年末时也参加了几节团课训练。每次运动完,都能明显的感觉自己的状态好了一些,而要不了多久,便又开始期待下一次的健身打卡及其带来的快乐。想起前几天看到一位投资者面对记者采访时说到,因为自己前一天熬夜状态不好,希望摄影师用一些“手段”将自己拍的更得体与优雅些,“一个好的状态与形象,既是对自己、也是对观众的交待”,这是他给的理由。逐渐沉溺于健身的我,非常认同这番话(当然,只是自己长得丑,和他不像而已)。取悦自己,找到自己愿意去做的事情,仿佛是一个奔三青年眼前最重要的事。
今年的我不仅变得异常怕死,同时也希望对自己查漏补缺。今年,我预约过几场心理咨询,也从中获得不少收获。探寻自己在家庭沟通上的一些失控情绪表达,找到内心潜在的一些心理缺陷并尝试修复,而这些都是我以前不曾涉足的领域。
我从原生家庭继承了一些执念,而时常又不自觉将这些执念寄托回他们身上。由于自己的认知仍在不断拓宽,一些强行灌输给他们的想法,在没有得到妥善处理时,便引发了不可避免的矛盾,这通常体现为我的大声说话与争吵。今年看的一本书《原生家庭》,帮助我对亲密关系以及性格缺陷有了更本质的一些理解,虽不至像书中一些案例一样中毒过深,但自己的成长或许也有从原生家庭习惯中隐性的吸到一些“毒气”。他们可能在生活的一些方面上具有闪光点,但却因为用力过猛而导致在其他一些方面上造成失控。与好几个朋友聊天时,他们对我都有相似的形容——能在工作上所向披靡,但回归生活发现很多事情都没有规划和过多想法。而在心理咨询后,我的这种行为被具象成了“由于无法得到满足,而对某些关系进行转移与嫁接”这样的标签。
年中出差成都,约了一个从小玩到大的朋友见面,我们聊了很久直到深夜,差不多绕着成都的高新区转了半个圈,期间探讨了很多事情,包括工作、未来发展、定居以及生活的方方面面,但在最后,他给我了一个标签,“你确实活得非常自律、严谨,就像个机器人,仿佛你的生活里只有黑白灰这三种颜色”。
我一时不知怎么接话,因为他说的确实在理,我只能笑笑,随意找了个借口回应道:“我确实没有什么物欲啊,很多人喜欢通过花钱来达到满足感,但对我不太适用;当然,投资亏钱除外。至于为什么要赚钱,一方面是为了‘安全感’,另一方面呢,也算是一种获胜的姿态吧,可以满足我的好胜心”。
就是这么一个黑白灰人格,既对亲人如此关心甚至到有些焦虑,而又对自己无欲无求、活得过于机械化,这也成为我要在新的一年去努力攻克的课题之一。
今年因为经常挂到医院一大早的号而早起,但也因此看到很多往常不曾见到的风景。阳光从树梢穿过,零星撒向地面;骑着单车,听到林间鸟叫、看到小区晨起锻炼的人儿;迎面与一个个充满朝气的少年相遇,从他们眼里真的能看到光。这是令人向往的风景,便也为此努力奋斗。
一点一滴,日积月累,这既是果实,也是漫漫人生。季节更替、时间流转,也望诸君可以缓慢而坚定地前进,去做自己能做的事情。新的一年,好好吃饭,好好锻炼,好好生活。