Categories
未分类

FOMO 的三层坏处

(图片来自 BBC Newsnight youtube.com/watch?v=VtH6kiPbMBw) 忘了在哪里看到Christopher Nolan的一个访谈,其中提到,说他不用现代化的科技,他没有email,甚至没有手机。如此,他多出来很多思考的时间。 没有手机。。。这对于“现代人”来说,简直是不敢相信的事情。包括我在内的很多人,一天不看微信、朋友圈、twitter,就担心自己错过了什么,实际上,有一个专门的词语来描述这种心理:FOMO(Fear Of Missing Out)。 我想了一下,结合前段时间看到的Elon Musk在JRE上面的访谈,我觉得被FOMO控制,不断的刷社交网络,带来的坏处有三个: 浪费时间无意义的刷feed,这是最显而易见,也是平时我们说的最多的。然而,这其实只是影响最小的一个坏处。 更重要的是,他会让你迷失方向。看到别人写文章,粉丝几百万,你也开始写文章;看到别人拍短视频,粉丝几千万,你也开始拍短视频。看到别人知识付费,月入几千几万,你也开始搞小圈圈。结果溜一圈下来,什么都没坚持到底,什么成果都没拿到。 它会让你产生不必要的自惭形秽心理。看到别人在旅游,你却在加班,你会想,为什么我这么惨,为什么我不在旅游?看到别人住高档奢侈的酒店,你会想,为什么我这么穷,为什么我住不起?看到别人年少有为财富自由成名在外,你会想,为什么我这么无能,这么失败,甚至觉得自己一无是处。 实际上,绝大多数人都只会把自己光鲜亮丽的一面晒在朋友圈。我们只会把跟对象甜蜜旅行的照片发在朋友圈,却不会把跟对象吵架的场景发在朋友圈。我们只看到别人在奢侈的酒店阳台喝下午茶,却没有想到,别人的酒店,可能是拼单的。我们只看到别人事业成功的瞬间,却没有看到别人付出的艰辛,成功之前失败的痛苦。 当然,我并不是说,要通过知道到别人过得不好,来让自己感觉好一点。我只是想说,没有必要在看到别人光鲜亮丽的一面的时候,自己产生自惭形秽的心理。每个人的生活都有好坏的一面,虽然比例不一样。但朋友圈,绝对不是一个人生活的全部。 可真正的问题是,这种心理的产生,我们是控制不住的。你在加班的时候看到别人在旅游,你就是会产生“我为什么这么惨”的想法,在你反应之前,这种想法就已经产生了。当然你可以事后再来安慰自己,说“每个人的生活都有好坏的一面,看到别人光鲜亮丽,我没有必要自惭形秽”。然而你不一定养成了这样的心理习惯,所以你不一定记得要这样去安抚自己的内心。此外,就算你记得,但在你反应过来之前的那几秒钟,你还是有了自惭形秽的想法。 至于第二点,对我来说,我就是一个喜欢创造东西的人,a creator of things。我只希望在一边工作上班的同时,自己能默默的坚持创造一些有用的,有意义的产品。虽然这不像拍视频、写文章那样,能用更短的周期得到反馈。(实际上,自己期待的是,用更短的周期,得到称赞,得到多巴胺)。但至少,在为了创造自己的产品而写代码的时候,我的心情是最平静和愉悦的。 说到底,还是老生常谈,少看微信,少刷点朋友圈,更不要无意识的、习惯性的刷朋友圈。写这篇文章把坏处整理一下,强调一下,或许我会更有动力来“戒微信”吧。

Categories
未分类

只做了两个小操作,让我的网站秒开了

