置顶通知
由于评论从畅言云评迁移到waline,导致评论数据丢失。非本人删除,各位大佬见谅!!!
由于评论从畅言云评迁移到waline,导致评论数据丢失。非本人删除,各位大佬见谅!!!
先来看一段 Java 代码,Application中有version和 logger。logger 依赖了 Version。
1 | public class Application |
那么问题来了,如何在 Rust 中实现相同的代码?
生命周期,简而言之就是引用的有效作用域。在大多数时候,我们无需手动的声明生命周期,因为编译器可以自动进行推导。当多个生命周期存在,且编译器无法推导出某个引用的生命周期时,就需要我们手动标明生命周期。
生命周期的主要作用是避免悬垂引用,它会导致程序引用了本不该引用的数据:
1 | { |
此处 r 就是一个悬垂指针,它引用了提前被释放的变量 x。
为了保证 Rust 的所有权和借用的正确性,Rust 使用了一个借用检查器(Borrow checker),来检查我们程序的借用正确性:
1 | { |
r 变量被赋予了生命周期 'a,x 被赋予了生命周期 'b,从图示上可以明显看出生命周期 'b 比 'a 小很多。在编译期,Rust 会比较两个变量的生命周期,结果发现 r 明明拥有生命周期 'a,但是却引用了一个小得多的生命周期 'b,在这种情况下,编译器会认为我们的程序存在风险,因此拒绝运行。如果想要编译通过,也很简单,只要 'b 比 'a 大就好。总之,x 变量只要比 r 活得久,那么 r 就能随意引用 x 且不会存在危险:
1 | { |
TCP协议是一种面向连接的有状态网络协议。对于发送的每个数据包,一旦TCP堆栈收到特定数据包的ACK,它就认为它已成功传递。
TCP使用指数退避超时重传一个未确认的数据包,最多tcp_retries2时间(默认为15),每次重传超时在TCP_RTO_MIN(200毫秒)和TCP_RTO_MAX(120秒)之间。一旦第15次重试到期(默认情况下),TCP堆栈将通知上面的层(即应用程序)断开连接。
tcp_retries2可以通过修改文件
/proc/sys/net/ipv4/tcp_retries2
或sysctl net.ipv4.tcp_retries2
进行调优。
TCP_RTO_MIN和TCP_RTO_MAX的值在Linux内核中硬编码,并由以下常量定义:
1 | #define TCP_RTO_MAX ((unsigned)(120*HZ)) |
Linux2.6+使用1000毫秒的HZ,所以TCP_RTO_MIN是200毫秒,TCP_RTO_MAX是120秒。给定tcp_retries设置为15的默认值,这意味着在将断开的网络链路通知给上层(即应用程序)之前需要924.6秒,因为在最后一次(第15次)重试到期时检测到连接断开。
Retransmission | RTO(ms) | Time before a timeout(sec) | Time before a timeout(min) |
---|---|---|---|
1 | 200 | 0.2 secs | 0.0 mins |
2 | 400 | 0.6 secs | 0.0 mins |
3 | 800 | 1.4 secs | 0.0 mins |
4 | 1600 | 3.0secs | 0.1 mins |
5 | 3200 | 6.2 secs | 0.1 mins |
6 | 6400 | 12.6 secs | 0.2 mins |
7 | 12800 | 25.4secs | 0.4 mins |
8 | 25600 | 51.0 secs | 0.9 mins |
9 | 51200 | 102.2 secs | 1.7 mins |
10 | 102400 | 204.6 secs | 3.4 mins |
11 | 120000 | 324.6 secs | 5.4 mins |
12 | 120000 | 444.6 secs | 7.4 mins |
13 | 120000 | 564.6 secs | 9.4mins |
14 | 120000 | 684.6 secs | 11.4 mins |
15 | 120000 | 804.6 secs | 13.4 mins |
16 | 120000 | 924.6 secs | 15.4 mins |
真正起到限制重传次数的并不是真正的重传次数。而是以tcp_retries2为boundary,以rto_base(如TCP_RTO_MIN 200ms)为初始RTO,计算得到一个timeout值出来。如果重传间隔超过这个timeout,则认为超过了阈值。实际TCP 的 RTO 是动态计算[1]的,也就是说:
由于tcp_retries2是个系统级参数,在实际使用中,可以针对应用修改TCP_USER_TIMEOUT
[2]。
建议公式为(开启了 KeepAlive 的情况):
1 | TCP_USER_TIMEOUT >= TCP_KEEPIDLE + TCP_KEEPINTVL * TCP_KEEPCNT |
TCP_USER_TIMEOUT 是RFC 54288 规定的 TCP option,用来扩展 TCP RFC 7939 协议中本身的 “User Timeout” 参数(原协议不允许配置参数大小)。其用来控制已经发送,但是尚未被 ACK的数据包的存活时间,超过这个时间则会强制关闭连接。
上篇博客介绍了 CPU异常分析的工具和方法。本文将介绍如何定位 CPU 耗时。
如果不同的类型具有相同的行为,那么我们就可以定义一个特征,然后为这些类型实现该特征。定义特征是把一些方法组合在一起,目的是定义一个实现某些目标所必需的行为的集合。
例如,我们现在有文章 Post 和微博 Weibo 两种内容载体,而我们想对相应的内容进行总结,也就是无论是文章内容,还是微博内容,都可以在某个时间点进行总结,那么总结这个行为就是共享的,因此可以用特征来定义:
1 | pub trait Summary { |
特征只定义行为看起来是什么样的,而不定义行为具体是怎么样的。因此我们需要为实现特征的类型,定义行为具体是怎么样的。
1 | pub struct Post { |
指针是一个包含了内存地址的变量,该内存地址引用或者指向了另外的数据。
在 Rust 中,最常见的指针类型是引用,引用通过 & 符号表示。不同于其它语言,引用在 Rust 中被赋予了更深层次的含义,那就是:借用其它变量的值。引用本身很简单,除了指向某个值外并没有其它的功能,也不会造成性能上的额外损耗,因此是 Rust 中使用最多的指针类型。
而智能指针则不然,它虽然也号称指针,但是它是一个复杂的家伙:通过比引用更复杂的数据结构,包含比引用更多的信息,例如元数据,当前长度,最大可用长度等。智能指针往往是基于结构体实现,它与我们自定义的结构体最大的区别在于它实现了 Deref 和 Drop 特征:
而 Box 指针是最简单的智能指针。本文将介绍 Box 指针以及 Deref 和 Drop 特征。
本文总结了如何使用 Java 客户端操作 HDFS,以及一些注意点。
Rust 为了解决内存安全问题,引入了所有权系统。
所有的程序都必须和计算机内存打交道,如何从内存中申请空间来存放程序的运行内容,如何在不需要的时候释放这些空间,成了重中之重,也是所有编程语言设计的难点之一。在计算机语言不断演变过程中,出现了三种流派:
Rust 选择了第三种,最妙的是,这种检查只发生在编译期,因此对于程序运行期,不会有任何性能上的损失。
本文记录一些分析 CPU 性能问题的工具&方法。