像许多公司一样,简街是以分布式模式运营的,实习也是如此。这意味着要做一系列不同的事情,包括重新思考我们如何让实习生上岗,并将他们分配到项目和团队中。
我们做出的一个改变是实习生被分配到项目的方式。在平常的一年里,实习生们会在技术组织的完全不同的部门做两个不同的项目:一个实习生可能会在上半个夏天从事LDAP实施工作,另一个实习生可能在下半年从事缓存来自Exchange来源的市场数据的快照的工具。
虽然我们认为这种多样化的体验有它的好处,但我们觉得今年我们不能公平地做到这一点,主要是因为时间限制。所以今年我们给每个实习生分配了整个夏天的单身女实习生。
这意味着每个实习生有更少的项目,但仍然有太多的项目要全部讨论!因此,像往常一样,我选择了几个进行更详细的说明:
Henry Nelson为异步RPC构建Wireshark插件的项目,异步RPC是一种常见的内部消息格式。在此过程中,Henry构建了一个通用库,用于在OCaml中构建Wireshark插件。
张玉兰的项目是构建一个自动共享交易系统的应用程序,以更好地平衡他们所需的资源,从而提高性能。
Eric Martin的项目利用一些奇特的测试,帮助我们从陈旧过时的正则表达式库中迁移出来。
Wireshark是一个用于检查和查看网络流量转储的交互式工具,它是一个非常有用的调试和分析工具。它可爱的功能之一是开箱即可理解2500多种网络协议。
当然,这并不意味着它理解我们的内部协议。不过,没关系!Wireshark有一个插件接口,可以添加对任意网络协议的支持。Henry今年夏天的项目是为Async-RPC编写一个插件,这是我们到处都在使用的内部开发的协议。
为了支持异步RPC,您需要处理许多不同的位和片段。首先,您需要编写知道如何解析异步RPC的核心心跳、查询和响应消息的代码。您还需要能够处理在多个数据包中分解的消息,甚至需要进行依赖于数据的数据包重组。您还需要处理解密,因为我们将Kerberos用于某些消息流。
所有这些都可以通过或多或少直接针对Wireshark的标准命令式C API编写来实现。但这似乎不是一个好主意,因为该API很棘手,很难推理。此外,通过直接针对C API编写代码,最终得到的解析器不能在不调用所有Wireshark功能的情况下进行合理测试。
取而代之的是,Henry编写了一个接口,允许您以一种从与Wireshark交互的具体细节中抽象出来的方式编写数据包解析逻辑,并将潜在的多阶段解析过程封装在所谓的一元接口中。单体的细节并不重要,但关键是我们可以使用特殊的let%bind语法来标记我们将控制权交还给Wireshark以获取更多信息的位置。
(*从lib/async_rpc_kernel/src/protocol col.ml*解析Message.t)让parse_message query_ids树字段=let open Parse。LET OPEN字段中的LET_SYNTAX。Let%bind message_type中的RPC,subtree=Wireshark_tree。添加项目树字段(_I)。匹配message_type中的message_type与|心跳-&>;返回查询ID|query->;parse_query query_ids子树字段|Response->;parse_Response query_ids子树字段。
Wireshark_tree.add_item调用既可以将消息类型UI元素添加到Wireshark GUI,也可以返回消息类型,以便可以进行匹配以确定如何继续解析。Fields.message_type是一种特殊的字段类型,它包含解析和显示协议消息类型的大脑。
数据包重组非常容易使用。您调用Parse.reAssemble_Packets_Until来告诉Wireshark您期望在此逻辑消息中剩余多少字节的数据。
Let parse_PRIV_ENCRYPTED_Bigstring~PARSE_LENGTH_HEADER~SESSION_KEY=让我们打开Parse。Let%bind length=parse_length_Header()中的let_语法let%bind()=parse。让%BIND DATA=PARSE中的REASSEMBLE_PACKETS_Until~Length。Parse_out(字段。读者。OF_LENGTH~LENGTH)在解密中。DECRYPT_KRB_PRIV~SESSION_KEY数据|>;解析。OF_OR_ERROR(错误或错误)
如果数据因为数据包被拆分而被截断,库将处理来自该连接的数据包的重组,直到有那么多数据可供您使用,然后它将回调到您的解析代码中,就好像数据一直都在那里一样。
此代码还支持无缝解密和显示Kerberized RPC数据包转储。该插件将连接到我们的内部授权数据库,并获取解密所需的数据,前提是相关用户拥有正确的权限。
我们对这个项目感到兴奋,这既是因为它为我们提供了一个即时实用的工具--异步RPC对Wireshark的支持,还因为它为我们提供了一个强大的库,使得为新协议构建新解析器变得简单和容易!
我们的许多交易系统都是以非常相似的方式构建的:交易系统的每个实例都负责一定数量的产品,每个产品都暗示着一系列数据,你需要使用这些数据来为产品定价和交易。
ETF就是一个简单易懂的例子。ETF(Short ForeXchange Traded Fund)本质上是一家目的是持有一篮子其他公司股票的公司。因此,如果你购买了间谍公司的股票,你实际上是在购买标准普尔500指数中每一家公司的一小部分。
为了给ETF定价,你需要获得该ETF成分股的市场数据;因此,就SPY而言,你需要获得标准普尔500指数(S&P;500 index)500个成分股的价格。
但是,您需要数据的每个组件都需要从使用它的实例中获得一些资源,这就存在一个优化问题。您如何决定如何将ETF分散到一个实例集合中,以避免对任何单个实例造成过重负担?这并不像看起来那么容易,因为正确的选择不仅取决于你需要的数据总量,还取决于你需要哪些股票的数据,因为将两个共享许多相同成分的ETF放在同一个实例上会更有效率。
我们对此的基线方法是相当原始的。我们使用了少量令人尴尬的人工启发式方法,并有效地手工完成了分割。这很糟糕,原因有几个:它需要一大堆时间,手工共享可能不是最优的,并且手工共享不会随着世界的变化而更新。你应该预期给定的证券会随着时间的推移而变化,ETF的构成也会随着时间的推移而变化。如果你不时不时地更新你的分割,你最终会在地面上留下性能上的胜利。而且手动做整个事情并不会激励你经常做这件事。
尤兰最终既与运行这一过程的交易部门合作,也与研究小组合作,研究小组向她指出了一些需要优化的更简洁的成本函数,并鼓励她在开始时使用的贪婪算法之外,尝试模拟退火。
而且结果看起来真的很有希望!我们现在有了一个解算器,您可以告诉您要分片哪些ETF和一些相关的元数据,几分钟后它就会显示出一个分片,可以用来驱动交易系统的配置。结果看起来可能比以前的手工分片效率提高了10%-20%,更好的是,这为办公桌省去了一大堆令人沮丧的手工工作。
管理技术债务的一个重要部分是迁移,即组织项目以删除过时的代码和模式。Eric Martin的项目就是这种迁移的一部分,特别是从一个正则表达式库Google的Re2库迁移到另一个称为Re的纯OCaml库。(有趣的是,很多年前,我们的Re2包装器也是一个实习生项目!)。
我们想要去掉re2已经有一段时间了,但这很棘手,替换它很痛苦,部分原因是re2规则表达式的语义与Re中的规则表达式的语义不太一致。Eric的项目是创建一个新的库Re_Replace_Re2,这意味着它是我们的Re2包装器的临时替代品,我们可以在树上自动地把它砸到合适的位置。
能有多难呢?答案很难,第一个任务是获得一个解析器,它可以用来生成一个表示规则表达式结构的抽象语法树(AST)。
Eric没有用OCaml编写解析器,而是与现有的Re2解析器挂钩,并使用它来生成表示AST的OCaml数据结构。这有几个优点:
尽管它没有完全降低我们对Re2的依赖,但它确实减少了我们依赖的代码量。
最后,我们希望使用它将Re2样式的模式机械地转换为RE已经知道如何解析的模式,让我们进一步减少对Re2的依赖。
最后,假设我们最终确实需要编写一个纯OCamlparser,那么拥有一个很好的C++解析器的打包版本会让我们更容易进行测试。
但是解析并不是唯一需要完成的工作。一旦您有了表示RE2regexp的AST,您仍然需要一些方法在RE中对其进行编码。这很棘手,因为尽管它们都是“正则表达式”引擎,但它们并不完全实现经典的正则表达式;它们的袖子上总是有几个扩展,通常没有指定得很好,这使得转换有点麻烦。
因此,正确构建这个库的很大一部分内容是测试!Eric部署QuickCheck进行一些双向模拟样式测试,以检查re_replace_re2与Re2的行为方式是否相同。(QuickCheck是一种用于构建概率分布以生成测试示例的巧妙习惯用法,而互模拟是一种技术,在这种技术中,您实际上可以一起运行同一程序的两个实现,并相互检查结果。)。
Eric还使用了一种名为AFL的看似神奇的工具,这是一种非常擅长生成测试用例来执行特殊仪器程序的模糊工具。他专门用它来查找他的C++解析代码中的错误。
无论如何,所有这些出色工作的最终结果是,我们有了一个几乎可以使用的Re_Replace_Re2版本,至少可以删除很大一部分Re2的使用。仍然存在一些语义鸿沟(其中一些依赖于Eric上游提交的修复来修复自己!),这意味着它还没有完全准备好在任何地方取代RE2。所有这些都表明,移民是一项艰苦的工作。
我希望这能让你感受到实习生在简街做的那种工作。我们的目标是给实习生提供既能教给他们有趣的东西,又能对组织产生实际影响的项目。我认为我们今年夏天在这方面做得相当不错。
如果你觉得这很有趣,你应该申请。如果你想更多地了解面试过程,这是一个很好的起点。