昨天把自己业余时间写的web app极客微博放出来之后,自己又点了好几次进去看。然而每一次都觉得很慢,有一次使用Chrome DevTools查看,居然花了30秒多,这无论如何也是无法接受的。刚开始以为是我家里的网络原因,换成4G之后,确实有所提升,打开速度大概在3秒作用。然后查看资源文件,发现最大的js bundle有200多KB: 这还是太慢了,于是使用Google PageSpeed Insights分析,并根据里面的几个建议调整了一下。目前,我自己使用Cmd+Shift+R(跳过缓存)试了几次,都可以算是“秒开”了。 Google PageSpeed Insights desktop速度也达到了100分 具体来说,只做了两件事情。 缩减图片的大小 根据Google PageSpeed Insights的提示,在展示一条微博的时候,geekweibo.com使用的是图片的原始尺寸: 我自己的头像达到500多K,这无疑增加了加载时间。 我的图片是放在阿里云OSS上面的,根据阿里云的api文档,加上自动裁剪的参数,就搞定: <img :src=“${tweet.user.avatar}?x-oss-process=image/resize,m_fill,h_100,w_100” /> 启用gzip压缩 在nginx config里面加上: location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { gzip_static on; expires max; add_header Cache-Control public; } 也就搞定了。 再次刷新,立刻能感觉到,网站打开的速度快多了。在使用chrome devtools查看,资源小了很多: Google PageSpeed Insights、图片使用适当大小、gzip压缩,这些对于一个web开发来说,都是最基本的常识。不过,如果刚开始接触这个领域的话,这些东西,还真不一定知道。

Categories
未分类

开源了一个类似于Twitter的项目:极客微博

这是个什么东西? 如题所说,这是一个类似于Twitter的项目。目前还是WIP,有一些最基本的功能:发推文、搜索、评论、点赞、通知。 为什么要做这个项目呢? 主要有两个原因。 一方面,目前对我来说,twitter是我最主要的技术咨询来源。我会在twitter上面关注很多技术博主,从他们的推文中,了解到最新的技术咨询、发现一些好的技术文章、或者是学习到一些tip and tricks。但是国内并没有这样的一个,可以让人用来发现技术的一个地方。微博?你是说那个看娱乐八卦新闻的网站吗? 另一方面,我一直就想有一些地方,能够用来存放和分享一些比较零碎的东西。比如,我经常会发现自己一遍一遍的去google相同的一个问题,而这个问题真正解决的办法,可能就一两行代码。因为不记得,所以只能下一次遇到的时候,再去google一遍。而其中有一些问题不是一google就出来了,这就很浪费时间。这时候,我就希望有一个地方,能够用来存放这些解决问题的答案,这样的话,我下次直接到那个地方去搜关键字就好了。你可能会想,为什么不放到一些笔记类的app里面,比如Bear、evernote等。在我的心智中,这些app就是用来记录比较长内容的笔记。如果一篇笔记里面就一两句话,我总是会觉得好像太浪费了。同时,这些长短的笔记夹杂在一起,也不是很好浏览和管理,在一个问题,就是放在自己的私人笔记里面,不是很好分享。类似这样“无处安放”的内容还有,代码上发现的一种好的写法,发现的一个好的命令行工具,阅读时看到的一两句觉得挺有道理的话,等等。 因此,出于 简单记录、分享和发现的需要,我写了这样一个项目。 为什么不用。。。 为什么不直接用Twitter呢? 有三个原因: Twitter不支持markdown,对于技术方面的知识片段来说,格式不够用,可读性不够高。 Twitter发布比较麻烦,要FQ并打开网页,而手机上发布则更加麻烦。很多时候,我只是想纯粹的发布一条记录一下的,但是打开网页就会看到很多干扰我注意力的内容。我试过很多的发布工具,比如rainbowstream,但是都不尽人意。也试过自己申请开发一个twitter app,但是被拒了。 Twitter上面还是有一些非技术的内推,这些东西,有的时候是有用的,有的时候就只是娱乐性的,浪费时间。 为什么不用Hacker News Hacker news主要是以分享链接为主,链接到某一篇文章,我希望能直接发布(同时也直接看到)内容片断本身。此外,HN上面的内容也不一定技术相关的,虽然技术占的比例确实很大。 为什么不用V2EX 跟HN有点类似,一方面,V站的首页显示的是链接(标题)列表,而不是内容本身,另一方面,V站的内容也不一定技术相关的,虽然技术占的比例确实很大。 为什么不用掘金、简书、知乎。。。 这些网站目前是以(较长篇)的博文为主的,对于我的“知识片段”的需求来说,有点过重,使用成本有点高。 说到底,可能是因为我是处女座,所以对所用的东西特别挑剔,希望能尽量完美的契合自己的需求。 (计划中的)项目特点 作为一个“简单记录”为重点功能的工具,这个工具最大的侧重点,就是“发布”这个功能会做的非常简便,工作量极小。我打算做很多的工作,来达到这个目的,目前想到的一些方法如下: 命令行工具 Alfred 插件 Chrome 插件 使用系统快捷键,直接读取剪贴板内容发布 用到的技术栈 Ruby on Rails Ruby 2.7.1,Rails 6.0.3.2 VueJS, AlphineJS TailwindCSS PostgreSQL ElasticSearch 项目地址:极客微博 欢迎体验、吐槽、反馈 Github地址:ChrisZou/geekweibo 欢迎star、fork、pr、issues

Categories
未分类

如何准备字节跳动的面试

因为在朋友圈和微信群招聘信息发的多,平时经常被问到如何准备字节跳动的面试,尤其是算法题。同时,自己在面试人的过程中,也发现有一些常见的方面,很多朋友表现的不是很好。因此,写了这样一篇文章,共大家参考。准确的说,这里的准备方法其实适用于绝大多数的互联网公司,不过,因为我自己只是在字节跳动,我没有办法为其他公司说话。 一个技术面试内容,主要分成三大块: 项目经历 基础知识 编程题 项目经历部分 面试官可能会问你,做了什么,用了哪些技术,遇到什么困难,怎么解决的。 这几个问题,建议可以对着自己的简历,思考一下如何回答。 除此之外,来有两个注意事项,最好也准备一下。 一是原因,比如说你做某一个需求,业界有ABC三种方案,你为什么用了A方案,而没用B或C方案。 二是原理,比如说你用了某个开源项目,它的实现原理是什么?最好是代码看过,如果没看过的话,要知道核心原理。 基础知识部分 这部分其实更多是取决于平时工作中,遇到问题,多总结反思。不过如果想要速成的话,也不是没有办法。最简单的就是,你Google一下所谓的“常见安卓面试题”,把里面的题目都背一下,应该就差不多了。因为如果你多面试几个公司的话,你会发现大家问的问题都差不多,就是那些。 当然,也不是鼓励大家死记硬背,只不过,很多地方,确实需要记忆,所以,就是这个意思。 最后,是编程题部分 字节跳动的每一个技术面试环节,都会有编程题,这是公司规定的面试流程。这部分的准备其实也很简单,一句话就是刷LeetCode,刷个几十道题。具体多少,跟每个人自己的基础有关。不过,认真做的话,最多一百道,基本就不会有问题了。 关于面试,就说到这里,其实你会发现,上面说的内容,不仅仅适用于头条,这里说的准备方法,可以应付绝大多数的互联网公司。此外,说起来容易,做起来可能不容易,你要搞清楚自己用过的技术,框架的代码、实现原理,这个不容易。 “常见”面试题,可能也不少,要理解他们并记住,也不简单。 最后,刷一百道leetcode,也不是一件容易的事。 总体下来,可能需要几个月,具体看每个人的基础。 不过,用几个月的努力,换一份待遇好、成长快、有挑战有趣味的工作,我个人觉得是非常值得的。 如果你准备好了,可以随时找我内推,过程中有任何问题,也可以随时联系我。

Categories
未分类

AndroidStudio调试小技巧

我在这一行代码打了个断点: 我能不能让代码走到这里的时候,IDE不停下来,而是打个log出来,告诉我代码走到这里了呢? 你可能会问,为什么,你为什么会有那样的需求? 因为我只是想知道代码有没有走到这里,并不是想让它停下来。 你可能又要问,你在那个地方加一行log,重新运行不就好了吗? 这样做确实可以,但是如果你的项目特别大,运行一次需要几分钟甚至十几分钟的时候,你就会尽量避免修改代码重新运行。 这时候,如果你手机上已经装了这个app,你就会想要通过断点的方式,来判读代码会不会走到某个地方。 这就回到我们开头的问题了,能不能让代码走到那个断点的时候,不停下来,而是打个log出来,告诉我代码走到那里了呢? 我探索了一下,发现确实可以! 在调试面板点击这个图标: 会出来下面这个界面: 左边选中相应的断点,勾掉“Suspend”,勾上“Breakpoint hit” message,如下图所示: 再次进行相应的用户操作,触发断点的代码,在调试面板的“Console” Tab,你就会看到断点打出来的log,表示这行代码被触发了。如下图所示。 在这里,你甚至可以自定义打印的log内容,勾上“Evaluate and log”,输入你想要打印的表达式,如下图所示: 效果如下:

Categories
未分类

我最近开始省钱了

为什么这么说呢?因为我之前不省钱。那为什么以前不省钱呢?因为我听说了这么一句话: 你能挣到的钱是无限的,你能省下的钱是非常有限的。所以你应该集中精力去赚钱,而不是想方设法省钱。 但是为什么我最近又开始省钱呢?因为我发现这句话错了! 这句话有两个错误的地方。 第一:她说“你能挣到的钱是无限的”,但其实这个无限只是理论上面是无限,实际操作层面,一个人一段时间之内,他能挣到的钱其实是有限的。至少在我身上是这样的。我们做决定,应该从实际情况出发,而不是从理论的可能性出发。 第二:这句话人为的制造了对立。实际上,你可以努力赚钱的同时,也在很多地方努力多省点钱。这两者并没有时时刻刻的对立关系。 所以,你判断要不要省钱,应该从ROI的角度出发去考虑。那就是,针对某一个具体的场景,如果你选择省钱,你需要为省钱付出多大的代价,然后你能省下多少钱,你省下的钱,值不值得你为之付出的代价,如果值得,那就应该选择省钱。 这是你要考虑的问题。

Categories
未分类

Ruby 2.7.0 上手体验以及问题记录

正如过去的每个版本一样,Ruby 最新大版本 2.7.0 在圣诞节那一天正式发布了。空下来以后,我第一时间开始使用了。因为里面有一个我期待已久的新功能,那就是 block default parameters。 在 2.7 以前,Ruby 里面写一个带参数的 block 是这样的。 [1, 2, 3].each { |item| puts item } Block 的参数放在两个|中间,这跟目前流行的大多数语言都不一样,非常的不直观,而且这个|符号也不好敲。 在 2.7 以后,你可以用_1 来引用第一个参数,_2 来引用第二个参数。所以,上面的例子就变成了: [1, 2, 3].each { puts _1 } 少敲几次键盘,简直爽呆了,懒人的幸福就是这么简单。 说一下升级过程中遇到的几个问题。 1. 使用 rvm 安装,下载时间特别长。 如果你使用 rvm 来安装、管理 Ruby,那使用 rvm install 来安装一个 Ruby 版本的时候,rvm 会先从travis-ci寻找 binary。如果找到了,则直接下载 binary 安装。不然的话,会从 ftp.ruby-lang.org […]

Categories
未分类

PostgreSQL 数据库从9.1版本升级到11.5

## 起因 === # 如果你不想听我自言自语,请跳到以下“升级”部分。 随着年龄越来越大,我在技术上的“最求”也变得更保守了,慢慢的,我开始信奉这样一句名言 Don't fix what's not broken — 不知道是谁说的不过不是我 这次选择这么大跨度的一个升级(很大吗?是的,9.1版本是2011年发布的,那一年,我还没毕业)自然是有原因的。 之前说过,打卡团服务器是用Elixir(一门语言)/Phoenix(一个Web框架)写的,这是个错误。至于为什么说这是个错误,以后有时间写写(这句话好像之前说过?)。 于是,最近一直想把它迁移到我信仰的Ruby on Rails(RoR)。当然,“迁移”是没时间迁移的,永远都没时间迁移。准确的说,是新功能用RoR开发,原来的功能就留着(“Don't fix what's not broken”,remember?)。 但是搭建好Rails scaffold之后,发现数据库连接不上。老是提示这样一个错误: Traceback (most recent call last): 2: from (irb):4 1: from (irb):4:in `rescue in irb_binding’ ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: relation "pg_range" does not exist) LINE 3: LEFT JOIN pg_range as r ON oid […]

Categories
ml 未分类

我对Embedding的理解

Embedding是NLP中,用来表示一个词的常见的方式。不过,他的用途其实不仅仅可以用在NLP中,在简单的线性回归或逻辑回归中 ———— 进而在神经网络中,也可以使用到这个东西。 我当初在学习Embeding这个概念的时候,花了比较长一段时间才算真正理解。我不知道到底是这个概念本身理解起来就比较难,还是容易遗忘的原因。Anyway,因为这一点,我决定写一篇文章,说说我对Embedding的理解。 在回答什么叫Embedding之前,我们先提出一个问题:给定任意的两个东西,怎么样来衡量他们之间的相似性呢? 举个例子,比如说,牛奶、咖啡和苹果。通常意义下,可能大部分人都会认为“牛奶”和“咖啡”更相似,其他两对组合“牛奶”和“苹果”以及“咖啡”和“苹果”没那么相似。 如果要进一步问为什么,大家可能会说,“牛奶”和“咖啡”都是液体,都是可以喝的,都是常见饮料,都是装在杯子或瓶子里面的等等等等。也就是说,我们会想出某一些角度,或者说一些特征,来衡量他们的相似性。这些“角度”或者说“特征”,我们用稍微显得专业一点的词来说,叫做维度。 如果我们把主要考虑的几个维度简单的列一下,可能会得出以下的一些: 是否食物、是否液体、是否需要人为加工、颜色、味道等等。列出这些维度以后,我们可以给这三个考察对象的每一个维度都分别“打个分”,分配一个数值。如下: 是否食物 是否液体 人为加工 颜色 味道 牛奶 1 1 0.8 -1 1 咖啡 1 1 0.9 -16777216 2 苹果 1 0.2 0.1 -16711936 3 你可能会有疑问,是否食物、是否液体、是否人为加工的数值都是小数,可以理解为“在多大程度上是食物/液体/人为加工”,但是颜色和味道的值怎么理解呢? 在上面的表格中,颜色的值我取得是Java中Color类的WHITE、BLACK、GREEN三个常量的数值。味道的三个值是我随便取得,你可以理解为,我们可以把每一种味道都用一个数字来表示,然后1、2、3分别是代表牛奶、咖啡、苹果的味道的数字。不用过分纠结这里的数字具体是什么值,这里只是举例说明一下原理。 好了,现在我们确定好了这些“维度”,并且给我们的考察对象在每一个维度上面都打了分,那么我们就可以用一个向量来代表我们的一个考察对象了。比如: 牛奶:[1, 1, 0.8, -1, 1] 咖啡:[1, 1, 0.9, -16777216 , 2] 苹果:[1, 0.2, 0.1, -16711936, 3] 每个对象对应的向量,就是表格中对应的那一行。这里的向量,其实就叫一个Embedding。如果要用稍微正式的语言来陈述一下,那就是:一个Embedding,就是用于描述某个实体的一个向量,这个向量里面的每一个值代表这个实体在某个维度上面的“打分”。 在实际使用的过程中,Embedding的生成过程可能跟我们上面讲述的过程不大一样。我们先来看一下PyTorch里面,Embedding的使用是怎么样的。 >>> import […]

Categories
未分类

PyTorch自动求导(Autograd)原理解析

我们知道,深度学习最核心的其中一个步骤,就是求导:根据函数(linear + activation function)求weights相对于loss的导数(还是loss相对于weights的导数?)。然后根据得出的导数,相应的修改weights,让loss最小化。 各大深度学习框架Tensorflow,Keras,PyTorch都自带有自动求导功能,不需要我们手动算。 在初步学习PyTorch的时候,看到PyTorch的自动求导过程时,感觉非常的别扭和不直观。我下面举个例子,大家自己感受一下。 >>> import torch >>> >>> a = torch.tensor(2.0, requires_grad=True) >>> b = torch.tensor(3.0, requires_grad=True) >>> c = a + b >>> d = torch.tensor(4.0, requires_grad=True) >>> e = c * d >>> >>> e.backward() # 执行求导 >>> a.grad # a.grad 即导数 d(e)/d(a) 的值 tensor(4.) 这里让人感觉别扭的是,调用 e.backward()执行求导,为什么会更新 a 对象的状态grad?对于习惯了OOP的人来说,这是非常不直观的。因为,在OOP里面,你要改变一个对象的状态,一般的做法是,引用这个对象本身,给它的property显示的赋值(比如 user.age […]