关于rust:Rust通过FFI调用C

<article class=“article fmt article-content”><h2><code>FFI</code>存在背景</h2><p><code>FFI(Foreign Function Interface)</code>能够用来与其它语言进行交互,然而并不是所有语言都这么称说,例如 <code>Java</code> 称之为 <code>JNI(Java Native Interface)</code></p><p><code>FFI</code> 之所以存在是因为事实中很多代码库都是由不同语言编写的,如果咱们须要应用某个库,然而它是由其它语言编写的,那么往往只有两个抉择:</p><ul><li>对该库进行重写或者移植</li><li>应用 <code>FFI</code></li></ul><h2><code>FFI</code>实现须要面对的挑战</h2><ul><li>调用方语言是否涵盖了被调用语言的数据类型,<code>rust</code>作为调用方语言,涵盖了所有<code>C</code>语言的数据类型,比方<code>C</code>当中的<code>int,double</code>对应了<code>rust</code>中的<code>i32,f64</code>类型</li><li>是否可能解决 <code>C</code>的裸指针,包含指向被看作是字符串的数组指针,包含构造体指针</li></ul><h2>在 <code>Rust</code> 中调用 <code>C</code> 的办法</h2><ol><li>在 <code>Rust</code> 代码中应用 <code>extern</code> 关键字申明要调用的 <code>C</code> 函数</li><li>应用 <code>unsafe</code> 块调用它</li></ol><p>留神点:须要手动解决参数和返回值的转换,可能产生异样报错</p><h2><code>FFI</code>实现调用简略<code>C</code>函数</h2><p>试验平台<code>Ubuntu22.04 amd64 Desktop</code></p><p>调用了<code>C</code>规范库当中的数学库函数,<code>abs</code>求绝对值,<code>pow</code>求幂,<code>sqrt</code>求平方根</p><pre><code class=“rust”>use std::os::raw::{c_double, c_int};// 从规范库 libc 中引入三个函数。// 此处是 Rust 对三个 C 函数的申明:extern “C” { fn abs(num: c_int) -> c_int; fn sqrt(num: c_double) -> c_double; fn pow(num: c_double, power: c_double) -> c_double;}fn main() { let x: i32 = -123; // 每次调用都必须产生在一个unsafe区域内, 表明Rust对外部调用中可能存在的不平安行为不负责 println!("{x}的绝对值是: {}.", unsafe { abs(x) }); let n: f64 = 9.0; let p: f64 = 3.0; println!("{n}的{p}次方是: {}.", unsafe { pow(n, p) }); let mut y: f64 = 64.0; println!("{y}的平方根是: {}.", unsafe { sqrt(y) }); y = -3.14; println!("{y}的平方根是: {}.", unsafe { sqrt(y) }); //** NaN = NotaNumber(不是数字)}</code></pre><p>上述程序的输入是</p><pre><code>-123的绝对值是: 123.9的3次方是: 729.64的平方根是: 8.-3.14的平方根是: NaN.</code></pre><h2><code>FFI</code>调用自定义地位的<code>C</code>库</h2><p>我的项目构造如下</p><pre><code>.├── build.rs├── Cargo.lock├── Cargo.toml├── hello│ └── hello.c└── src └── main.rs</code></pre><p>编辑<code>hello/hello.c</code>文件</p><pre><code class=“c”>#include <stdio.h>void hello() { printf(“Hello, build script!!!!\n”);}</code></pre><p>在<code>Cargo.toml</code>退出构建时依赖</p><pre><code class=“toml”>[build-dependencies]cc = “1.0”</code></pre><p>批改<code>build.rs</code></p><pre><code class=“rust”>fn main() { // 示意在hello/hello.c文件产生批改的时候须要从新运行build脚本 println!(“cargo:rerun-if-changed=hello/hello.c”); let mut builder: cc::Build = cc::Build::new(); builder .file("./hello/hello.c") .compile(“hello”);}</code></pre><p>批改<code>src/main.rs</code></p><pre><code class=“rust”>// 应用extern申明hello是C外面的函数extern “C” { fn hello();}fn main() { // rust调用的时候须要应用unsafe包裹 unsafe { hello(); } println!(“Hello, world!”);}</code></pre><p>运行</p><pre><code class=“shell”>$ cargo runHello, build script!!!!Hello, world!</code></pre><h2><code>FFI</code>调用简单函数</h2><p>本示例蕴含构造体指针的传递</p><p>当初应用<code>C</code>库中的函数<code>asctime</code></p><p><code>header</code>文件地位是<code>/usr/include/time.h</code>,函数定义如下,通过传入一个<code>tm</code>类型的构造体指针,返回一个日期格局为<code>Day Mon dd hh:mm:ss yyyy\n</code>的字符串</p><pre><code class=“c”>/* Return a string of the form “Day Mon dd hh:mm:ss yyyy\n” that is the representation of TP in this format. /extern char asctime (const struct tm __tp) __THROW;</code></pre><p>因为波及到大量的模板代码和类型转换,须要应用<code>bindgen</code>工具从C语言的头文件生成<code>rust</code>代码放慢开发速度,缩小低级谬误,提高效率</p><p>工具由<code>rust</code>语言官网保护,地址</p><pre><code>https://github.com/rust-lang/rust-bindgen</code></pre><p><code>Debian/Ubuntu</code>系列的装置依赖</p><pre><code class=“shell”>$ sudo apt install llvm-dev libclang-dev clang</code></pre><p>其余零碎的装置依赖参考</p><pre><code>https://rust-lang.github.io/rust-bindgen/requirements.html</code></pre><p>装置命令行工具</p><pre><code class=“shell”>$ cargo install bindgen-cli</code></pre><p>比方当初转换<code>/usr/include/time.h</code>文件</p><p>在<code>rust</code>的我的项目根门路下执行命令</p><pre><code class=“shell”>$ bindgen /usr/include/time.h > src/mytime.rs</code></pre><p>之后比照<code>/usr/include/time.h</code>和<code>src/mytime.rs</code></p><p>查看<code>C</code>语言的原始代码,找到函数<code>asctime</code>和构造体<code>tm</code>的定义</p><pre><code class=“c”>/ 源码地位 /usr/include/time.h // Return a string of the form “Day Mon dd hh:mm:ss yyyy\n” that is the representation of TP in this format. /extern char asctime (const struct tm __tp) __THROW;/ 源码地位 /usr/include/x86_64-linux-gnu/bits/types/struct_tm.h尽管执行的命令是bindgen /usr/include/time.h > src/mytime.rs然而工具依然会主动扫描转换相干头文件定义的构造体类型// ISO C `broken-down time’ structure. /struct tm{ int tm_sec; / Seconds. [0-60] (1 leap second) / int tm_min; / Minutes. [0-59] / int tm_hour; / Hours. [0-23] / int tm_mday; / Day. [1-31] / int tm_mon; / Month. [0-11] / int tm_year; / Year - 1900. / int tm_wday; / Day of week. [0-6] / int tm_yday; / Days in year.[0-365] / int tm_isdst; / DST. [-1/0/1]/# ifdef __USE_MISC long int tm_gmtoff; / Seconds east of UTC. */ const char tm_zone; / Timezone abbreviation. /# else long int __tm_gmtoff; / Seconds east of UTC. */ const char __tm_zone; / Timezone abbreviation. */# endif};#endif</code></pre><p>查看<code>src/mytime.rs</code>文件外面的代码,找到<code>asctime</code>函数以及<code>tm</code>构造体的定义</p><pre><code class=“rust”>extern “C” { pub fn asctime(__tp: *const tm) -> *mut ::std::os::raw::c_char;}#[repr(C)]#[derive(Debug, Copy, Clone)]pub struct tm { pub tm_sec: ::std::os::raw::c_int, pub tm_min: ::std::os::raw::c_int, pub tm_hour: ::std::os::raw::c_int, pub tm_mday: ::std::os::raw::c_int, pub tm_mon: ::std::os::raw::c_int, pub tm_year: ::std::os::raw::c_int, pub tm_wday: ::std::os::raw::c_int, pub tm_yday: ::std::os::raw::c_int, pub tm_isdst: ::std::os::raw::c_int, pub tm_gmtoff: ::std::os::raw::c_long, pub tm_zone: *const ::std::os::raw::c_char,}</code></pre><p>批改<code>src/main.rs</code>文件内容</p><pre><code class=“rust”>use std::ffi::{c_char, CStr, CString};// mytime.rs作为main.rs的一个modmod mytime;fn main() { // 因为mytime::mm构造体外面的tm_zone字段是一个字符串指针 // 先创立一个字符串 let timezone = CString::new(“UTC”).unwrap(); // 从mytime中导入一个tm构造体,填写参数如下 let mut time_value = mytime::tm { tm_sec: 1, tm_min: 1, tm_hour: 1, tm_mday: 1, tm_mon: 1, tm_year: 1, tm_wday: 1, tm_yday: 1, tm_isdst: 1, tm_gmtoff: 1, // 此处转换为指针类型 tm_zone: timezone.as_ptr() }; unsafe { // 裸指针 let c_time_value_ptr = &mut time_value; // 获取一个c字符串指针 let asctime_result_ptr = mytime::asctime(c_time_value_ptr); // 从指针再转变为CStr类型 let c_str = CStr::from_ptr(asctime_result_ptr); // 最初再转变为rust的&str类型,返回的是一个Result类型,可能会产生utf-8编码谬误 println!("{:?}", c_str.to_str()); }}</code></pre><p>运行</p><pre><code class=“shell”>$ cargo runOk(“Mon Feb 1 01:01:01 1901\n”)</code></pre><p>因为<code>bindgen</code>是把整个<code>/usr/include/time.h</code>文件外面的所有函数和构造体都转换到<code>rust</code>中,所以编译<code>rust</code>的时候会产生很多的<code>function *** is never used, constant **** should have an upper case name</code>这种告警,这个是失常的</p><h2>参考浏览</h2><p>从 <code>Rust</code> 调用 <code>C</code> 库函数 - <code>linux cn</code></p><p><code>Rust</code>调用<code>C</code>程序的实现步骤</p><p><code>C</code> 规范库</p><p><code>rust</code>语言圣经 - <code>FFI</code></p></article> ...

March 4, 2024 · 3 min · jiezi

关于rust:Cargo的自定义命令扩展功能

对于Cargo的自定义命令扩大性能 Cargo的子命令扩大性能反对通过增加新的可执行文件来扩大Cargo的命令集Cargo的自定义命令扩大性能容许开发者通过创立特定命名的可执行文件来扩大Cargo的内置命令集。这些自定义命令能够执行任何工作,如构建工具、辅助脚本、或是与我的项目相干的任何操作,为Rust我的项目提供了极大的灵活性和扩展性。 作用和益处 自动化和简化工作:开发者能够创立自定义命令来自动化重复性的工作,如代码格式化、动态剖析、或主动部署,从而简化开发流程。集成第三方工具:通过自定义命令,能够轻松地将第三方工具和服务集成到Cargo的工作流中,进步开发效率,比方集成代码覆盖率工具、性能剖析工具等。加强我的项目的构建流程:自定义命令能够用来加强规范的Cargo构建流程,比方增加预构建或后构建步骤,执行特定的测试或验证等。我的项目特定的工作流:对于简单的我的项目,能够创立特定的自定义命令来解决我的项目特有的构建步骤或工作,使得项目管理更加灵便。 工作原理 Cargo自定义命令扩大性能的工作原理 基于命名约定:当使用者执行cargo something时,Cargo会在PATH环境变量指定的目录中查找名为cargo-something的可执行文件。如果找到,Cargo则会执行这个可执行文件,并将后续的命令行参数传递给它。 亲测体验 比方我想给cargo减少一个hello的扩大命令, 当执行cargo hello xxx时, 输入你报 xxx,以后工夫为 2024-03-01 20:16:18 创立一个可执行文件(不肯定非要Rust开发,用其余语言如Go也也能够~),将其命名为cargo-hello,并确保这个文件在零碎PATH中。 package mainimport ( "fmt" "os" "time")func main() { if len(os.Args) < 2 { fmt.Println("请提供一个参数,例如:hello xxx") return } name := os.Args[1] currentTime := time.Now().Format(time.DateTime) message := fmt.Sprintf("你好 %s,以后工夫为 %s", name, currentTime) fmt.Println(message)} 通过 echo $PATH,从输入的全副path门路中找一个目录cp进去即可 而后须要改名为cargo-hello 这样在运行cargo hello xxx时,Cargo会从PATH门路来寻找一个名为cargo-hello的可执行文件来执行。 需注意,为了让Cargo辨认和执行自定义命令,可执行文件必须以cargo-为前缀,并且位于零碎的PATH门路中

March 1, 2024 · 1 min · jiezi

关于rust:一封来自-DatenLord-关于GSoC-2024的挑战书

Google Summer of Code是一项全球性的在线打算,致力于将新的contributor引入开源软件开发畛域。GSoC 参与者在导师的领导下,与开源组织单干发展为期 12 周以上的编程我的项目。往年,达坦科技入选作为开源社区组织,携CNCF Sandbox我的项目Xline下泛滥乏味、翻新且有挑战性的题目参加本次流动。 https://summerofcode.withgoogle.com/programs/2024/organizations/datenlord-6z 期待气味相投的,敢于挑战自我的小伙伴踊跃退出咱们~ 为什么要加入GSoC?参加GSoC,短时间晋升编程硬实力近距离接触资深导师,定制适合的我的项目实现路线结识气味相投的小伙伴,编程路上不再孤独依据我的项目开发成绩取得GSoC官网提供我的项目补贴等GSoC提供我的项目补贴将依据两次评估后果进行领取,且具体金额依据地理位置进行计算(中国大陆地区 900~3600美元)。您能够参考 https://developers.google.com/open-source/gsoc/help/student-stipends?hl=zh-cn来获取更多信息。期待开源爱好者参加的我的项目您能够在DatenLord GSoC Ideas Page:https://datenlord.github.io/xline-home/#/GSoC中看到达坦科技为本届GSoC筹备的5个我的项目,包含: Integrating Xline to DatenLordImprove Transaction ValidationXline C ClientJoint Consensus Correctness TestingImplementing Chaos Testing in Madsim 对于我的项目更多详细信息,如我的项目简介、难易水平、须要技能、mentor等请参考Ideas Page。参加指南正式报名链接将于3月18日 18:00UTC(即北京工夫3月19日2:00)开启,截止至4月2日 18:00 UTC(北京工夫4月3日2:00)届时您将须要登陆GSoC官网:https://summerofcode.withgoogle.com/进行报名。 请在您的申请表中提供以下信息: 1. 您的简历,包含您的过往经验、联系方式等。 2. 对以下问题的答复: 您认为咱们的我的项目最吸引您的中央以及您抉择咱们的起因是什么?您目前的技能如何与咱们我的项目的要求相匹配?您冀望从该我的项目中取得什么,咱们如何能力让您施展最大的作用?您以前是否加入过 GSoC(或相似我的项目)?您对于该我的项目具体的proposal (施行打算),包含每周的日程表、指标的细分等流动重要工夫点3/18-4/2 UTC 参与者筛选我的项目、mentor沟通并填写报名表在官网报名 5/1 18:00 UTC 申请者报名表审核后果公示 5/1-5/26 UTC 社区分割期 | GSoC 参与者意识导师,浏览文档,尽快开始我的项目工作 5/27 UTC 我的项目正式开始 5/28-8/26 UTC 我的项目开发 9/3UTC GSoC初步后果公示 (若有参与者非凡延期,则缩短两个月我的项目开发工夫) 如果您还有更多对于流动工夫节点相干疑难,请参考GSoC官网: https://developers.google.com/open-source/gsoc/timeline 联系方式对于报名形式有任何疑难,或者对某一个我的项目十分感兴趣,并且想要深刻理解的同学,欢送退出Xline Discord进行发问或与我的项目导师进行进一步沟通:https://discord.com/invite/hqDRtYkWzm 您也能够增加小助手微信 DatenLord_Tech,或发邮件至info@datenlord.com 进行征询。 ...

March 1, 2024 · 1 min · jiezi

关于rust:Rust-交叉编译-macOS-为-Linux-和-Windows

前言 鉴于 rust 中文材料较少,遇到问题的解决方案更少。这里记录遇到的一些问题。Rust 反对穿插编译,能够在 macOS 平台编译出 Linux 或者 Windows 可运行的程序,或者在 Linux 平台编译 macOS 或者 Windows 可运行的程序。 > > 本文次要文章解说 Mac 平台编译为其余平台的二进制程序。想要实现跨平台编译且可运行的程序,那么咱们就须要动态链接,这样生成程序才不会因为动态链接库的起因运行失败。默认状况下,Rust 动态连贯所有 Rust 代码。如果程序中应用了规范库,Rust 会连贯到零碎的 libc 实现。 环境 苹果零碎: 操作系统:macOS 12.3.1 21E258 x86_64 生锈:rustc 1.60.0 (7737e0b5c 2022-04-04) 生锈:rustup 1.24.3 (ce5817a94 2021-05-31)Linux: 操作系统:EndeavourOS Linux x86_64 外围:5.17.1-arch1-1 生锈:rustc 1.60.0 (7737e0b5c 2022-04-04) 生锈:rustup 1.24.3 (ce5817a94 2021-05-31)首先须要装置 Rust,应用命令 。 案例 应用 Cargo 新建二进制我的项目:cargo new --bin hello文件 main.rs:fn main() {println!("Hello World!\n");}macOS 编译为 Linux 和 Windows 可用二进制程序编译为 Linux 平台想要实现 Linux 平台能够运行的程序,那么就须要应用 musl 来代替 glibc,musl 实现了 Linux libc。musl 在 macOS 上应用 musl-cross,musl-cross 是专门编译到 Linux 的工具链,上面进行装置:musl https://musl.libc.org/$ brew install FiloSottile/musl-cross/musl-cross还须要创立 musl-gcc:$ ln -s /usr/local/bin/x86_64-linux-musl-gcc /usr/local/bin/musl-gcc增加对应的 Target,只须要执行一次就能够了:rustup target add x86_64-unknown-linux-musl批改配置文件~/.cargo/config(如果没有能够新建),增加以下内容:[target.x86_64-unknown-linux-musl]linker = "x86_64-linux-musl-gcc"也能够在我的项目根目录下创立 .cargo/config 文件,只对以后我的项目失效:应用cargo build --release --target x86_64-unknown-linux-musl后果:$ tree -L 2 target/x86_64-unknown-linux-musltarget/x86_64-unknown-linux-musl├── CACHEDIR.TAG└── debug├── build├── deps├── examples├── hello├── hello.d└── incremental5 directories, 3 files$ file target/x86_64-unknown-linux-musl/debug/hellotarget/x86_64-unknown-linux-musl/debug/hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, with debug_info, not stripped ...

March 1, 2024 · 1 min · jiezi

关于rust:Actor并发系统说明与使用

简介Actor模型是一种并行计算模型,提供了一种用于构建并发、分布式系统的形象办法 在Actor模型中,计算被示意为独立的、轻量级的计算单元,称为Actor,能够发送和接管音讯并进行本地计算 作为一种通用的消息传递编程模型,被宽泛用于构建大规模可伸缩分布式系统 核心思想是独立保护隔离状态,并基于消息传递实现异步通信 Actor模型组成存储:每个 Actor 持有一个邮箱(mailbox),实质上是一个队列,用于存储音讯通信:每个 Actor 能够发送音讯至任何 Actor,应用异步消息传递,不保障音讯达到指标 Actor 时的程序计算: Actor 能够通过解决音讯来更新外部状态,对于内部而言,Actor 的状态是隔离的isolated state劣势每个 Actor 独立运行,因而程序天然是并行的每个Actor都齐全独立于其余实例,不存在共享内存和竞争条件的问题,能够防止并发编程中的一些难点通过消息传递进行通信,每个Actor都有一个邮箱来接管音讯,每次只解决一个音讯,以确保状态的一致性和线程平安消息传递是异步的,发送方不须要期待接管方的响应,从而防止了锁和同步的开销提供高度的并发性和可扩展性,可能无效地解决多核CPU和分布式系统中的并发编程问题提供良好的容错性和可恢复性,因为每个Actor都有本人的状态和行为,能够更容易地实现零碎的容错和复原Actor 基于线程的任务调度为每一个 Actor 调配一个独立的执行过程(线程),独占该线程,能够是操作系统线程,协程或者虚拟机线程 如果以后 Actor 的邮箱为空,Actor 会阻塞以后线程,期待接管新的音讯 因为线程数量受到零碎的限度,因而 Actor 的数量也会受到限制 Actor基于事件驱动的任务调度只有在事件触发(即接管音讯)时,才为 Actor 的任务分配线程并执行,当事件处理完毕,即退出线程 该形式能够应用很少的线程来执行大量 Actor 产生的工作,也是当初大部分Actor模型所采纳的调度形式 这种实现与 run loop、event loop 机制十分类似 rust中的Actor模型实现-actix Actix 建设在 Actor 模型的根底上,容许将应用程序编写为一组独立执行但合作的Actor,这些Actor通过音讯进行通信 Actor 是封装状态和行为的对象,并在actix 库提供的Actor零碎中运行 Actor 在特定的执行上下文 Context<A> 中运行, 上下文对象仅在执行期间可用, 每个 Actor 都有一个独自的执行上下文,执行上下文还管制 Actor 的生命周期。 Actor 仅通过替换音讯进行通信 任何 Rust 类型都能够是 Actor,只须要实现 Actor Trait 即可 为了可能解决特定音讯,参与者必须为此音讯提供 Handler<M> 实现 ...

February 28, 2024 · 1 min · jiezi

关于rust:Rust-workspace的使用

Rust中Workspace的应用 对于较大型我的项目,随着性能的一直减少,规模的不断扩大,将面临如何组织我的项目的问题。在这种状况下,能够应用 Cargo workspace来组织和治理我的项目。 workspace能够用于治理多个依赖包,它容许在一个独自的我的项目中构建、测试和共享多个包。这一机制特地实用于大型项目,或者当想将一个我的项目拆分成多个较小的、可重用的组件时。 引入的背景 workspace能够帮忙治理多个相干的包,通过共享同一个Cargo.lock文件和同一个输入目录(target),以及其余配置(比方公布配置)在Rust呈现workspace之前,独立治理多个相干的包可能十分艰难。每个包都须要独自配置、编译和测试,这使得跨包的依赖治理和版本控制变得复杂。随着我的项目规模的增长,这种办法变得越来越不可继续。 为了解决这些问题,Rust引入了workspace概念,目标是简化这些工作,特地是在波及多个包的场景中。workspace容许开发者在一个共享的环境中工作,其中所有包都能够被对立构建和测试,依赖关系也被智能地治理。 如何应用 要在Rust中应用workspace,须要创立一个顶层的Cargo.toml文件来定义workspace及其成员。 上面是一个简略的例子: 假如想创立一个名为my_workspace的workspace,其中蕴含两个包:library(一个库包)和app(一个二进制包,依赖于library)。 创立workspace目录: mkdir my_workspacecd my_workspace配置workspace的Cargo.toml: 在my_workspace目录中,创立Cargo.toml: [workspace]members = [ "library", "app",]创立包: 对于library包:mkdir librarycd librarycargo init --lib默认生成的lib.rs中会有如下内容: pub fn add(left: usize, right: usize) -> usize { left + right}#[cfg(test)]mod tests { use super::*; #[test] fn it_works() { let result = add(2, 2); assert_eq!(result, 4); }} 对于app包: cd ../ # 回到workspace根目录mkdir appcd appcargo init 增加依赖:在app的Cargo.toml中增加对library的依赖: [dependencies] library = { path = "../library" }并且在app/main.rs中,调用一下library中的add函数: ...

February 27, 2024 · 1 min · jiezi

关于rust:Rust-开发命令行工具上

你必须按所想去生存,否则只能按生存去想。 --王小波大家好,我是柒八九。 作为一个前端/Rust/AI常识博主,之前的文章中,大部分篇幅都是对于前端的常识分享,而对Rust和AI的内容只是做了几篇内容梳理和介绍。 而,咱们今后的重心也会逐步偏移,势必能达到前端/Rust/AI三足鼎立的场面。 这里也和很多精力股东做一次简短的汇报,之前许可大家多出一些Rust相干的文章,因为工作和集体事务强占大部分学习和总结的工夫,所以迟迟没有兑现承诺。也很感激大部分老粉能不离不弃,在这里先叩谢大家了。 你们的反对也是我输出内容的精神支柱,同时也很感激有些远在天南地北的敌人,不停的给出倡议和改良意见,Last but not least,因为有些技术能力的无限,在一些表达方式和技术深度方向上,有很多瑕疵。也心愿当前大家,互相学习,共同进步。 好了,预计大家不想听我在这里一个人聒噪了,那么就进入咱们明天的主题。 前言在上一篇致所有渴望学习Rust的人的信中咱们介绍了Rust能够在命令行工具上也大有建树。 当初就是咱们兑现承诺的时候了。 Rust是一种动态编译的、疾速的语言,具备杰出的工具反对和迅速增长的生态系统。这使它非常适合编写命令行应用程序。 通过编写具备简略CLI的程序,对于那些初学者来说是一个很好的练习,也是咱们须要循序渐进的一个过程。毕竟,大家刚开始接触一个新的语言都是从Hello World的动手的,然而这种Demo级别的程序,能够说是闭门造车,没有任何的理论价值。并且这种程序是难登大雅之堂的。 所以,咱们明天来通过一个简略的CLI来坚固之前的内容,并且写出的货色也能够在公司利用场景中有用武之地。 所以说抉择很重要,咱们不要成为他人口中说的你之所以穷,是因为你不够致力的人。 咱们在解说代码中,有一些根底语法会一带而过,也就是说,曾经默认大家曾经有Rust根底了。如果,你是一个Rust初学者,咱们也提供了Rust学习笔记系列,能够疾速把握根底语法。当然,外面的有一些内容也会做一些简略的梳理和解说。这个就因人而异了,看大家理论状况吧。 因为篇幅的起因,咱们打算写三篇文章(上/中/下),来介绍如何用Rust来编写属于本人的命令行工具。 明天是第一篇文章,咱们次要的目标是用Rust写出一个可用的命令行工具。属于本地利用级别,当初先不要不屑一顾,咱们前面的2篇文章,会逐渐优化这个我的项目,而后达到最初发版供他人应用的级别。你能所学到的知识点前置知识点我的项目设置解析命令行参数解析文件内容更人性化的错误报告信息输入解决代码展现 (这个狠重要) 徐志胜语音包好了,天不早了,干点闲事哇。 1. 前置知识点前置知识点,只是做一个概念的介绍,不会做深度解释。因为,这些概念在上面文章中会有呈现,为了让行文更加的顺畅,所以将本该在文内的概念解释放到后面来。如果大家对这些概念相熟,能够间接疏忽同时,因为浏览我文章的群体有很多,所以有些知识点可能我视之若瑰宝,尔视只如草芥,弃之如敝履。以下知识点,请酌情应用。grep 简介grep 是一个罕用的命令行工具,用于在文本文件中搜寻指定的文本模式并返回匹配的行。其名称来源于 global regular expression print(全局正则表达式打印),它最后是在UNIX操作系统中开发的,当初曾经成为大多数Unix-like零碎(包含Linux)的规范工具之一。grep 的次要性能是查找文件中蕴含特定文本的行,并将这些行打印到规范输入(通常是终端)上。 以下是 grep 命令的根本语法: grep [选项] 模式 [文件...]选项:能够是一些管制搜寻行为的可选标记,例如 -i(疏忽大小写)、-r(递归搜寻目录)、-l(仅显示蕴含匹配项的文件名)等。模式:要搜寻的文本模式,通常应用正则表达式来指定。文件:要搜寻的文件列表。如果不指定文件,则 grep 将从规范输出中读取数据。一些常见的 grep 用法示例: 在文件中搜寻特定字符串(不辨别大小写): grep -i "search_text" file.txt在多个文件中递归搜寻特定字符串并显示蕴含匹配项的文件名: grep -r -l "search_text" directory/应用正则表达式搜寻匹配模式: grep "pattern.*text" file.txt统计匹配的行数: grep -c "pattern" file.txtgrep 是一个弱小的文本搜寻工具,能够在各种状况下用于过滤、查找和解决文本数据。它的灵活性和正则表达式反对使得它在命令行中十分有用。 让咱们编写一个小型的相似grep的工具。给它起一个霸气侧漏的名称,那就叫它 - f789吧。 ...

September 21, 2023 · 6 min · jiezi

关于rust:文盘Rust-给程序加个日志-京东云技术团队

日志是应用程序的重要组成部分。无论是服务端程序还是客户端程序都须要日志做为谬误输入或者业务记录。在这篇文章中,咱们联合log4rs聊聊rust 程序中如何应用日志。 log4rs相似java生态中的log4j,应用形式也很类似 log4rs中的基本概念log4rs 的性能组件也由 appender 和 logger形成。 appender 负责向指定文件或控制台追加日志logger 蕴含多个 appender ,比方一条日志既要输入到控制台也要长久化到日志文件中,就能够在logger中同时绑定 ConsoleAppender 和 FileAppenderlog4rs 应用示例示例形容 咱们须要在工程中记录系统日志和业务日志,别离记录在logs/sys.log 和 logs/business.log定义 appender 和 logger 并初始化 代码地位 src/logger/logger.rs let sys_file = FileAppender::builder() .encoder(Box::new(PatternEncoder::new("{d} - {m}{n}"))) .build("logs/sys.log") .unwrap(); let business_file = FileAppender::builder() .encoder(Box::new(PatternEncoder::new("{d} - {m}{n}"))) .build("logs/business.log") .unwrap(); let stdout = ConsoleAppender::builder().build(); let config = Config::builder() .appender(Appender::builder().build("stdout", Box::new(stdout))) .appender(Appender::builder().build("sys", Box::new(sys_file))) .appender(Appender::builder().build("business", Box::new(business_file))) .logger( Logger::builder() .appender("sys") .build("syslog", LevelFilter::Info), ) .logger( Logger::builder() .appender("business") .build("businesslog", LevelFilter::Info), ) .build( Root::builder() .appender("stdout") .appender("file_out") .build(LevelFilter::Info), ) .unwrap(); let _ = log4rs::init_config(config).unwrap();代码中定义了 sys\_file 和 business\_file 两个FileAppender 别离用于像sys.log 和 business.log中追加日志。 ...

September 11, 2023 · 1 min · jiezi

关于rust:Rust相关

材料: 官网官网learnthe book (书:Rust权威指南) 透过 Rust 摸索零碎的本原:编程语言

September 7, 2023 · 1 min · jiezi

关于rust:文盘Rust-生命周期问题引发的-static-hashmap-锁-京东云技术团队

2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提醒这些cli该有的罕用性能做进去了。我的项目地址:https://github.com/jiashiwen/interactcli-rs。 春节以前看到axum曾经0.4.x了,于是想看看能不能用rust做个服务端的框架。 春节后开始入手,在做的过程中会碰到各种乏味的问题。于是记下来想和社区的小伙伴一起分享。社区里的小伙伴大部分是DBA和运维同学,如果想进一步理解更底层的货色,代码动手是个好路数。 我集体认为想看懂代码先要写好代码,起码理解开发的根本路数和工程的个别组织模式。但好多同学的次要工作并不是专职开发,所以也就没有机会下探研发技术。代码这个事儿光看书是不论用的。理解一门语言最好的形式是应用它。 那么,问题来了非研发人员如何相熟语言呢?咏春拳里有句拳谚:”无师无对手,桩与镜中求“。解释两句,就是在没有师兄弟练习的状况下,对着镜子和木人桩练习。在这里我感觉所谓桩有两层含意,一个是木人桩,就是练习的工具,一个是”站桩“,传统武术训练基本功的办法。其实在理论的工作中DBA和运维同学会有很多场景须要编程,比方做一些运维方面的统计工作;剖析问题时须要拿到某些数据。如果谋求简略用Python的话可能对于其余语言就没有涉猎了。如果联合你运维数据库的原生开发语言,假以时日缓缓就能看懂相干的底层逻辑了。我集体有个观点,产品研发的原生语言是理解产品底层最好的入口。 前面如果在Rust的开发过程中有其余问题,我自己会把问题结合实际也写到这个系列里,也心愿社区里对Rust感兴趣的小伙伴一起来”盘Rust“。 言归正传,说说这次在玩儿Rust时遇到的问题吧。 在 Rust 开发过程中,咱们常常须要全局变量作为公共数据的寄存地位。通常做法是利用 lazy_static/onecell 和 mux/rwlock 生成一个动态的 collection。 代码长这样 use std::collections::HashMap;use std::sync::RwLock;lazy_static::lazy_static! { static ref GLOBAL_MAP: RwLock<HashMap<String,String>> = RwLock::new({ let map = HashMap::new(); map });}根本的数据存取这样实现 use std::collections::HashMap;use std::sync::RwLock;lazy_static::lazy_static! { static ref GLOBAL_MAP: RwLock<HashMap<String,String>> = RwLock::new({ let map = HashMap::new(); map });}fn main() { for i in 0..3 { insert_global_map(i.to_string(), i.to_string()) } print_global_map(); println!("finished!");}fn insert_global_map(k: String, v: String) { let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.insert(k, v);}fn print_global_map() { let gpr = GLOBAL_MAP.read().unwrap(); for pair in gpr.iter() { println!("{:?}", pair); }}insert\_global\_map函数用来向GLOBAL\_MAP插入数据,print\_global_map()用来读取数据,下面程序的运行后果如下 ...

September 5, 2023 · 2 min · jiezi

关于rust:DatenLord前沿技术分享No34

达坦科技专一于打造新一代开源跨云存储平台DatenLord,通过软硬件深度交融的形式买通云云壁垒,致力于解决多云架构、多数据中心场景下异构存储、数据对立治理需要等问题,以满足不同行业客户对海量数据跨云、跨数据中心高性能拜访的需要。在本周的前沿技术分享中,咱们邀请到了王俊吉,来为大家分享RustBelt与Rust形式化办法。 01、演讲题目RustBelt与Rust形式化办法 02、演讲工夫2023年9月3日上午10:30 03、演讲人王俊吉 Rust编译器/形式化办法爱好者。 04、引言RustBelt是Rust语言内存平安的形式化语义模型,将比照与其余Rust形式化验证工具的差别,并选取RustBelt中所有权的局部作简要介绍。 05、内容简介Rust是一门内存平安的零碎编程语言,通过所有权、生命周期标注等伎俩在编译期实现内存平安。同时,Rust也提供了隔离的unsafe机制,容许绕过局部安全检查以实现更精密的内存拜访等需要。在Rust规范库中,存在大量的unsafe代码,其内存安全性存疑。基于此背景下,RustBelt我的项目提出了可用于证实Rust代码内存安全性的语义模型,将Rust MIR代码经简化后手工转写为-Rust的形式化语言后,RustBelt语义模型保障只有能通过-Rust的类型查看,则该段代码是内存平安的。 06、直播预约欢迎您预约直播,或者登陆腾讯会议观看直播: 会议号:474-6575-9473 达坦科技(DatenLord)专一下一代云计算——“天空计算”的基础设施技术,致力于拓宽云计算的边界。达坦科技打造的新一代开源跨云存储平台DatenLord,通过软硬件深度交融的形式买通云间壁垒,实现数据高效跨云拜访,建设海量异地、异构数据的对立存储拜访机制,为云上利用提供高性能平安存储反对。以满足不同行业客户对海量数据跨云、跨数据中心高性能拜访的需要。 公众号:达坦科技DatenLord DatenLord官网:http://www.datenlord.io 知乎账号: https://www.zhihu.com/org/da-tan-ke-ji B站: https://space.bilibili.com/2017027518

August 31, 2023 · 1 min · jiezi

关于rust:推荐5个优秀的Rust开源项目

1、YewYew是一个开源的 Rust 框架,专门用来创立 Web 利用。借助于 Rust 弱小的性能劣势,开发人员可能创立具备交互性和高性能的前端应用程序。 Yew 采纳相似于 React 和 Eml 的基于组件架构,反对多线程,具备 与 JavaScript 的互操作性,并与虚构 DOM 和差别算法的优化下提供高效的渲染能力。尽管 yew 可能不太实用于大型项目,但在中小型我的项目,是一个十分不错的抉择,如果你想试着用Rust 来做一些炫酷的网页利用的话,Yew 能够是你的抉择之一。 2、ZolaZola 是一个弱小的开源表态网站生成器,它能够简化表态网站的创立和托管过程。Zola 的特点是疾速创立和操作简略,Zola 容许用户疾速构建网页,无需做太多简单的动静内容设置。 它还反对应用 Markdown创立内容,提供主题性能,生成轻量、加载速度快的网站,十分实用于博客、作品、文档等网站。 3、DruidDruid 是一款开源的实时数据存储系统,专为实时剖析而精心打造的零碎,领有高性能、可扩展性和弱小的互动性等特点,适宜那些须要疾速查问和剖析数据的业务场景。Druid 采纳了列式存储格局,可能反对实时数据的捕捉和解决,所以它能够无效地解决大量的流式数据。尤其在工夫序列数据分析方面体现尤其杰出,可能提供疾速的交互式查问,让开发者可能即时从数据中提取有价的信息。Druid 个别宽泛的用于监控、业务智能等畛域,Druid 具备杰出的分布式架构,蕴含了协调器、代理、治理节点等组件,能够保证系统具备高可用性和容错性。 4、TauriTauri 是一个开源框架,架构里应用了Web技术,如HTML、CSS和JavaScript,让开发者可能轻松构建实用于多个平台的原生桌面利用。这个框架比拟有意思的一点,就是能够用这些web技能,能够去开发原生利用UI和高性能体验的应用程序。 5、 FeatureProbeFeatureProbe 是基于 Feature Flags 技术开发开源的性能公布管理工具。 出于性能的思考,FeatureProbe 的后端 SDK 和客户端SDK 都是用Rust开发的,实现高性能和跨平台利用性能治理公布。在 FeatureProbe 你能够通过简略的接入教程,通过可视化的治理操作界面,实现以性能为粒度的近程配置性能公布与敞开,无需更改代码配置和部署,即可实现单功能公布和回滚。

August 24, 2023 · 1 min · jiezi

关于rust:Rust和V冒泡排序对比测试benchmark

介绍V语言在HN上常常被探讨,号称有几个长处: 平安(默认不可变变量等相似Rust个性)简略易用(语法一看就懂)内置包管理工具(VPM)跨平台UI目标初步理解V语言;学习valgrind工具获取程序运行信息;冒泡排序Rust比照V语言;作为技术决策的调研数据;V的其它劣势能够将C语言工程间接翻译为V hot reload相似于增量编译,每次批改代码不须要编译整个工程基于OpenGL/Metel/DirectX11的图形库加载3D模型和材质Camera骨骼动画穿插编译容易加一个参数就能够在Windows平台上编译为Linux,这个比拟弱小,目前支流穿插编译的我的项目例如ReactNative,Electron的做法都比这个要麻烦。v -os windows 或者 v -os linux 即可。没搞懂它背地如何实现的,可能搞了一种字节码和runtime。测试条件硬件CPU: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz 3.19 GHz RAM: 16.0 GB OSMicrosoft Windows 11WSL2 Ubuntu 22.04.2 LTS我的项目文件读取JSON parse冒泡排序所以正好有趣味测试一下V语言是否像它声称的那么好。测试条件我抉择从文件中读取JSON数据,剖析后对数组进行冒泡排序,这个测试第一能够测试IO性能,第二减少了JSON parse的过程,最初用冒泡排序查看内存应用状况。 代码如下: import osimport timeimport jsonfn main() { sw := time.new_stopwatch() str := os.read_file('../data.json')! mut arr := json.decode([][]f64, str)! // println(arr) for i in 0..arr.len { bubble_sort(mut arr[i]) // println(arr[i]) } println('耗费工夫 : ${sw.elapsed().milliseconds()}ms')}// Bubble Sort[direct_array_access]fn bubble_sort(mut array []f64) { for i in 0..array.len { for j in 0..array.len - 1 - i { if array[j] > array[j + 1] { array[j], array[j + 1] = array[j + 1], array[j] } } } // println('${array[i]}')}Rust局部代码 ...

July 3, 2023 · 2 min · jiezi

关于rust:图解-Rust-内存布局

疫情居家时看的一个英文视频(Rust Memory Layout),解开了心里的一些纳闷。从 5 号到 15 号做了残缺翻译(所有视频中的图片从新绘制花了些精力)。 侵删。 1. 二进制文件分段fn main() { println!("Hello, world!");}当咱们编写 Rust 程序时,要么是间接调用 rustc , $ rustc main.rs要么通过 cargo 生成一个可执行文件。 $ cargo build而后便能够通过终端运行或间接双击(如 windows 中)运行它。 $ ./target/debug/demoHello, world!生成的可执行二进制文件以特定格局存储数据。对于 linux 零碎来说,最常见的格局是 elf 64 。每个操作系统(如 linux、mac 或 windows )应用不同的可执行格局,只管二进制文件在各个操作系统上的格局不同,然而它的执行形式却简直雷同。可执行格局大抵是:前 x 个字节示意一些头信息,接下来的 y 字节示意其它内容,依此类推。 当你运行二进制文件时,内核会为程序提供一个间断范畴的内存地址以供其应用。当然,这并不是 RAM 上的理论内存地址,内核和硬件零碎会在程序应用内存时再将它们映射到实在的物理内存地址。这段间断范畴的内存被称为程序的虚拟地址空间。 正在运行的程序称为过程(Process)。从过程的视角来看,它能看到的只是一段间断的从 0 到最大值的地址空间。像 elf 64 这类可执行文件格局,个别都指定了一些“段(segments)”,当二进制文件执行时,内核将它们映射到内存,segment 的数量因编译器而异,在此,仅展现其中一些重要的。 编译器可能将 Rust 这种高级语言编写的代码转换为 CPU 能够执行的机器指令。 text segment 便蕴含这些指令。 text segment 也被称为 code segment。这些指令因 CPU 架构而异,例如编译给 x86-64 平台应用的可执行文件便无奈在 ARM-64 平台 CPU 上运行。text segment 是只读的,运行中的程序无奈更改它。data segment 蕴含已初始化的动态变量(即全局变量)和一些已定义且能够被批改的部分动态变量。bss 的意思是 Block Started by Symbol ,该段蕴含未初始化的全局变量。内核还会将一些附加数据,例如环境变量、程序运行参数和参数的数量映射到高位地址。 ...

June 19, 2023 · 7 min · jiezi

关于rust:Rust-X-DatenLord-l-Rust-China-Conf-2023-倒计时

Rust语言作为一种强调性能、平安和并发性的新的编程语言,吸引了越来越多的程序员想要尝试学习和应用Rust。达坦科技(DatenLord)旗下的开源我的项目Xline (用于元数据管理的分布式KV存储)就是用Rust写就的,咱们也始终动摇地做Rust语言在中国的布道。 因而,2023年6月17-18日咱们也将奔赴上海,反对Rust语言中文社区在疫情之后首次举办的大型线下Rust开发者大会。达坦科技的两位创始人将在Rust China Conf 2023上别离做主题演讲,在6月17日晚,达坦科技还将资助举办一场干货满满的workshop。 主会场王璞 达坦科技联结创始人兼CEO 演讲主题:Rust原子操作的高性能实际 简介:Rust作为新一代零碎编程语言,提供了很多实现高性能编程的组件和性能。其中,原子操作是高性能编程里比较复杂的局部,本次演讲深入分析Rust的原子操作原理,并分享咱们在Rust原子操作方面的理论教训,以便于Rust开发者更好地应用原子操作实现高性能编程。 分论坛:Rust语言与高性能实际施继成 达坦科技联结创始人兼CTO 演讲主题:Rust异步Runtime的兼容层 简介:Rust 语言倒退至今,异步运行时曾经有许多抉择,有像 Tokio 这种大而全的类型,也有像 smol 这种小而美的类型,抉择哪一种 Runtime 成为了难题。同时 lib 的提供者往往为了兼容多种 runtime 付出了很多反复的致力。为了解决这些问题,咱们将为大家提供一个 Runtime 的兼容层,可能不便大家切换应用的 Runtime,为 App 或者 Lib 开发者提供抉择的能力。 Workshop:Rust in System工夫:2023年6月17日19:00-21:00 地点:上海浦东张杨路777号上海锦江汤臣洲际大酒店三楼洲际三号厅 赵佳炜,达坦科技分布式存储工程师 题目:《如何应用Rust来编写写分布式的KV Store》 简介:分享会介绍分布式KV Store (Xline) 整体的组成,以及不同组件之间如何去交互。在广域网下的分布式系统如何高效地达成共识,以及分布式系统如何实现容错。 米明恒,DatenLord开源社区爱好者 题目:《30分钟体验Rust for Linux内核模块开发》 简介:本主题会提供构建好的docker开发环境,在30分钟内演示如何应用r4l开发一个繁难内核模块,并介绍目前r4l的倒退现状。能够自备好电脑现场体验。 魏星达,上海交通大学软件学院助理传授 题目:Building microsecond-scale system with modern networking in Rust 简介:随着新型网络技术,如RDMA的遍及,古代分布式应用的提早降到了毫秒甚至微秒级别。这为构建系统软件带来了新的挑战。Rust的zero-cost形象及内存治理能力可能为构建新型分布式应用带来新的时机。我将分享利用Rust在用户态及内核态构建新型系统软件的相干教训,包含如何利用Rust形象RDMA硬件的底层形象及如何在内核构建一个毫秒级的容器启动机制。 报名注意事项在workshop中,演讲者将分享他们在操作系统开发、嵌入式零碎、和分布式系统等畛域中应用Rust的理论案例。通过这些案例,听众将理解到Rust语言在解决特定问题、进步零碎安全性、升高资源耗费和加强性能方面的劣势。演讲者也将为听众提供很多的实战技巧和教训,分享他们在理论我的项目中的挑战和解决方案,以帮忙听众理解不同行业背景下的最佳实际,并从中取得启发。 无论您是否报名参加本次Rust China Conf 2023,晚间的workshop收费向所有Rust爱好者凋谢,请对Rust实际与利用有趣味的开发者扫码或点击报名。 报名链接:http://hdxu.cn/4qa6N 增加小助手微信DatenLord_Tech (或分割邮箱info@datenlord.com),进入达坦科技Rust前沿技术交换群 更多对于Rust China Conf 2023官网信息,请查阅 ...

June 12, 2023 · 1 min · jiezi

关于rust:文盘Rust-tokio绑定cpu实践-京东云技术团队

tokio 是 rust 生态中风行的异步运行时框架。在理论生产中咱们如果心愿 tokio 应用程序与特定的 cpu core 绑定该怎么解决呢?这次咱们来聊聊这个话题。 首先咱们先写一段简略的多任务程序。 use tokio::runtime;pub fn main() { let rt = runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap(); rt.block_on(async { for i in 0..8 { println!("num {}", i); tokio::spawn(async move { loop { let mut sum: i32 = 0; for i in 0..100000000 { sum = sum.overflowing_add(i).0; } println!("sum {}", sum); } }); } });}程序非常简单,首先结构一个tokio runtime 环境,而后派生多个 tokio 并发,每个并发执行一个有限循环做overflowing\_add。overflowing\_add函数返回一个加法的元组以及一个示意是否会产生算术溢出的布尔值。如果会产生溢出,那么将返回包装好的值。而后取元祖的第一个元素打印。 这个程序运行在 Ubuntu 20 OS,4 core cpu。通过nmon的监控如下: ...

June 5, 2023 · 2 min · jiezi

关于rust:RustChinaConf-2023官网上线精彩议题早知道

随着大会日益邻近,咱们RustChinaConf 2023筹备委员会的工作也在井井有条的进行中。最新的好消息来了,官网已上线,拜访地址: https://rustcc.cn/2023rustchinaconf/ 从官网进去也能够报名! 大会工夫地址6.17 - 6.18浦东新区张杨路777号 上海锦江汤臣洲际酒店 门票报名本次大会门票集体普票票价 399 元,蕴含两天的会议议程及两天的中午的自助餐。还有精美 T-shirt,福袋哦。 早鸟票 299 ,只凋谢100张(已售罄)。普票还有一些余量,欲购从速。 扫码立刻报名购票 https://www.huodongxing.com/event/1702066803600 本次大会共收集到了60多个议题申请,通过组委会评审,选出了其中40个左右的议题。议题的评审规范如下: 议题审核规范为了晋升大会的议题内容品质,议题将不与赞助商权利绑定。本次议合乎评审规定者优先思考。评审后果将分批次放出,名额满即止。 议题入选评审规范: 内容要围绕 Rust ,题目明确,纲要清晰内容面向 Rust  的学术研究 / 生产教训  优先内容面向 Rust 守业产品 且 围绕 Rust 技术层面 者 优先对 Rust 生态有影响的开源我的项目优先在往期大会或meetup并未呈现的内容优先禁止呈现国家政策明令禁止的内容要合乎社区友善度禁止呈现大量广告PPT评审规范 PPT  页数 20 页为佳(半小时) ,次要是避免超过议题工夫PPT 内容要与纲要吻合 禁止呈现国家政策明令禁止的内容论坛设置本次大会共设两个主论坛(上午),六个分论坛(下午)。 六个分论坛别离是:6.17 分论坛一:Rust 语言和高性能实际分论坛分论坛二:数据库分论坛分论坛三:Rust 教育与商业实际分论坛 6.18分论坛四:嵌入式与操作系统、云原生分论坛分论坛五:Rust 与区块链、密码学和平安分论坛分论坛六:跨平台:Rust 与 WebAssembly 、挪动开发分论坛 精彩议题早晓得《应用硬件加速Tokio》Tokio是Rust风行的调度框架,本次演讲将介绍Tokio调度原理及其实现,并提供用硬件加速调度的设计与实现,展示软硬件联合的劣势。 戴翔 Intel微软MVP,Dapr maintainer,摸索软硬件联合新范式 《Rust OS 开源操作系统训练营的教与学》从2020年起清华大学开始尝试让学生用Rust语言来写操作系统,并面向全国高校发展Rust OS开源训练营教学。4年来造成了Rust语言编程,RISC-V体系架构,OS大试验,ArceOS组件化OS和Hypervisor虚拟化专题等一系列课程,为国内大规模造就用Rust写操作系统的人才积攒了教训。 李明 清华大学清华大学计算机系硕士,2004年参加创建了国内最早的嵌入式Linux职业教育机构北京亚嵌教育,造就了6000余名嵌入式开发工程师。2022年开始创立了 os2edu.cn 开源操作系统社区平台和 rustedu.com 阿图教育网站,通过零碎的课程培训了上千名 Rust 编程开发人才。 《Rust挪动端并发框架》摸索Rust异步框架在挪动端以及嵌入式场景的利用,探讨社区现有并发框架存在的问题以及挪动端对并发框架的诉求。介绍Ylong开源调度框架并分享实际,重点包含工作优先级调度机制以及工作结构化并发。瞻望Rust并发框架在挪动端的可能性。 陈明煜 华为陈明煜,毕业于加州大学圣地亚哥分校,就任于华为。目前积极探索并打造Rust挪动端异步框架。 《硬件守业公司的Rust利用和转型》鹿仔科技(重庆)有限公司是一家专一于生命科学仪器研发的公司,目前正在摸索将局部嵌入式和桌面端业务采纳Rust代替C/C++。本次演讲将涵盖以下内容:1. 作为一个硬件守业公司,咱们抉择Rust的起因;2. 在嵌入式和桌面端畛域尝试将C/C++替换为Rust的实际;3. 公司将来研发的锈化思路和构想。 ...

June 1, 2023 · 1 min · jiezi

关于rust:tmc2209堵转的问题

总结一下tmc2209在diag脚输入堵转状态的配置 1.串口配置串口波特率会主动适配,最大值最小值和2209的外部时钟有关系,大略9600到500k都能适配,应用半双工通信,发完再收,以stm32为例 TMC_uart_write_datagram_t *tmc_uart_read (trinamic_motor_t driver, TMC_uart_read_datagram_t *datagram){ memset(read_res.data, 0, 8); HAL_HalfDuplex_EnableTransmitter(&huart1); HAL_UART_Transmit(&huart1, datagram->data, 4, MOTO_MTMC2209_SEND_RECV_TIME_OUT); HAL_HalfDuplex_EnableReceiver(&huart1); int ret = HAL_UART_Receive(&huart1, read_res.data, 8, MOTO_MTMC2209_SEND_RECV_TIME_OUT); return &read_res;}残缺代码能够参考tmc2209库 2.堵转检测2209的堵转只有在有肯定速度时候才会开始检测,必须满足 TCOOLTHRS >= tstep > TPWMTHRS 具体大于多少开始通过堵转检测通过TCOOLTHRS来配置的,能够通过tstop来配置,tstop是一个脉冲外部的时钟周期数,能够通过0x12读取到,而后将TCOOLTHRS间接配置一个比tstop大一点的值TPWMTHRS是速度太高了是否切换到通知模式,能够设置成0不切换

May 24, 2023 · 1 min · jiezi

关于rust:Rust-笔记-错误处理泛型特质测试

The Rust Programming LanguageRust 编程语言笔记。 起源:The Rust Programming Language By Steve Klabnik, Carol Nichols 翻译参考:Rust 语言术语中英文对照表 错误处理Rust 把谬误分为两类: 可复原的(recoverable):例如:文件未找到等。该类谬误能够提醒用户查错后持续运行程序不可复原的(unrecoverable):例如:数组拜访越界等。该类谬误呈现后必须终止程序对于可复原谬误,Rust 采纳 Result<T, E> 来解决;对于不可复原谬误,Rust 采纳 panic!() 宏(macro) 来解决。 在其余编程语言中,通常不会对谬误进行分类,而是应用 Exception 对立解决。 不可复原谬误和 panic!有两种状况会执行 panic!: 显式调用 panic!() 宏(macro)程序呈现谬误,例如:数组拜访越界默认状况下,Rust 会打印错误信息、解开(unwind)、清理栈内存、退出程序。通过环境变量,能够打印调用栈(calling stack),有助于更好 debug。 解开(unwind)栈内存 VS 立刻终止 默认状况下,当 panic 产生时,程序会开始解开(unwinding),Rust 会回到栈内存中,找到每个函数并清理数据。该操作须要破费大量资源。另一种代替形式是,**立刻终止(abort)**程序,不清理内存。 此时,程序应用的内存会由操作系统来清理。要切换到立刻终止选项,在 Cargo.toml 文件中的 [profile.release] 区域增加 panic = 'abort'; [profile.release]panic = 'abort'让咱们看一下显式调用 panic!() 的状况: fn main() { panic!("Crash and burn");}如果运行上述程序,编译器会弹出: $ ./testthread 'main' panicked at 'Crash and burn', test.rs:2:5note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace阐明此时程序 panicked。 ...

May 19, 2023 · 6 min · jiezi

关于rust:保姆级教程如何用Rust编写一个ChatGPT桌面应用-京东云技术团队

为什么咱们须要一个桌面利用起因切实太多,咱们须要便捷地导出记录,须要在答复长度超长的时候主动加上“持续”,须要珍藏一些很酷很实用的prompt...... (首先我假如你是一名如我一样习惯用IDEA开发的java仔) 为什么是用Rust编写效率高、资源占用量低。安全性高:Rust 是一种内存平安的语言,其所有操作都通过零碎级别的严格代码查看,缩小了运行期间的解体和内存透露等问题的呈现。可维护性高:Rust 可能更好地编写可保护的代码,并且反对面向对象编程和函数式编程,这使得开发人员可能更好地组织代码,易于了解和批改。同时,Rust 的模块化设计使得不同的开发人员能够同时在我的项目中工作,而不会互相烦扰。跨平台:Rust 广泛支持多种操作系统和平台,包含 Windows,macOS,Linux 和 Android 等,这使得开发人员可能设计实用于不同平台和设施的利用。如何用Rust编写一个桌面利用1.装置 Rust 语言工具链:首先,请确保你已装置了 Rust 编程语言工具链,包含 Rust 编译器 (rustc) 和包管理工具 (cargo)。能够通过拜访 Rust 官方网站 并遵循阐明来装置。 2.装置 Rust 插件:关上 IntelliJ IDEA,而后转到 "File" > "Settings" (Windows/Linux) 或 "IntelliJ IDEA" > "Preferences" (macOS)。在设置窗口中,抉择 "Plugins",搜寻 "Rust",而后单击 "Install"。装置实现后,重启 IntelliJ IDEA。 3.创立新的 Rust 我的项目:在 IntelliJ IDEA 中,抉择 "File" > "New" > "Project",而后在我的项目类型列表中抉择 "Rust"。依照提醒配置我的项目设置,而后单击 "Finish" 以创立新我的项目。 4.增加 GUI 库:你能够抉择的 GUI 库(如 GTK 或 Qt),在我的项目的 Cargo.toml 文件中增加相应的依赖项。例如,对于 GTK,须要增加如下依赖: ...

May 15, 2023 · 1 min · jiezi

关于rust:Rust-笔记

The Rust Programming LanguageRust 编程语言笔记。 起源:The Rust Programming Language Book 。 装置应用 rustup 来装置 Rust。 Rust 源文件以 .rs 作为扩展名。 几个罕用的命令: 编译:rustc .rs-file 运行:./compiled-file查看 Rust 编译器版本:rustc --version查看 rustup 版本:rustup --version更新 Rust 编译器:rustup update卸载 Rust 和 rustup:rustup self uninstall本地文档:rustup doc包管理工具Rust 的包管理工具是 Cargo。 几个罕用的命令: 查看 cargo 的版本:cargo --version新建我的项目:cargo new我的项目构建:cargo build运行我的项目:cargo run我的项目查看:cargo check:该命令确保我的项目能够编译,但不生成可执行文件,速度比 cargo build 更快包Rust 应用 TOML(Tom's Obvious Minimal Language) 格局来治理依赖。 应用 cargo new 创立新我的项目后,在该项目标目录下会有名为 Cargo.toml 的文件来治理依赖和包。 能够应用 cargo add 来增加依赖,也能够在 .toml 文件的 [dependencies] 字段下增加包名。 ...

May 10, 2023 · 5 min · jiezi

关于rust:文盘Rust-rust连接oss-京东云技术团队

作者:京东科技 贾世闻 对象存储是云的根底组件之一,各大云厂商都有相干产品。这里跟大家介绍一下rust与对象存储交到的根本套路和其中的一些技巧。 根本连贯咱们以 [S3 sdk]( https://github.com/awslabs/aws-sdk-rust)为例来说说根本的连贯与操作,作者验证过aws、京东云、阿里云。次要的增删改查性能没有什么差异。 建设客户端let shared_config = SdkConfig::builder() .credentials_provider(SharedCredentialsProvider::new(Credentials::new( "LTAI5t7NPuPKsXm6UeSa1", "DGHuK03ESXQYqQ83buKMHs9NAwz", None, None, "Static", ))) .endpoint_url("http://oss-cn-beijing.aliyuncs.com") .region(Region::new("oss-cn-beijing")) .build(); let s3_config_builder = aws_sdk_s3::config::Builder::from(&shared_config); let client = aws_sdk_s3::Client::from_conf(s3_config_builder.build());建设Client所须要的参数次要有你须要拜访的oss的AK、SK,endpoint url 以及服务所在的区域。以上信息都能够在服务商的帮忙文档查问到。 对象列表let mut obj_list = client .list_objects_v2() .bucket(bucket) .max_keys(max_keys) .prefix(prefix_str) .continuation_token(token_str);let list = obj_list.send().await.unwrap();println!("{:?}",list.contents());println!("{:?}",list.next_continuation_token());应用list\_objects\_v2函数返回对象列表,相比list\_objects函数,list\_objects\_v2能够通过continuation\_token和max_keys管制返回列表的长度。list.contents()返回对象列表数组, list.next\_continuation\_token()返回持续查问的token。 上传文件let content = ByteStream::from("content in file".as_bytes()); let exp = aws_smithy_types::DateTime::from_secs(100);let upload = client .put_object() .bucket("bucket") .key("/test/key") .expires(exp) .body(content);upload.send().await.unwrap();指定bucket及对象门路,body承受ByteStream类型作为文件内容,最初设置过期工夫expires,无过期工夫时不指定该配置即可。 下载文件let key = "/tmp/test/key".to_string();let resp = client .get_object() .bucket("bucket") .key(&key) .send() .await.unwrap();let data = resp.body.collect().await.unwrap();let bytes = data.into_bytes();let path = std::path::Path::new("/tmp/key")if let Some(p) = path.parent() { std::fs::create_dir_all(p).unwrap();}let mut file = OpenOptions::new() .write(true) .truncate(true) .create(true) .open(path).unwrap();let _ = file.write(&*bytes);file.flush().unwrap();通过get_object()函数获取GetObjectOutput。返回值的body 就是文件内容,将 body 转换为 bytes,最初关上文件写入即可。 ...

May 10, 2023 · 2 min · jiezi

关于rust:RustDesk-远程桌面

RustDesk 是一款开源远程桌面软件。有云服务器的话,能够几分钟就搭一个,本文是搭建的记录。 自建服务器下载服务器程序, # 上传进服务器,假如其 IP 为 `x.x.x.x`scp rustdesk-server-linux-amd64.zip ubuntu@x.x.x.x:登录进服务器: # 解压unzip rustdesk-server-linux-amd64.zip# 重命名mv amd64 rustdeskrustdesk/ 下有: hbbs - RustDesk ID注册服务器hbbr - RustDesk 中继服务器装置 supervisor 进行部署,以常驻后盾: # 装置sudo apt install supervisor -y# 配置# ./hbbs -r <hbbr运行所在主机的地址[:port]># ./hbbrsudo -icat <<-EOF >> /etc/supervisor/supervisord.conf[program:hbbs]directory=/home/ubuntu/rustdeskcommand=/home/ubuntu/rustdesk/hbbs -r x.x.x.xpriority=999autostart=trueautorestart=truestartsecs=10startretries=3stdout_logfile=/var/log/hbbs_out.logstdout_logfile_maxbytes=1MBstdout_logfile_backups=10stdout_capture_maxbytes=1MBstderr_logfile=/var/log/hbbs_err.logstderr_logfile_maxbytes=1MBstderr_logfile_backups=10stderr_capture_maxbytes=1MBenvironment=nocleanup=false[program:hbbr]directory=/home/ubuntu/rustdeskcommand=/home/ubuntu/rustdesk/hbbrpriority=999autostart=trueautorestart=truestartsecs=10startretries=3stdout_logfile=/var/log/hbbr_out.logstdout_logfile_maxbytes=1MBstdout_logfile_backups=10stdout_capture_maxbytes=1MBstderr_logfile=/var/log/hbbr_err.logstderr_logfile_maxbytes=1MBstderr_logfile_backups=10stderr_capture_maxbytes=1MBenvironment=nocleanup=falseEOFexit# 更新sudo supervisorctl update all# 查看sudo supervisorctl status all查看公钥: cat ~/rustdesk/id_ed25519.pub装置客户端下载客户端程序, # 装置,例如 Linux 客户端sudo apt install ./rustdesk-1.1.9.deb配置“ID/中继服务器”, 第一个“ID服务器”,填 IP 或绑好的域名。其余“服务器”不填,会主动推导。最初一个“Key”,填公钥,以加密连贯。 这样当前,一个客户端就能近程另外一个客户端了。 GoCoding 集体实际的教训分享,可关注公众号!

May 9, 2023 · 1 min · jiezi

关于rust:RustShyper基于-Rust-语言的高可靠开源嵌入式-Hypervisor

「Rust-Shyper 是北京航空航天大学计算机学院王雷传授团队设计开发的虚拟机监控器,该零碎基于 Rust 语言,实现了一个高牢靠、嵌入式 Hypervisor。2023 年 2 月 15 日 Rust-Shyper 正式在 openEuler 社区开源。」 我的项目地址:https://gitee.com/openeuler/rust_shyper Rust-Shyper 是一款基于 AArch64 架构、「Rust 编写」、面向无人车、机器人等嵌入式场景的「Type-1 型」虚拟机监控器(Hypervisor)。其设计指标是在进步资源利用率的同时,保障虚拟机实时性、隔离性与内存平安。此外,Rust-Shyper 反对「虚拟机迁徙」(VM migration)和「监控器动静降级」(Hypervisor Live-update)两种热更新机制,可能在不影响虚拟机运行的状况下,动静修复 Hypervisor 的软件破绽。目前该零碎能够在 NVIDIA Jetson TX2、Raspberry Pi 4 和 QEMU 平台上运行,反对实时和非实时虚拟机,可运行 Linux 和 RTOS。 往年的 「openEuler Developer Day 2023 嵌入式分论坛」 进行了 Rust-Shyper 我的项目 “基于Rust的嵌入式虚拟机监视器及热更新技术” 的主题演讲,可通过以下链接观看视频回放(21日嵌入式分论坛,议题从00:49:38开始): https://www.openeuler.org/zh/interaction/summit-list/devday2023/ 嵌入式虚拟化的挑战物联网的一直倒退使得古代嵌入式零碎正在朝着通用零碎和混合要害零碎的方向演变,其承载的工作往往有着不同的可靠性、实时性和验证级别,如何保障不同关键性工作之间的互相隔离以及实时性成为了一个难题。虚拟化技术提供的资源隔离伎俩成为了解决上述问题的要害,但嵌入式虚拟化也面临一些挑战: 如何保障虚拟机之间的「隔离性和安全性」,避免歹意攻打;如何保障虚拟机之间的通信效率和「实时性」,防止提早或者抖动;如何保障 「Hypervisor 自身的稳定性和可靠性」,防止出现故障。Rust-Shyper 的设计理念和特点「内存平安」:利用 Rust 语言类型零碎和内存平安模型,保障 Hypervisor 的内存平安;「强隔离性」:利用硬件辅助虚拟化,实现虚拟机间的平安隔离和故障隔离;「丰盛的设施模型」:为进步资源利用率,实现了直通设施、中介传递和全模仿等多种设施模型;「实时虚拟化」:针对性能需求 ,实现资源直通以及实时虚拟化技术;「虚拟机监控器热更新技术」:实现了虚拟机迁徙和监控器动静降级两类视器热更新机制。Rust-Shyper 零碎架构和性能 Rust-Shyper 是一款基于 AArch64 体系结构的 Type-1 虚拟机监控器,整个构造蕴含三个层级: 最底层为硬件层级,对应 ARMv8 EL3 固件层级;中间层为虚拟机监控器层,对应 ARMv8 EL2 虚拟化层级,该层级也是 Rust-Shyper 代码所处的特权层级;最上层为虚拟机层级,对应 ARMv8 EL1 和 EL0 层级。为了合乎嵌入式应用的需要,Rust-Shyper 通过提供不同的虚拟机类型,来提供差异化的虚拟化服务,Rust-Shyper 中反对治理虚拟机(MVM)、客户虚拟机(GVM)、实时虚拟机(RTVM)等三类虚拟机。 ...

April 27, 2023 · 1 min · jiezi

关于rust:Rust二进制文件大小优化

Rust二进制文件大小优化,在优化二进制文件过程中,编译工夫会减少,然而个别编译时候的优化会放慢程序执行速度 初始化我的项目在Ubuntu22下面进行试验 创立我的项目 $ cargo new demo批改Cargo.toml如下,须要退出一点罕用的库 [dependencies]tokio = {version = "1", features = ["full"]}tracing = "0.1"tracing-subscriber = "0.3"批改main.rs如下 #[tokio::main]async fn main() { tracing_subscriber::fmt::init(); loop { tokio::time::sleep(std::time::Duration::from_secs(1)).await; tracing::info!("Hello, world!"); }}debug和release的大小比照编译 $ cargo build$ cargo build -r查看大小 $ ll target/* target/debug:总计 28M-rwxrwxr-x 2 gong gong 28M 四月 25 15:47 demo...target/release:总计 5.0M-rwxrwxr-x 2 gong gong 5.0M 四月 25 15:46 demo....可见release版本二进制大概是debug版本的17%,后续所有二进制优化采纳release 5M大小为基准,每次优化都只改变一个配置项作为比照 优化符号信息symbols在Linux和macOS上,默认状况下,符号信息蕴含在编译的.elf文件中,正确执行二进制文件不须要此信息 配置Cross.toml [profile.release]strip = true 编译之后demo二进制变为887k,约为之前的17%,成果好 这个配置项在我的项目比拟大的时候,比方最终二进制是100M优化成果就不怎么显著了,个别符号信息是会减小几M大小,存在一个下限 配置优化level默认的release opt-level是3,debug opt-level是0 ...

April 25, 2023 · 1 min · jiezi

关于rust:DatenLord前沿技术分享No24

达坦科技专一于打造新一代开源跨云存储平台DatenLord,通过软硬件深度交融的形式买通云云壁垒,致力于解决多云架构、多数据中心场景下异构存储、数据对立治理需要等问题,以满足不同行业客户对海量数据跨云、跨数据中心高性能拜访的需要。在本周的前沿技术分享中,咱们邀请到了一位喜好硬件的软件工程师米明恒,来为大家分享Rust嵌入式开发生态介绍及入门。 1、演讲题目Rust嵌入式开发生态介绍及入门 2、演讲工夫2023年4月30日上午10:30 3、演讲人米明恒软件工程师,硬件爱好者 4、引言Rust能够在资源无限的嵌入式处理器上进行开发,并且提供良好的开发体验。本次分享将介绍Rust在嵌入式开发畛域的社区和生态环境,心愿通过本次分享能够让更多同学退出到Rust嵌入式生态的建设中。  5、内容简介本次分享将从全局视角登程,梳理社区中各种我的项目之间的关系,帮忙开发者疾速相熟Rust嵌入式开发生态并搭建开发环境。丝滑的开发体验离不开社区中各种开源组件的反对,故此在相熟完现有生态后,将介绍一些为开源社区进行奉献的路径,心愿借此吸引更多开发者退出到Rust嵌入式社区的建设中,让将来的嵌入式开发更加简洁高效。 6、直播预约欢迎您预约直播,或者登录腾讯会议观看直播:会议号:955-6910-3992

April 24, 2023 · 1 min · jiezi

关于rust:如何优雅地组织Rust项目中的异步代码

概要很多应用过Async Rust的人都可能有过被其要求的束缚所困扰的经验,例如,spawned task有'static的要求,MutexGuard不能逾越.await,等等。克服这些束缚须要认真地设计代码构造,很可能会导致艰涩和嵌套的代码,这对开发人员和审查人员都是一种挑战。在这篇文章中,我将首先列出我在编写async Rust代码时的一些痛点。而后,我将指出咱们真正须要异步代码的场景,并探讨为什么咱们应该把异步和非异步代码离开。最初,我将展现我是如何在最近的一次Curp重构中实际这一准则的。 痛点:Spawned Task必须是'static在spawn一个新的async task的时候,编译器并不知道该task会被执行多久,可能很短暂,也可能会始终执行至程序运行完结。所以,编译器会要求该task所含的所有类型都领有'static的生命周期。 这样的限度使得咱们经常能在spawn前看到不少的clone代码。当然,这些代码从某种角度来讲能够帮忙程序员更好天文清哪些变量的所有权是要被移交给新的task的,但同时,也会使得代码看上去很啰嗦,不够简洁。 let a_arc = Arc::clone(&a);let b_arc = Arc::clone(&b);tokio::spawn(async move { // ...});非Send的变量的持有不能够逾越.await点这点限度背地的起因tokio的task并不是固定在一个线程上执行的,闲暇线程会被动“偷取”繁忙线程的task,这就须要task能够被Send。 请看上面一段代码: let mut log_l = log.lock();log_l.append(new_entry.clone());broadcast(new_entry).await;尝试编译后,会发现报错:log_l不能逾越.await点持有。 天然,为了使得拿着锁的critical section尽量地短,咱们不须要拿着锁过.await点,所以咱们在其中加一行放锁的代码: let mut log_l = log.lock();log_l.append(new_entry.clone());drop(log_l);broadcast(new_entry).await;很惋惜,还是不能通过编译,这是因为编译器目前只能通过计算代码Scope的形式来判断一个task是否能够被Send。如果说上一个痛点还有肯定的益处,那么这个问题就纯正来源于编译器的限度了。所以咱们必须把代码改成这个样子: { let mut log_w = log.write(); log_w.append(new_entry.clone());}broadcast(new_entry).await;如果一个函数中有须要拿多把锁,又有很多的异步调用,代码就会嵌套起来,变得复杂艰涩。Side Note: 咱们晓得tokio本人有个异步的锁tokio::sync::Mutex,它是能够被hold过.await的。但要留神的是,大多数状况下,咱们并不会须要异步锁,因为异步锁通常意味着拿着锁的critical section是会十分长的。所以,如果咱们须要在异步代码中拿锁,不要不加思索地应用异步锁,事实上,在tokio官网文档中,也是更加倡议应用同步锁的。 应用异步Rust的场景和组织形式如果咱们常常在我的项目开发中遇到上述问题,天然就会开始思考其产生的起因以及该怎么防止。我认为一个很重要的因素就是没有把async和非async的代码给离开,或者说,更实质的起因是咱们没有在设计我的项目架构的时候将须要async的局部和不须要async的局部离开。所以接下来,我将梳理咱们什么时候能力真正地用到Async Rust? I/O当咱们进行比拟耗时的I/O操作,咱们不想让这些操作block住咱们以后的线程。所以咱们用异步I/O,当运行到await 的时候,I/O就能够到后盾去做,让其它的task执行。 // .await will enable other scheduled tasks to progresslet mut file = File::create(“foo.txt”).await?;file.write(b"some bytes”).await?;后台任务后台任务的task通常会随同着一个channel的接收端呈现。 tokio::spawn(async move { while let Some(job) = rx.recv().await { // ... }};并发工作并发地spawn多个task能够更高效地利用多核处理器。 ...

April 21, 2023 · 2 min · jiezi

关于rust:精彩回顾|48-Beijing-Rust-Meetup

2023年4月8日,达坦科技联结南京大学、CloudWeGo、华为等技术专家胜利举办了题为Rust X的meetup。开发者们不仅线下踊跃报名参加,更在线上直播中踊跃参加互动,一起探讨Rust作为一种强调性能、平安和并发性的编程语言的各种利用和实际。演讲者与观众间灵感与想法的一直碰撞正印证着本次的主题:用Rust编程语言“点亮”的任何利用、实际,和摸索Rust的有限可能性。接下来让咱们一起来回顾本次流动的精彩霎时。 精彩回顾本次meetup首先由《Rust 编程之道》作者、Rust 中文社区布道者张汉东老师收场,Rust语言以安全性著称,但他演讲的主题却为《了解 Unsafe Rust》 。张老师从为什么须要unsafe、unsafe能做什么,到unsafe平安哲学、Unsafe编程准则,循序渐进,由浅入深地一步步解说。最初更是援用reddit热帖,将Unsafe Rust与Zig进行安全性比照:Unsafe Rust 的平安哲学让开发者能够充沛地思考裸指针的平安问题,对开发者有更高的要求,零碎的安全性可能更好,Reddit热帖的作者尽管推崇Zig策略,但Zig 的安全策略并非百分百平安,同样须要开发者思考一些平安因素,因而,并没有什么谁比谁更平安一说。 [点击链接跳转张汉东老师分享《了解 Unsafe Rust》](https://www.bilibili.com/video/BV1c24y1A7aK/?spm_id_from=333....) 接下来南京大学计算机科学与技术系助理研究员冯洋老师进行《基于理论场景利用剖析的Rust库含糊测试技术报告》的演讲分享。Rust是一种承诺内存平安和并发平安的语言,而各类Rust库中API的破绽与缺点可能会对所有应用该库的程序产生影响。为了进一步保障Rust库的平安,冯老师提出了一种依附现有Rust生态系统来生成含糊测试指标的办法,利用MIR解析待测库所在生态系统中的我的项目,找到事实中API之间的调用和依赖关系,从而从中提取出待测库的API序列,依此生成Rust库的含糊测试指标。 点击链接跳转冯洋老师分享《RUFES》 第三位出场分享的是达坦科技联结创始人兼CTO施继成,演讲主题是《Rust for linux6.2》。他从为什么抉择Rust、Rust for Linux以及Linux6.2三个方面顺次递进介绍。咱们抉择Rust不仅因为其领有与C语言相似的高效率个性,其同时也具备Java语言所领有的强安全性,高效率与高安全性的组合带来了许多Rust在Linux中的尝试。Rust for Linux并不是要取代Linux中所有的C代码或是在Rust中提供所有的Linux内核模块,它是一个框架或工具,帮忙用Rust构建Linux模块。接着,施老师介绍了Rust for Linux的外围组成部分与如何编译Linux的Rust反对,并以ChrDev为例做了进一步的解说。最初,施老师对Linux6.2做了简略的评论,他认为Linux6.2减少了一些根本反对,除了将工具链从夜间版改到稳定版(1.62.0 )以外,这个版本也改良了对字符串和格式化、谬误、打印、内存调配、宏的反对。但若想间接从Rust for Linux我的项目移植还得期待当前的版本。 点击链接跳转施继成老师分享《Rust for Linux 6.2》 华为技术有限公司叶天星老师接着就《用Rust实现Git传输协定、Git对象解析和数据库存储》进行了分享,他从DVCS,Git Objects,Git Packfile和Git 传输协定四个方面进行了介绍。Git作为“版本控制软件”之一,是目前最受欢迎的管制版本,其目标不仅是存储一组文件的以后状态,而且还包含这些文件随工夫如何变动的历史记录。它应用了一种称为对象存储的形式来存储代码版本信息,且领有blob、tree、commit 和 tag四种对象类型,叶老师也别离顺次对它们进行了介绍和解说。Git能够应用四种不同的协定来传输数据:Local、HTTP、SSH 和 Git,本次分享中次要就HTTP 和 SSH进行了探讨,在演讲的最初,叶老师进行了demo演示,以不便观众进一步了解与把握。 点击链接跳转叶天星老师分享《用Rust实现Git传输协定、Git对象解析和数据库存储》 最初,来自CloudWeGo社区的 Monoio 我的项目负责人茌海老师做了《Monoio:一个基于 io-uring 的 Rust Runtime》的分享,他介绍了Rust 语言中的异步机制、Monoio设计与Runtime的比照及利用。茌老师举例说明,揭发了Async Await 背地的机密,并对Rust 中对异步 Task 的外围形象--Future形象,进行了更深一步的解说。Monoio设计通过 Feature 与代码指定 Driver 并有条件地做运行时探测,领有裸露对立的 IO 接口同时外部利用 OpAble 对立组件实现,是下层无感知的 Driver 探测与切换;其高性能、功能性与兼容接口等特点也带来了诸多便当。 点击链接跳转茌海老师分享《Monoio:一个基于 io-uring 的 Rust Runtime》 ...

April 14, 2023 · 1 min · jiezi

关于rust:使用rust开发android底层

本文档应用rust开发android程序,只波及到底层开发,不波及任何ui相干,开发前举荐装置好magisk框架,不便前面获取手机root权限,或者有别的计划能够使adb获取到root权限也行 把android看成是一个裁剪了很多模块的linux操作系统,前面的操作与概念就好了解很多了 linux权限阐明root权限,超级权限,能够得心应手,随心所欲一般权限Android权限阐明平安体系结构设计的外围是:默认状况下,任何应用程序都无权执行任何会对其余应用程序、操作系统或用户产生负面影响的操作为了爱护Android用户的隐衷,防止上述负面影响,Android对权限进行治理:Android利用在须要应用某些性能时必须进行权限的申请,而依据权限的爱护级别,零碎可能会主动授予权限,或者提醒用户批准申请Android包装了一套本人的权限体系 rootplatformmediashared...root权限是超级权限,该权限能够对系统进行任意操作,这一点与linux雷同提供了拜访system目录的权限,即system权限,对应Android的权限体系为platform试验设施信息Xiaomi Redmi note 7 Pro rust我的项目创立$ cargo new android-agent批改Cargo.toml的依赖信息如下 [dependencies]tokio = { version = "1", features = ["full"]}tracing = "0.1"tracing-subscriber = "0.3"批改main.rs #[tokio::main]async fn main() { tracing_subscriber::fmt::init(); loop { tracing::info!("Hello world!"); tokio::time::sleep(std::time::Duration::from_secs(1)).await; }}因为自己是在Ubuntu22环境下开发,底层C库与android的库可能有较大差别,所以编译须要依赖一个rust的穿插编译我的项目cross,工具装置与操作自行查看该我的项目文档 https://github.com/cross-rs/cross查看rust反对编译的android类型 $ rustc --print target-list |grep androidaarch64-linux-androidarm-linux-androideabiarmv7-linux-androideabii686-linux-androidthumbv7neon-linux-androideabix86_64-linux-android因为目前测试机是实在的Android手机,Android手机根本都是arm架构的,所以编译target抉择aarch64-linux-android,如果是电脑下面的虚构手机,这些年的非苹果电脑根本都是x86_64架构的,能够抉择x86_64-linux-android 应用的包可能比拟新,cross工具发行release和以后工夫可能存在较大时间差到时某些GLibc版本可能差别较大导致编译报错,所以还须要新建一个文件Cross.toml,配置应用最新的cross编译镜像 [target.aarch64-linux-android]image = "ghcr.io/cross-rs/aarch64-linux-android:edge"开始执行编译 $ cross build --target aarch64-linux-android -r应用adb把编译生成的文件推送到android手机上,留神,须要推送到/sdcard上面,/sdcard的属主/归属组是root/root $ adb push target/aarch64-linux-android/release/android-agent /sdcard/target/aarch64-linux-android/release/android-agent: 1 file pushed. 30.8 MB/s (2677824 bytes in 0.083s)进入android手机shell环境 $ adb shelladb获取root权限,该操作是装置了Magisk之后才能够这样获取 ...

April 14, 2023 · 1 min · jiezi

关于rust:文盘Rust-用Tokio实现简易任务池

作者:京东科技 贾世闻 Tokio 无疑是 Rust 世界中最优良的异步Runtime实现。非阻塞的个性带来了优异的性能,然而在理论的开发中咱们往往须要在某些状况下阻塞工作来实现某些性能。 咱们看看上面的例子 fn main(){ let max_task = 1; let rt = runtime::Builder::new_multi_thread() .worker_threads(max_task) .build() .unwrap(); rt.block_on(async { println!("tokio_multi_thread "); for i in 0..100 { println!("run {}", i); tokio::spawn(async move { println!("spawn {}", i); thread::sleep(Duration::from_secs(2)); }); } }); }咱们期待的运行构造是通过异步工作打印出99个 “spawn i",但理论输入的后果大略这样 tokio_multi_threadrun 0run 1run 2.......run 16spawn 0run 17......run 99spawn 1spawn 2......spawn 29......spawn 58spawn 5959执行完前面就没有输入了,如果把max_task设置为2,状况会好一点,然而也没有执行完所有的异步操作,也就是说在资源有余的状况下,Tokio会摈弃某些工作,这不合乎咱们的预期。那么能不能再达到了某一阀值的状况下阻塞一下,不再给Tokio新的工作呢。这有点相似线程池,当达达最大线程数的时候阻塞前面的工作待有开释的线程后再持续。 咱们看看上面的代码。 fn main(){ let max_task = 2; let rt = runtime::Builder::new_multi_thread() .worker_threads(max_task) .enable_time() .build() .unwrap(); let mut set = JoinSet::new(); rt.block_on(async { for i in 0..100 { println!("run {}", i); while set.len() >= max_task { set.join_next().await; } set.spawn(async move { sleep().await; println!("spawn {}", i); }); } while set.len() > 0 { set.join_next().await; } }); }咱们应用JoinSet来治理派生进去的工作。set.join_next().await; 保障至多一个工作被执行实现。联合set的len,咱们能够在工作达到下限时阻塞工作派生。当循环完结,可能还有未实现的工作,所以只有set.len()大于0就期待工作完结。 ...

April 14, 2023 · 1 min · jiezi

关于rust:利用springboot初始化机制三种实现策略模式的应用

面试时总被问,spring中应用了哪些设计模式,你在理论开发中又应用哪些设计模式。给他手指一个方向跟他说,这就是一个模式:go out!。这就是一种模式:策略模式,一个接口的多个实现形式(算法)。本文梳理了应用springboot实现的三种实现策略模式的利用咱们晓得,springboot利用初始化的过程是通过事件机制进行的。次要是通过 EventPublishingRunListener 在不同的初始化阶段发送不同的 SpringApplicationEvent (不同的子)事件,触发相应逻辑(这里的逻辑指class的加载)的加载和初始化。当 ApplicationPreparedEvent 事件发送后,对于利用来讲,阐明整个初始化过程已实现,也意味着所有的类已放入spring ioc 中。这时咱们就能够联合本人的业务逻辑实现策略模式的利用,咱们通过以下三种形式实现策略的利用形式一:应用ApplicationListener 和 ContextRefreshedEvent外围应用的是 ApplicationContext.getBeanNamesForAnnotation(Class annotationType)办法,基于注解类,获取标有指定注解类的所有实例咱们的业务逻辑是这样的:利用Api接管规定参数(authType),Api 依据authType 值的不同,应用不同的auth service,执行相应的规定业务逻辑。public interface UserValidator<D, R> { String check(D data, R rule);œ}@Service@Validator(authType = AuthType.B_USER)public class BUserValidator implements UserValidator<String, String> { @Overridepublic String check(String data, String rule) { System.out.println("客官,这里B端用户逻辑"); return "";}}@Service@Validator(authType = AuthType.C_USER)public class CUserValidator implements UserValidator<String, String> { @Overridepublic String check(String data, String rule) { System.out.println("客官,这里C端用户逻辑"); return "";}}public enum AuthType { B_USER(1, "b端用户"),C_USER(2, "c端用户");public final int type;public final String code;AuthType(int type, String code) { this.type = type; this.code = code;}}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Component@Inheritedpublic @interface Validator { ...

April 12, 2023 · 3 min · jiezi

关于rust:未来量化私募的竞争人才之争技术之争

近期,多家百亿量化私募外围投研人员到职的风闻,再次引起大家关注。而近几年量化私募倒退迅速,外部待遇不均加之量化策略在A股市场大热,不少外围投研人员感觉“不如本人干”,或是“择木而栖”。 国内量化私募行业绝对年老,不少量化私募在2017-2019年才创建,随后疾速升级为百亿级私募。在2019-2020年,随着股指走强以及股指期货的松绑,量化私募行业迎来大暴发。依据中信证券研究部估算,目前量化行业规模已冲破1.5万亿元。据私募排排网最新数据显示,目前国内百亿级量化私募机构已超30家,其中少数均是2020年之后“破百”。 目前,国内头部量化私募的管理模式分为两种:1.PM制;2.分工制。其中,PM制是指治理人旗下设置多个投资经理,除了共享基础设施,我的项目之间互不烦扰。然而,分工制是将策略的环节拆分,每个环节装备业余的投研人员。 自2022年以来,量化整体超额收益在衰减,即行业竞争愈发强烈。进入2023年,国内量化私募的倒退进入新阶段,在投研纬度以及治理方面,须要更加系统化和精细化。 有量化机构人士示意,无论公司采纳PM制还是分工制,人才、技术、治理都是将来量化私募行业竞争的关键点。此外,随着量化市场逐步拥挤,采取超额收益越来越难。对于新量化私募而言,募资挑战艰巨;对于曾经在市场中厮杀较长时间的“老机构”而言,想要持续获取超额收益,还须要拼细节,拼策略的创新性、敏锐性,拼发现正当价值的能力,最终还是要落实到人才团队的比拼。 往年春招,各大量化私募踊跃招募人才。有猎头示意,有百亿量化私募开出了最高200万元的年薪,更有私募示意“薪资不设限”,对于人才的竞争十分激烈。 私募排排网财产研究部副总监示意,将来量化私募的竞争是人才之争、技术之争,要留住优良的策略研发人才,治理人不仅要提供有竞争力的薪酬和股权激励,更要“走心”,关注人才的职非业倒退布局,提供顺畅的降职门路,并营造谐和的工作气氛。 在这场人才争夺战中,作为第三方算法服务商的非凸科技也在加快脚步,晋升本身硬实力的同时,也在积攒大量优秀人才。公司致力于建设工程师文化,笃信弱小的技术体系才是继续发明持重回报的根底和要害。现阶段,非凸技术与非技术岗位都在招募,欢送酷爱量化的你们,退出非凸! 【招聘岗位】Rust开发工程师/全栈工程师/量化策略研究员/机构业务经理/财务经理/招聘经理【投递邮箱】recruit@ft.tech【官方网站】ft.tech【工作地点】北京/上海/成都/新加坡【薪酬待遇】Base +奖金; 【公司福利】公司将依照国家规定为你缴纳养老保险、就业保险、根本医疗保险、工伤保险、生养保险及住房公积金;将为你提供带薪休假、年度高端体检、团队建设、下午茶等福利流动;还能够依据理论业务需要申请个性化定制的顶级工作设施,如电脑、显示器等。

April 7, 2023 · 1 min · jiezi

关于rust:倒计时3天-I-48-Beijing-Rust-Meetup

4.8 Beijing Rust Meetup倒计时3天! 对Rust编程语言感兴趣的你筹备好相聚进行一场头脑风暴了吗?赶快预约报名参加本周六下午的线下Meetup。一起和来自达坦科技、南京大学、CloudWeGo、华为等的技术专家来探讨Rust作为一种强调性能、平安和并发性的编程语言的各种利用和实际。咱们的主题是Rust X,意在探讨用Rust编程语言“点亮”的任何利用、实际,和摸索Rust的有限可能性。 工夫:2023年4月8日 14:00 地点:环球财讯核心M层 北京市西城区宣武门外大巷甲 1 号 嘉宾及议题介绍(Guests & Topics)嘉宾:冯洋 南京大学计算机科学与技术系助理研究员 议题:基于理论场景利用剖析的Rust库含糊测试技术报告 摘要:Rust是一种承诺内存平安和并发平安的语言,而各类Rust库中API的破绽与缺点可能会对所有应用该库的程序产生影响。因而,保障Rust库的安全性与可靠性是一个极为重要的问题。为了进一步保障Rust库的平安,通过含糊测试来对Rust的库进行测试是一个可行办法。在本报告中,咱们提出了一种依附现有Rust生态系统来生成含糊测试指标的办法,该办法利用MIR解析待测库所在生态系统中的我的项目,找到事实中API之间的调用和依赖关系,从而从中提取出待测库的API序列,依此生成Rust库的含糊测试指标。 嘉宾:施继成 达坦科技联结创始人兼CTO 议题:在Linux 6.2中用Rust语言写驱动 摘要: Linux 在 6.1 中退出了 rust 语言的反对,自此开发者能够应用 Rust 语言进行 Linux 内核驱动开发。因为 Rust 语言的安全性,将来驱动的开发工作应用 Rust 语言将成为必然趋势。尽管 Rust 语言的反对还有许多不欠缺的中央,但不障碍咱们“吃螃蟹”——应用 Rust 语言写一个 Linux 驱动。本次分享将:1. 介绍 Linux 零碎的 Rust 语言反对。2. 以 Linux 上的简略 Driver 举例,阐明如何用 Rust 写驱动。3. 剖析 Rust 在 Linux 中工作的原理。4. 列举 Rust 进行驱动编写时的限度。5. 给出应用 Rust 编写驱动的 Guideline。 嘉宾:叶天星 华为技术有限公司 议题:用Rust实现Git传输协定、Git对象解析和数据库存储 ...

April 5, 2023 · 1 min · jiezi

关于rust:48-Beijing-Rust-Meetup-Call-For-Presenters

如果你有趣味参加探讨Rust作为一种强调性能、平安和并发性的编程语言的各种利用、实际和有限可能性的头脑风暴,就肯定不能错过这场来自达坦科技、南京大学、CloudWeGo、华为等技术专家带来的对于Rust编程语言相干利用的线下Meetup。咱们的主题是Rust X,意在探讨用Rust编程语言“点亮”的任何利用、实际和摸索。 工夫:2023年4月8日 14:00 地点:环球财讯核心M层 北京市西城区宣武门外大巷甲 1 号 嘉宾演讲(Presenter & Topic)目前曾经锁定的分享嘉宾和演讲主题有: 嘉宾:冯洋 南京大学计算机科学与技术系助理研究员 议题:基于理论场景利用剖析的Rust库含糊测试技术报告 摘要:Rust是一种诺内存平安和并发平安的语言,而各类Rust库中API的破绽与缺点可能会对所有应用该库的程序产生影响。因而,保障Rust库的安全性与可靠性是一个极为重要的问题。为了进一步保障Rust库的平安,通过含糊测试来对Rust的库进行测试是一个可行办法。在本报告中,咱们提出了一种依附现有Rust生态系统来生成含糊测试指标的办法,该办法利用MIR解析待测库所在生态系统中的我的项目,找到事实中API之间的调用和依赖关系,从而从中提取出待测库的API序列,依此生成Rust库的含糊测试指标。 嘉宾:施继成 达坦科技联结创始人兼CTO 议题:在Linux 6.2中用Rust语言写驱动 摘要: Linux 在 6.1 中退出了 rust 语言的反对,自此开发者能够应用 Rust 语言进行 Linux 内核驱动开发。因为 Rust 语言的安全性,将来驱动的开发工作应用 Rust 语言将成为必然趋势。尽管 Rust 语言的反对还有许多不欠缺的中央,但不障碍咱们“吃螃蟹”——应用 Rust 语言写一个 Linux 驱动。 本次分享将: 介绍 Linux 零碎的 Rust 语言反对。以 Linux 上的简略 Driver 举例,阐明如何用 Rust 写驱动。剖析 Rust 在 Linux 中工作的原理。列举 Rust 进行驱动编写时的限度。给出应用 Rust 编写驱动的 Guideline。嘉宾:叶天星 华为技术有限公司 议题:用Rust实现Git传输协定、Git对象解析和数据库存储 摘要:本次分享将蕴含: 应用 Rust 实现 Git 传输协定 - Git 传输协定是一种用于 Git 客户端和服务器之间进行通信的协定,有两种实现形式:HTTP 和 SSH。Git 传输协定能够确保数据传输的安全性和可靠性,并且可能高效地解决大量的数据。通过应用 Rust,能够轻松地实现 Git 客户端和服务器之间的数据传输,并确保高效的网络通信和数据安全性。Git 存储构造介绍 - Git 应用了一种称为对象存储的形式来存储代码版本信息。Git 对象有四种类型:blob、tree、commit 和 tag。 ...

April 1, 2023 · 1 min · jiezi

关于rust:关于rust交叉编译的问题

rust穿插编译依赖我的项目https://github.com/cross-rs/cross 装置$ cargo install cross该我的项目须要依赖docker或者podman 获取镜像的时候因为是间接拉ghcr.io/cross-rs/*的镜像,所以国内配置的镜像是无奈应用的,这个时候须要配置docker的代理服务才行 查看docker服务配置文件地位 $ sudo systemctl status docker● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)根据下面命令输入,批改文件/lib/systemd/system/docker.service配置HTTP代理,代理的参数值须要根据本人代理而调整 [Service]Environment="HTTP_PROXY=http://127.0.0.1:20171"Environment="HTTPS_PROXY=http://127.0.0.1:20171"重启服务 $ sudo systemctl daemon-reload$ sudo systemctl restart docker执行穿插编译应用的时候须要把cargo替换为cross命令 $ cross build -r --target x86_64-pc-windows-gnu执行的时候会主动拉取一个镜像ghcr.io/cross-rs/x86_64-pc-windows-gnu:{version},version参数的值是默认根据cross的版本号定的,比方执行命令如下,发现版本号是0.2.5,则对应的获取镜像是ghcr.io/cross-rs/x86_64-pc-windows-gnu:0.2.5 $ cross --versioncross 0.2.5[cross] note: Falling back to `cargo` on the host.cargo 1.68.0 (115f34552 2023-02-26)编译时候的报错解决该谬误个别会呈现在rust以及第三方库版本十分新,然而cross的版本是比拟久之前公布的 目前cross的版本是0.2.5,对应的tag值也是一样 编译过程当中会呈现如下谬误,示意找不到某个GLIBC版本 error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /target/release/deps/libfutures_macro-7a167e0564403030.so)查看容器根底镜像信息 $ docker run ghcr.io/cross-rs/x86_64-pc-windows-gnu:0.2.5 cat /etc/os-releaseNAME="Ubuntu"VERSION="18.04.6 LTS (Bionic Beaver)"...VERSION_CODENAME=bionicUBUNTU_CODENAME=bionic查看反对的GLIBC版本信息 ...

March 16, 2023 · 1 min · jiezi

关于rust:文盘Rust-安全连接-TiDBMysql

作者:京东科技 贾世闻最近在折腾rust与数据库集成,为了偷懒,选了Tidb Cloud Serverless Tier 作为数据源。Tidb 无疑是近五年来最优良的国产开源分布式数据库,Tidb Cloud Serverless Tier作为pingcap旗下的云产品不便又经济,这次应用还有一些小惊喜,这个后文再说。 Tidb Cloud Serverless Tier 的应用文档还是很全面的,详细情况请参考应用 TiDB Cloud (Serverless Tier) 构建 TiDB 集群. 集群建设实现后,Tidb Cloud Serverless Tier 有个小性能是能够显示支流客户端以及风行编程语言的连贯代码。包含: MysqlCli、MyCli、JDBC、Python、golang以及Nodejs。 嗯?rust 的代码在哪儿?很遗憾没有rust的代码。而且为了平安起见,Tidb Cloud Serverless Tier 貌似只反对平安连贯。在查找文档过程中rust 的 数据库驱动和很多orm文档中也没有对于平安具体的形容,不少思路是在issues外面给出的。索性把rust 连贯 mysql 支流形式的平安连贯代码都记录下来,一来给本人留个备忘,二来给须要的同学做个提醒。 以下实例所应用的的标的建表语句如下 CREATE TABLE IF NOT EXISTS sample ( id BIGINT NOT NULL , name VARCHAR(128) NOT NULL, gender TINYINT NOT NULL, mobile VARCHAR(11) NOT NULL, create_time DATETIME NOT NULL, update_time DATETIME NOT NULL, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;mysql rust driverrust-mysql-simple,纯 rust 实现的 mysql 驱动。 ...

March 15, 2023 · 4 min · jiezi

关于rust:性能的极致Rust的加持ZedDev编辑器快速搭建Python310开发环境

快就一个字,甚至比以快著称于世的Sublime 4编辑器都快,这就是Zed.dev编辑器。其底层由 Rust 编写,比基于Electron技术微软开源的编辑器VSCode快一倍无余,性能上无出其右,同时反对多人编辑代码。 装置和配置Zed.devZed.dev编辑器还在灰度测试阶段,临时只释出了Mac版本,在Zed.dev官网下载,装置胜利后,进入Zed.dev编辑器,应用组合键 Command + , 调出编辑器的配置文件: // Zed settings // // For information on how to configure Zed, see the Zed // documentation: https://zed.dev/docs/configuring-zed // // To see all of Zed's default settings without changing your // custom settings, run the `open default settings` command // from the command palette or from `Zed` application menu. { "theme": "One Dark", }编辑器默认应用暗黑格调的One Dark主题,也能够通过配置theme来抉择别的主题,比方"Rosé Pine Moon: "theme": "Rosé Pine Moon",如图所示: ...

March 14, 2023 · 1 min · jiezi

关于rust:20230313-技术周刊

记录一周所见所闻 关注公踪号 进二开物,更多 JS/TS/CSS/Rust 技术文章和科技资讯...浏览语句扭转是要一点一点来的,走得越慢,到得反而越快。很多扭转甚至是在意识不到的状况下产生的。一开始的扭转,普普通通,看上去就和没变一样。资讯随着前端畛域的一直倒退,前端工具层面对性能的要求越来越高。由此涌现进去了很多的工具 esbuild/turbopack 等基于其余高性能语言的工具,本周字节开源本人的 web 构建工具 Rspack,最大的特点就是基于 Rust, 兼容 webpack 的生态,定制性强等。 2023 年 3 月编程语言榜单 其中值得关注的是 Go 进入了前 10 名。react-native 公布 v0.71.4 版本,更好的反对 Monorepo 等。mongoose 公布了 v7.0.1 版本文章举荐在 Linux 上应用 Tealdeer 代替手册页 Tealder 是 Rust 版本的 tldr,对罕用的命令提供了易于了解的阐明信息。什么时候用:REST、GraphQL、Webhook 和 gRPC分析师都在说硅谷银行是个案,真的如此吗?Node.js 将来发展趋势实用工具taffy 一个高性能的 Rust 布局库。protomaps.js 实用于 Web 的轻量级矢量地图渲染、标注和符号零碎。typewriterjs 一个简略而弱小的原生 JavaScript 插件,用于很酷的打字机成果。flexsearch 下一代实用于 Node.js 和浏览器的全文搜寻库。farm 用 Rust 编写的超疾速 Web 构建工具。inquire 用于构建交互式提醒的 Rust 库。superjson 平安地将 JavaScript 表达式串行化为 JSON 的超集,其中包含 Dates、BigInt 等。tsm TypeScript 模块 Loader。micromorph 一个十分小的 DOM 节点比照库。clap 一个功能齐全、疾速的 Rust 命令行参数解析器。开源与库windmill 开源开发人员平台,用于将脚本转换为工作流和 UI。Airplane and Retool 的开源替代品。remult 在没有样板文档的状况下构建全栈、端到端类型平安的 CRUD 利用。monkeytype 最可定制的打字网站,具备简洁的设计和大量性能。在各种模式下测试本人,跟踪进度并进步速度。ink 交互式命令行应用程序的 React 库。bumpalo 一个基于 Rust 的疾速调配办法。eventsource 用于 Node.js 和浏览器的事件原客户端(polyfill)。rolldown Rust 中的疾速 JavaScript/TypeScript bundler 与 Rollup 兼容 API。click-prompt 用于一键轻松查看、分享和执行您的 Prompt。theia Eclipse Theia 是一个用 TypeScript 实现的云和桌面 IDE 框架。往期举荐# 2023-03-13 技术周刊第 19 期# 2023-02-27 技术周刊第 18 期# 2023-02-20 技术周刊第 17 期更多微信搜寻并关注公踪号 进二开物,更多技术 JS/TS/CSS/Rust 文章... ...

March 12, 2023 · 1 min · jiezi

关于rust:rust使用hashmap存储函数并调用

背景在rust 1.67.1 (d5a82bbd2 2023-02-07) 版本测试失常 应用rust的hashmap存储i32为key, 函数作为value, 当查问某个key如果存在具体的函数则调用 反对异步函数存储与调用 次要办法 如果类型不同,则须要包一层Box,把存储的内容放到堆内存上,保障编译器能够失常计算内存大小,次要是针对存储在栈上的内存大小如果是异步办法,因为异步函数没有申明Unpin,所以须要包一层Pin,应用Box::pin实现,次要是保障异步函数运行的时候不会挪动future同步函数,雷同参数,雷同返回值的实现use std::collections::HashMap;fn first(value: i32) -> i32 { println!("{value} in sync first"); value}fn second(value: i32) -> i32 { println!("{value} in sync second"); value}type HashMapFun = HashMap<i32, Box<dyn Fn(i32) -> i32>>;fn main() { let mut map: HashMapFun= HashMap::new(); map.insert(1, Box::new(first)); map.insert(2, Box::new(second)); for v in 0..4 { map.get(&v).and_then(|f| Some(f(v))); }}同步函数-雷同参数-不同返回值的实现因为返回的值不同,所以每个存储的函数返回值都被蕴含了一层Boxhashmap插入函数的时候编译器冀望的是一个trait object,如果间接传递first或者second会产生报错,能够只有闭包解决use std::collections::HashMap;use std::fmt::Display;fn first(value: i32) -> Box<impl Display> { println!("{value} in sync first"); Box::new(value)}fn second(value: i32) -> Box<String> { println!("{value} in sync second"); Box::new(format!("-----{value}"))}type HashMapFun = HashMap<i32, Box<dyn Fn(i32) -> Box<dyn Display>>>;fn main() { let mut map: HashMapFun = HashMap::new(); map.insert(1, Box::new(|x| first(x))); map.insert(2, Box::new(|x| second(x))); for v in 0..4 { map.get(&v).and_then(|f| Some(f(v))); }}异步函数-雷同参数-雷同返回值的实现use std::collections::HashMap;use std::future::Future;use std::pin::Pin;async fn third(value: i32) -> i32 { println!("{value} in async third"); tokio::time::sleep(std::time::Duration::from_secs(1)).await; value}async fn fourth(value: i32) -> i32 { println!("{value} in async fourth"); tokio::time::sleep(std::time::Duration::from_secs(1)).await; value}type HashMapAsyncFun = HashMap<i32, Box<dyn Fn(i32) -> Pin<Box<dyn Future<Output = i32>>>>>;#[tokio::main]async fn main() { let mut async_map: HashMapAsyncFun = HashMap::new(); async_map.insert(3, Box::new(|x| Box::pin(third(x)))); async_map.insert(4, Box::new(|x| Box::pin(fourth(x)))); for v in 0..5 { if let Some(f) = async_map.get(&v) { f(v).await; } }}参考浏览Rust小技巧 - 把异步函数放进vector当中 ...

March 10, 2023 · 1 min · jiezi

关于rust:轻量易部署Coolbpf-发布不依赖-Clang-的脚本化编程特性-lwcb-龙蜥技术

文/eBPF技术摸索 SIG 基于 CO-RE(Compile Once – Run Everywhe)实现的 Coolbpf 我的项目,新推出轻量级脚本化编程个性 lwcb(Lightweight Coolbpf)。lwcb 是一款面向 eBPF 的脚本语言和 tracing 开发工具,它能够解析用户编写的脚本,生成 eBPF 字节码,从而实现对 Linux 内核零碎的跟踪诊断、性能剖析和监控。此外,lwcb 还提供了大量内置函数,如 tcpstate 能够轻松将整数转换成 tcp 状态字符串,tcphdr、iphdr 能够让用户从 skb 里获取 tcphdr 或 iphdr 构造体,有助于疾速编写内核网络相干的 eBPF 程序。lwcb 也让用户不便地增加更多的内置函数,笼罩更多利用场景。 01 lwcb 个性轻量级、易部署lwcb 应用 rust 开发了一个玲珑的解析器,不依赖于 Clang。它采纳轻量级的编译器,并且为编译器增加了 eBPF 后端,使其不须要依赖于 llvm。lwcb 编译后只有一个大小约为 8MB 的独立二进制程序,部署十分方便快捷。以往部署 BCC 和 bpftrace 等工具,须要在指标执行机器上装置一堆编译和运行库。 脚本化、开发快lwcb 以后反对相似于 bpftrace 的脚本解释执行能力,劣势是不须要编译。同时提供了更多内置函数,不便开发和应用。另外,他人造反对 CO-RE 的能力,在不同内核版本上平安运行。能够说,性能比拟弱小。 lwcb 功能性强次要体现在以下几点: 更多的内置函数:如tcphdr、iphdr、tcpstate 等等。探测点函数参数主动注入性能:lwcb -t 'kprobe:tcp_rcv_established { ih = iphdr(skb); print("sip: %s dip: %s\n", ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr))); }'用户能够间接拜访 tcp_rcv_established 函数的 skb 参数,进而获取 IP 地址和端口号信息。 ...

March 1, 2023 · 2 min · jiezi

关于rust:Rust中一些KV存储引擎

K/V存储引擎的由来能够追溯到20世纪70年代的Berkley DB,而近年来,随着互联网利用的倒退,KV存储引擎因其简略高效、可扩展性和适宜缓存利用等特点,在分布式存储畛域失去了广泛应用。而应用Rust编写KV存储具备内存平安、高性能、并发平安、跨平台反对和Rust沉闷的社区反对等提点,能够进步程序的可靠性、性能和可维护性,尤其适宜用于对数据安全性有严格要求的场景。本周咱们翻译一篇Reddit上无关用Rust语言编写的一些要害值存储引擎的文章,让大家一窥目前比拟热门的KV Store都有哪些~ 本文的作者是Bassfaceapollo,原文公布在Reddit下Rust讨论区。原文链接: https://www.reddit.com/r/rust... 本文中的我,指代作者自己。 注释局部我发现了一些很酷的我的项目想与社区分享。其中一些可能曾经为你们所知了: Engula - 一个分布式K/V存储。它仿佛是这些我的项目中最踊跃工作的了,但如果仅从版本(0.4.0)上看,依然没有为生产工作做好筹备。AgateDB - 一个由PingCAP创立的新的存储引擎,试图取代Tikv DB栈的RocksDB。Marble - 一个新的K/V存储,旨在成为Sled的存储引擎。正如u/mwcAlexKorn在上面的评论中指出的,Sled自身可能仍在开发中。PhotonDB - 一个旨在利用古代多核芯片、存储设备、操作系统和编程语言的弱小性能的高性能存储引擎。目前尽管在Github上的star不多,但依然在踊跃致力着,且看起来很不错。因而我也想分享一下。DustData - Rustbase的一个存储引擎。Rustbase是一个NoSQL K/V数据库。Sanakirja - 由Pijul VCS背地的团队开发,是一个由B-Tree反对的K/V存储。它被Pijul团队应用。与Git不同,Pijul是基于补丁实践的一个新版本的控制系统。Sanakirja的源码仓库在Nest上,并且是目前惟一一个应用Pijul的代码库。 (credit: u/Kerollmops) 另外,Pijul和Sanakirja的作者Pierre-Étienne Meunier(u/pmeunier)也在这个话题中。你能够浏览他的评论以理解更多的观点。Persy - Persy是一个用Rust编写的事务性存储引擎。(credit: u/Kerollmops)ReDB - 一个简略的、可移植的、高性能的、ACID的、嵌入式的K/V存储,其灵感源自于 LMDB。(起源:u/Kerollmops)Xline - 一个用于元数据管理的分布式K/V存储,提供与etcd兼容的API和k8s的兼容性。(credit: u/withywhy)Locutus - 一个分布式的、去中心化的K/V存储,其中的键是决定该键下什么值无效的加密合约。该存储是可察看的,容许建设在Locutus上的应用程序监听值的变动并立刻失去告诉。加密合约是在webassembly中指定的。这种K/V存储是扩散的、可扩大的和不可信赖的中心化服务的代替计划的根底,包含电子邮件、即时通讯和社交网络,其中许多都依赖于关闭的专有协定。(credit: u/sanity)PickleDB-rs - PickleDB(基于 Python 实现) 的一个 Rust 实现版本。结束语不言而喻,很多我的项目(甚至是Rust我的项目)偏向于应用相似于RocksDB的货色来实现K/V。这不禁让我想到了PingCAP的Tikv和Stalwart实验室的JMAP服务器。 话虽如此,我还是喜爱看到用Rust编写这种货色的大胆尝试。讲一点题外话就是,我依然忍不住诧异,除了ToyDB之外,还没有人尝试在Rust中创立一个用于OLTP负载的关系型数据库。 免责申明我自己与这些我的项目中的任何一个都没有关系。我只是在分享他们,因为我发现它们很乏味。 对于咱们达坦科技(DatenLord)推出的开源分布式KV存储Xline,针对多数据中心场景,实现数据的高性能跨云、跨数据中心共享拜访,并保证数据的一致性,不便业务零碎实现多地多核心多活部署。 GitHub链接:Https://github.com/datenlord/Xline 达坦科技(DatenLord)专一下一代云计算——“天空计算”的基础设施技术,致力于拓宽云计算的边界。达坦科技打造的新一代开源跨云存储平台DatenLord,通过软硬件深度交融的形式买通云云壁垒,实现无限度跨云存储、跨云联通,建设海量异地、异构数据的对立存储拜访机制,为云上利用提供高性能平安存储反对。以满足不同行业客户对海量数据跨云、跨数据中心高性能拜访的需要。 公众号:达坦科技DatenLord 知乎账号:https://www.zhihu.com/org/da-... B站:https://space.bilibili.com/20...

February 24, 2023 · 1 min · jiezi

关于rust:文盘Rust-本地库引发的依赖冲突

作者:京东科技 贾世闻问题形容clickhouse 的原生 rust 客户端目前比拟好的有两个clickhouse-rs 和 clickhouse.rs 。clickhouse-rs 是 tcp 连贯;clickhouse.rs 是 http 连贯。两个库在独自应用时没有任何问题,然而,在同一工程同时援用时会报错。 Cargo.toml # clickhouse httpclickhouse = {git = "https://github.com/loyd/clickhouse.rs", features = ["test-util"]}# clickhouse tcpclickhouse-rs = { git = "https://github.com/suharev7/clickhouse-rs", features = ["default"]}报错如下 Blocking waiting for file lock on package cache Updating git repository `https://github.com/suharev7/clickhouse-rs` Updating crates.io indexerror: failed to select a version for `clickhouse-rs-cityhash-sys`. ... required by package `clickhouse-rs v1.0.0-alpha.1 (https://github. com/suharev7/clickhouse-rs#ecf28f46)` ... which satisfies git dependency `clickhouse-rs` of package `conflict v0.1.0 (/Users/jiashiwen/rustproject/conflict)`versions that meet the requirements `^0.1.2` are: 0.1.2the package `clickhouse-rs-cityhash-sys` links to the native library `clickhouse-rs`, but it conflicts with a previous package which links to `clickhouse-rs` as well:package `clickhouse-rs-cityhash-sys v0.1.2` ... which satisfies dependency `clickhouse-rs-cityhash-sys = "^0.1.2"` (locked to 0.1.2) of package `clickhouse v0.11.2 (https://github.com/ loyd/clickhouse.rs#4ba31e65)` ... which satisfies git dependency `clickhouse` (locked to 0.11.2) of package `conflict v0.1.0 (/Users/jiashiwen/rustproject/conflict)`Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='clickhouse-rs-cityhash-sys' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.failed to select a version for `clickhouse-rs-cityhash-sys` which could resolve this conflict谬误形容还是很分明的,clickhouse-rs-cityhash-sys 这个库抵触了。认真看了一下两个库的源码,援用 clickhouse-rs-cityhash-sys 库的形式是不一样的。clickhouse.rs 是在其Cargo.toml 文件中应用最广泛的形式援用的 ...

February 20, 2023 · 2 min · jiezi

关于rust:rust入坑指南之ownership

作者:京东批发 王梦津 I. 前言Rust,不少程序员的白月光,这里咱们简略列举一些大牛的评估。 Linus Torvalds:Linux内核的创始人,对Rust的评估是:“Rust的次要长处是代码的安全性和速度,很难在C++中实现这种安全性,而且Rust编译器会捕捉很多C++难以发现的谬误”。 Brian Kernighan:C语言的创始人之一,对Rust的评估是:“Rust是一门十分弱小的程序语言,在资源管理、内存平安、多线程等方面具备很强的能力”。 Rob Pike:Go语言的创始人之一,对Rust的评估是:“Rust是一门很有前途的语言,它将许多最佳实际和先进技术整合在了一起,是将来零碎编程的重要抉择”。 越来越多大学的课程设计中也将rust作为了一个选项, 比方取得国家精品课程的清华大学的操作系统: http://rcore-os.cn/rCore-Tuto... 如果下面这些让你对rust感兴趣了的话,能够移步官网学习链接:https://doc.rust-lang.org/book/ II. Rust Ownership概述这篇文章咱们介绍一下rust的一个外围概念 ownership Ownership是Rust语言的一个外围概念,它决定了一个值在程序中的生命周期以及对其拜访权限的限度。Rust的Ownership有以下几个特点: Rust有严格的内存安全性:Ownership规定决定了在程序中每一个值的生命周期,因而在Rust程序中不存在内存透露和数据竞争问题。 Rust是一种动态语言:在编译阶段就能够确定程序中每一个值的生命周期,因而程序的性能是十分稳固的。 明确的资源管理:Ownership规定决定了程序中的资源如何被调配,开释和治理,因而程序员不用手动进行内存治理。 总的来说,Rust的Ownership提供了一种通过明确的规定治理内存和资源的形式,从而防止了许多常见的编程谬误,使程序员可能开发出更平安,高效,牢靠的程序。 III. Ownership的代码实际// Rust代码fn main() { let v = vec![1, 2, 3]; let _v2 = v; println!("{:?}", v);}下面的 Rust 代码会产生编译谬误,因为在 Rust 中一个变量只能有一个所有者。在本代码中,当将 v 赋值给变量 v2 时,v 就不再领有它调配的内存,所以 v 不能被应用。相比之下,C++代码是这样的: #include <vector>#include <iostream> int main() { std::vector<int> v = {1, 2, 3}; std::vector<int> v2 = v; std::cout << v[0] << std::endl; return 0;}这段 C++ 代码不会产生任何谬误,即便 v 被赋值给 v2,v 依然能够被应用。这是因为 C++ 应用垃圾回收机制,它在运行时才检测到内存问题,而 Rust 应用编译期所有权管理机制,能够在编译阶段发现内存问题,更平安。 ...

February 15, 2023 · 1 min · jiezi

关于rust:文盘Rust-领域交互模式如何实现

作者:京东科技 贾世闻 文盘Rust -- 畛域交互模式如何实现书接上文,上回说到如何通过interactcli-rs四步实现一个命令行程序。然而shell交互模式在有些场景下用户体验并不是很好。比方咱们要连贯某个服务,比方mysql或者redis这样的服务。如果每次交互都须要输出地址、端口、用户名等信息,交互起来太麻烦。通常的做法是一次性输出和连贯相干的信息或者由对立配置文件进行治理,而后进入畛域交互模式,所有的命令和反馈都和该畛域相干。interactcli-rs 通过 -i 参数实现畛域交互模式。这回咱们摸索一下这一模式是如何实现的。 基本原理interactcli-rs 实现畛域交互模式次要是循环解析输出的每一行,通过rustyline 解析输出的每一行命令,并交由命令解析函数解决响应逻辑 当咱们调用 ‘-i’ 参数的时候 实际上是执行了 interact::run() 函数(interact -> cli -> run())。 pub fn run() { let config = Config::builder() .history_ignore_space(true) .completion_type(CompletionType::List) .output_stream(OutputStreamType::Stdout) .build(); let h = MyHelper { completer: get_command_completer(), highlighter: MatchingBracketHighlighter::new(), hinter: HistoryHinter {}, colored_prompt: "".to_owned(), validator: MatchingBracketValidator::new(), }; let mut rl = Editor::with_config(config); rl.set_helper(Some(h)); if rl.load_history("/tmp/history").is_err() { println!("No previous history."); } loop { let p = format!("{}> ", "interact-rs"); rl.helper_mut().expect("No helper").colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p); let readline = rl.readline(&p); match readline { Ok(line) => { if line.trim_start().is_empty() { continue; } rl.add_history_entry(line.as_str()); match split(line.as_str()).as_mut() { Ok(arg) => { if arg[0] == "exit" { println!("bye!"); break; } arg.insert(0, "clisample".to_string()); run_from(arg.to_vec()) } Err(err) => { println!("{}", err) } } } Err(ReadlineError::Interrupted) => { println!("CTRL-C"); break; } Err(ReadlineError::Eof) => { println!("CTRL-D"); break; } Err(err) => { println!("Error: {:?}", err); break; } } } rl.append_history("/tmp/history") .map_err(|err| error!("{}", err)) .ok();}解析主逻辑交互逻辑次要集中在 ‘loop’ 循环中,每次循环解决一次输出申请。 ...

February 13, 2023 · 2 min · jiezi

关于rust:rust-aes256加密-为什么-加密结果无法输出字符串

[dependencies] aes = "0.8.2"ecb = "0.1.1" use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};type Aes256CbcEnc = ecb::Encryptor<aes::Aes256>;type Aes256CbcDec = ecb::Decryptor<aes::Aes256>;// const KEY: &[u8; 16] = b"abcdedghijklmnop"; // 模仿密钥,请勿在理论程序中应用const key: &[u8; 32] = b"ec3d170007120634a792c6c7b694e336";/// 加密pub fn encrypt(plain: &[u8]) -> Vec<u8> { // 随机值 let mut buf = [0u8; 48]; let pt_len = plain.len(); buf[..pt_len].copy_from_slice(plain); let ct = Aes256CbcEnc::new(key.into()) .encrypt_padded_b2b_mut::<Pkcs7>(plain, &mut buf) .unwrap(); ct.to_vec()}/// 解密pub fn decrypt(cipher: &[u8]) -> Vec<u8> { let cipher_len = cipher.len(); let mut buf = [0u8; 48]; buf[..cipher_len].copy_from_slice(cipher); let pt = Aes256CbcDec::new(key.into()) .decrypt_padded_b2b_mut::<Pkcs7>(cipher, &mut buf) .unwrap(); pt.to_vec()}fn main() { // 账号密码应为单向加密,参考:https://github.com/RustCrypto/password-hashes // 这里的示例代码利用来加密如手机号、身份证号、银行卡号等波及用户隐衷的数据 let plain = b"admin"; let ct = encrypt(plain); let ct2 = ct.clone(); println!("加密后果{:?}", String::from_utf8(ct2));//加密后果Err(FromUtf8Error { bytes: [225, 51, 115, 113, 36, 252, 95, 73, 227, 166, 134, 32, 50, 140, 248, 43], error: Utf8Error { valid_up_to: 0, error_len: Some(1) } }) // let text = "4TNzcST8X0njpoYgMoz4Kw==".as_bytes().to_vec(); let pt = decrypt(&ct); println!("解密后果:{:?}", String::from_utf8(pt));//解密后果:Ok("admin")}

February 9, 2023 · 1 min · jiezi

关于rust:Rust学习内存安全探秘变量的所有权引用与借用

作者:京东批发 周凯 一.前言Rust 语言由 Mozilla 开发,最早公布于 2014 年 9 月,是一种高效、牢靠的通用高级语言。其高效不仅限于开发效率,它的执行效率也是令人称誉的,是一种少有的兼顾开发效率和执行效率的语言。Rust语言具备如下个性: •高性能 - Rust 速度惊人且内存利用率极高。因为没有运行时和垃圾回收,它可能胜任对性能要求特地高的服务,能够在嵌入式设施上运行,还能轻松和其余语言集成。 •可靠性 - Rust 丰盛的类型零碎和所有权模型保障了内存平安和线程平安,让您在编译期就可能打消各种各样的谬误。 •生产力 - Rust 领有杰出的文档、敌对的编译器和清晰的谬误提示信息, 还集成了一流的工具 —— 包管理器和构建工具, 智能地主动补全和类型测验的多编辑器反对, 以及主动格式化代码等等。 Rust最近几年倒退十分迅速,广受一线程序员的欢送,Rust有一个官网保护的模块库(crates.io: Rust Package Registry),能够通过编译器自带的cargo管理工具不便的引入模块,目前crates.io下面的模块数量曾经冲破10万个,仍在快速增长,此情此景好像过来10年node.js的倒退情景再现。 12月11日,Linus Torvalds公布了Linux6.1内核稳定版,并带来一个重磅的新闻,即Linux6.1将蕴含对Rust语言的原生反对。只管这一性能仍在构建中,不过这也意味着,在可见的未来,Linux的历史将打开簇新的一页——除了C之外,开发人员将第一次可能应用另一种语言Rust进行内核开发。 在近几年的探讨中,是否在Linux内核中引入Rust屡次成为议题。不过包含 Torvalds在内的一众关键人物均对此示意了期待。早在2019年,Alex Gaynor和Geoffrey Thomas就曾于Linux Security Summit平安峰会上进行了演讲。他们指出,在Android和Ubuntu中,约有三分之二的内核破绽被调配到CVE中,这些破绽都是来自于内存平安问题。原则上,Rust能够通过其type system和borrow checker所提供的更平安的API来完全避免这类谬误。简言之,Rust比C更平安。谷歌Android团队的Wedson Almeida Filho也曾公开示意:“咱们感觉Rust当初曾经筹备好退出C语言,作为实现内核的实用语言。它能够帮忙咱们缩小特权代码中潜在谬误和安全漏洞的数量,同时很好地与外围内核配合并保留其性能特色。” 以后,谷歌在Android中宽泛应用Rust。在那里,“指标不是将现有的C/C++转换为Rust,而是随着工夫的推移,将新代码的开发转移到内存平安语言”。这一舆论也逐步在实践中失去论证。“随着进入Android的新内存不平安代码的数量缩小,内存安全漏洞的数量也在缩小。从2019年到2022年,相干破绽占比已从Android总破绽的76%降落到35%。2022年,在Android破绽排行中,内存安全漏洞第一次不再是主因。” 本文将探寻相比于其余语言,Rust是怎么实现内存平安的。Rust针对创立于内存堆上的简单数据类型,设计了一套独有的内存管理机制,该套机制蕴含变量的所有权机制、变量的作用域、变量的援用与借用,并专门针对字符串、数组、元组等简单类型设计了slice类型,上面将具体讲述这些机制与规定。 二.变量的所有权Rust 的外围性能(之一)是 所有权(ownership)。尽管该性能很容易解释,但它对语言的其余局部有着粗浅的影响。 所有程序都必须治理其运行时应用计算机内存的形式。一些语言中具备垃圾回收机制,在程序运行时有法则地寻找不再应用的内存;在另一些语言中,程序员必须亲自调配和开释内存。Rust 则抉择了第三种形式:通过所有权系统管理内存,编译器在编译时会依据一系列的规定进行查看。如果违反了任何这些规定,程序都不能编译。在运行时,所有权零碎的任何性能都不会减慢程序。 因为所有权对很多程序员来说都是一个新概念,须要一些工夫来适应。好消息是随着你对 Rust 和所有权零碎的规定越来越有教训,你就越能天然地编写出平安和高效的代码。坚持不懈! 当你了解了所有权,你将有一个松软的根底来了解那些使 Rust 独特的性能。在本章中,咱们将通过实现一些示例来介绍所有权,这些示例基于一个罕用的数据结构:字符串。 栈(Stack)与堆(Heap)在很多语言中,你并不需要常常思考到栈与堆。不过在像 Rust 这样的零碎编程语言中,值是位于栈上还是堆上在更大程度上影响了语言的行为以及为何必须做出这样的抉择。咱们会在本文的稍后局部形容所有权与栈和堆相干的内容,所以这里只是一个用来预热的简要解释。栈和堆都是代码在运行时可供使用的内存,然而它们的构造不同。栈以放入值的顺序存储值并以相同程序取出值。这也被称作 后进先出(last in, first out)。设想一下一叠盘子:当减少更多盘子时,把它们放在盘子堆的顶部,当须要盘子时,也从顶部拿走。不能从两头也不能从底部减少或拿走盘子!减少数据叫做 进栈(pushing onto the stack),而移出数据叫做 出栈(popping off the stack)。栈中的所有数据都必须占用已知且固定的大小。在编译时大小未知或大小可能变动的数据,要改为存储在堆上。 堆是不足组织的:当向堆放入数据时,你要申请肯定大小的空间。内存分配器(memory allocator)在堆的某处找到一块足够大的空位,把它标记为已应用,并返回一个示意该地位地址的 指针(pointer)。这个过程称作 在堆上分配内存(allocating on the heap),有时简称为 “调配”(allocating)。(将数据推入栈中并不被认为是调配)。因为指向放入堆中数据的指针是已知的并且大小是固定的,你能够将该指针存储在栈上,不过当须要理论数据时,必须拜访指针。设想一上来餐馆就座吃饭。当进入时,你阐明有几个人,餐馆员工会找到一个够大的空桌子并领你们过来。如果有人来迟了,他们也能够通过询问来找到你们坐在哪。入栈比在堆上分配内存要快,因为(入栈时)分配器无需为存储新数据去搜寻内存空间;其地位总是在栈顶。相比之下,在堆上分配内存则须要更多的工作,这是因为分配器必须首先找到一块足够存放数据的内存空间,并接着做一些记录为下一次调配做筹备。拜访堆上的数据比拜访栈上的数据慢,因为必须通过指针来拜访。古代处理器在内存中跳转越少就越快(缓存)。持续类比,假如有一个服务员在餐厅里解决多个桌子的点菜。在一个桌子报完所有菜后再挪动到下一个桌子是最有效率的。从桌子 A 听一个菜,接着桌子 B 听一个菜,而后再桌子 A,而后再桌子 B 这样的流程会更加迟缓。出于同样起因,处理器在解决的数据彼此较近的时候(比方在栈上)比拟远的时候(比方可能在堆上)能更好的工作。当你的代码调用一个函数时,传递给函数的值(包含可能指向堆上数据的指针)和函数的局部变量被压入栈中。当函数完结时,这些值被移出栈。跟踪哪局部代码正在应用堆上的哪些数据,最大限度的缩小堆上的反复数据的数量,以及清理堆上不再应用的数据确保不会耗尽空间,这些问题正是所有权零碎要解决的。一旦了解了所有权,你就不须要常常思考栈和堆了,不过明确了所有权的次要目标就是为了治理堆数据,可能帮忙解释为什么所有权要以这种形式工作。2.1.所有权规定首先,让咱们看一下所有权的规定。当咱们通过举例说明时,请谨记这些规定: ...

February 9, 2023 · 11 min · jiezi

关于rust:Rust-初步研究

趋势StackOverflow 颁布了报告 Rust 间断 7 年成为“最受欢迎”的语言。越来越多的公司筹备在新我的项目上使用它来增强平安和性能上的保障: Gooogle、FaceBook、亚马逊等大公司外部都有开始在底层零碎上用 Rust 代替局部C/C++;最新的安卓 13 颁布了 SOAP 底层零碎有 21% 的 Rust 程序,且数据显示极大升高了安全漏洞;Linus 也示意 Rust 将成为 C 以外的另一种零碎编程语言;华为、亚马逊、微软、Mozlia 等已成立 Rust 基金会。这一系列的事件表明,Rust 正在越来越被器重。 从另外一个角度,不同于一些被大公司把持的技术,Rust 是由公益组织 Mozilla 牵头试验的一项开源我的项目,整个过程和细节都是公开通明,且最终有多家公司成立的 Rust 基金会负责管理。 Rust 是一项没有历史包袱、且不被任何一家公司垄断的技术。 源起每种语言的诞生和受欢迎都有其背景,咱们不比拟语言的“好坏”,而是简略看下 Rust 的是怎么产生、想要解决什么问题。 早在几十年前的贝尔实验室诞生的 C 及后续的 C ++ 提供了十分风行的高级语言,C 简直是为 unix 零碎而生,是最高用高级语言编写操作系统的尝试之一。它提供了简洁敌对的下层体现能力,同时又能灵便的拜访底层。C ++ 实践上能够了解为 C 的一个超集(理论不齐全兼容),在 C 的根底上提供面向对象等各种解决简单畛域的形象和工具。C/C++ 在诞生到现在,始终是底层零碎开发的支流,操作系统、浏览器,嵌入式设施等这些须要拜访底层硬件,或者须要高性能的畛域简直都在应用 C/C++。 C/C++ 绝对汇编而言,是一种更高的形象,但须要额定做很多底层的事件,比方管制指针操作堆内存,手动开释内存等。对于大量下层应用软件而言,咱们心愿开发者能够更加聚焦到业务自身,而不是底层细节。于是有了大量进一步形象的高级语言,比方适宜浏览器的 Javascript ,适宜后盾业务逻辑解决的 Java、C# , 风行于科学计算的 python 等。这些语言屏蔽了更多底层细节,做了更多适宜于特定场景的设计,比方面向对象,弱化类型、函数式、垃圾回收等。这些形象水平更高的语言,大部分都是解释型语言,须要自带解释器或者虚拟机。解释执行带来的益处是跨平台,能够主动进行垃圾回收,代价是执行性能受到限制。 为了持续在语言层面兼具性能和不便开发者,持续优化方向有两种。其一是把程序编译成二进制文件,但同时依然提供主动垃圾回收和各种高级形象的语法,在性能和内存治理上进行均衡,代表则是 Google 公布的 Go ;另一种是编译成二进制文件,在不提供运行时的主动垃圾回收的状况,依然能主动治理内存。 在 C/C++ 中,开发者须要手工治理内存,通常非常容易带来潜在的平安问题,还有各种开发的心智累赘。Go 采取了折中,在编译的二进制文件程序中,提供运行时垃圾回收。为什么说是折中呢?因为内存没有被开发者手动开释,须要垃圾回收逻辑定期的寻找这些被援用的变量,而后再集中清理掉。在清理垃圾的过程,程序是处于短暂暂停状态。对于大部分份场景,这种毫秒级暂停简直能够忽略不计,所以 Google 大部分后盾业务由 Go 进行实现的。但对于更底层的操作系统、浏览器、FPS 游戏、性能工具等对停滞十分敏感的场景,垃圾回收依然被视为一种累赘。怎么样能力既满足编译到二进制的高性能,又不想减少开发治理内存带来的心智累赘, ...

January 17, 2023 · 3 min · jiezi

关于rust:如何使用-rust-写内核模块

近年来,Rust 语言以内存平安、高可靠性、零形象等能力取得大量开发者关注,而这些个性恰好是内核编程中所须要的,所以咱们看下如何用rust来写Linux内核模块。 Rust 与内核模块尽管 Rust 反对曾经在 LinuxKernel6.1 版本合并到主线了,所以实践上来说,开发者能够应用 Rust 来为 Linux6.1 写内核模块。 但理论开发工作中,内核版本不是最新的,比方 Debian 11 的内核就是 5.10 版本的,那么在这种状况下,该如何用 Rust 写内核模块呢? 原理Rust 如何向内核注册回调、如何调用内核代码。Rust 和 C 的互操作性Rust 如何编译到指标平台上。Rust 的 target 配置Rust 如何申明内核模块入口、并增加非凡 section。Rust 内核模块的二进制约定Rust 和 C 的互操作性第一个问题基本上就是 C 和 Rust 的互操作性了。 得益于 Rust 的抽象层次,C 语言和 Rust 的相互调用都是比拟容易的。rust 官网也提供了 bindgen 这样,依据 .h 文件生成 .rs 文件的库。 这样一来,貌似间接应用 bindgen 将内核头文件翻译成 .rs 就能够了? 但还有一个问题,如何获取内核头文件门路呢? 能够应用一个 dummy 内核模块,在编译过程中把编译参数导出来,其中蕴含了头文件门路,编译参数等,用于 bindgen 生成代码。 Rust 和 target 配置内核模块和一般的程序相比,次要的不同在于: 内核模块是 freestanding 的,没有 libc、内存调配也比拟原始内核模块对于异样解决等有非凡约定Rust 提供了 no_std 机制,能够让 rust 代码编译成 freestanding 二进制;Rust 也提供了自定义 target 的形式,能够自定义申明生成二进制的标准。 ...

January 17, 2023 · 2 min · jiezi

关于rust:SpringBoot整合达梦数据库

装置结束后关上DM数据库配置助手创立数据库,设置字符集utf8,去除字符大小写敏感 创立表空间及用户,最好是一个库对应一个用户一个表空间,创立用户时须要指定对应表空间 须要对用户调配DBA操作权限 数据表迁徙针对现有我的项目或框架库须要同步迁徙达到梦数据库,本文以mysql5.7为例,关上DM数据迁徙工具,留神放弃对象名大小写,抉择表时全副取出再全选,迁徙的表名和字段名就与原数据库保持一致 maven援用 <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <version>8.1.1.193</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.0</version> </dependency> 复制代码数据库配置应用druid治理连接池,去除wall的配置否则会报错spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: dm.jdbc.driver.DmDriver url: jdbc:dm://localhost:5236/ROOT?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8 username: ROOT password: abcd@1234filters: stat,slf4j复制代码兼容代码映射成LinkHashMap数据会在达梦的数据库驱动中强制大写,这对某些接口的数据返回给前端数据大小写呈现问题,影响范畴较大 JdbcTemplate解决咱们能够通过混合应用jdbcTemplate进行查问的通用操作,调用query办法,传入自定义的ResultSetExtractor,失去jdbc原生的ResultSet对象,取出ResultSetMetaData转换成DmdbResultSetMetaData,其中的columns对象为公有对象且无办法拜访,通过反射取出即可,通过columns获取到数据库理论的列名 public List<LinkedHashMap<String, Object>> findListByParam(String sqlText, Map<String, Object> map) { List<LinkedHashMap<String, Object>> result = new ArrayList<>(); List<Object> paramList = new ArrayList<>(); //解析sqlText中的占位符#{xxxx} String regex = "\\#\\{(?<RegxName>[\\w.]*)\\}"; String sqlTextCopy = sqlText; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(sqlTextCopy); while (matcher.find()) { String paramNameSymbol = matcher.group(0); sqlText = sqlText.replace(paramNameSymbol, " ? "); } logger.debug("【sqlText】:" + sqlText); //参数赋值 matcher = pattern.matcher(sqlTextCopy); while (matcher.find()) { String paramNameSymbol = matcher.group(0); String paramName = paramNameSymbol.replace("#", "").replace("{", "").replace("}", ""); Object paramValue = map.get(paramName); logger.debug("【paramName】:" + paramName); logger.debug("【paramValue】:" + paramValue); paramList.add(paramValue); } jdbcTemplate.query(sqlText, paramList.toArray(), new ResultSetExtractor<Object>() { @Override public Object extractData(ResultSet rs) throws SQLException, DataAccessException { try { ResultSetMetaData rsMetaData = rs.getMetaData(); Column[] dm_columns = null; if (dataBaseInfoUtil.getUsingDataBaseType() == GlobalEnum.DataBaseType.DM) { ResultSetMetaDataProxyImpl resultSetMetaDataProxy = (ResultSetMetaDataProxyImpl) rsMetaData; DmdbResultSetMetaData dmdbResultSetMetaData = (DmdbResultSetMetaData) resultSetMetaDataProxy.getRawObject(); Class dataClass = DmdbResultSetMetaData.class; Field field = dataClass.getDeclaredField("columns"); field.setAccessible(true); dm_columns = (Column[]) field.get(dmdbResultSetMetaData); } while (rs.next()) { LinkedHashMap<String, Object> resultitem = new LinkedHashMap<>(); for (int i = 1; i <= rsMetaData.getColumnCount(); i++) { String columnName = ""; if (dataBaseInfoUtil.getUsingDataBaseType() == GlobalEnum.DataBaseType.DM) { columnName = dm_columns[i - 1].name; } else { columnName = rsMetaData.getColumnName(i); ; } Object columnValue = rs.getObject(columnName); resultitem.put(columnName, columnValue); } result.add(resultitem); } } catch (Exception e) { e.printStackTrace(); } finally { return null; } } }); return result;}复制代码与mybaits对立数据源在应用事务时,因为查问操作通过jdbcTemplate,更新操作通过myabtis,在某些隔离级别下会查问不到未提交的数据,所以须要对立数据源都为druid治理的datasource,这里的dynamicDataSource为我自定义的数据源解决对象,继承自spring的AbstractRoutingDataSource,为了解决多数据源状况 ...

January 5, 2023 · 2 min · jiezi

关于rust:字节跳动在-Rust-微服务方向的探索和实践

近日, Qcon寰球软件开发大会2022(上海站)圆满闭幕,大会是由InfoQ 中国主办的综合性技术盛会,近百位国内外技术大咖现场分享前沿技术案例与翻新实际。本文整顿自字节跳动火山引擎基础架构服务框架工程师吴迪于大会上的分享内容,主题为《字节跳动在 Rust 微服务方向的摸索和实际》。 本次分享内容次要分为以下三个局部: 咱们为什么抉择了 Rust 语言;咱们做了什么;展望未来:时机与挑战。嘉宾介绍 我会为大家次要介绍一下咱们为什么会抉择 Rust 语言,因为大家可能据说字节跳动比拟有名的框架叫做 Kitex,是一个 Go 的框架,字节跳动在 Go 方向投入了很多,为何当初开始摸索 Rust 方向呢?其次,在这个方向咱们做了哪些事件,遇到的一些问题,以及咱们的解决方案。其三,会为大家分享一下咱们所认为目前 Rust 的时机以及将来挑战。 咱们为什么抉择了 Rust 语言一开始,我是做 Go 的语言开发,做 Go 的 RPC 框架,但过后咱们遇到了很多 Go 语言的一些问题。 Go 语言的枷锁深度优化艰难在 Go 外面,你想要深度优化是十分十分艰难的一件事件,因为当咱们体量变得越来越大的时候,深度优化是越来越重要了。然而如果在 Go 外面,想要去做一些深度优化,你常常会发现在跟 runtime 以及编译器做很多奋斗,须要用一些很 hack 的方法去绕过它的一些限度。 工具链和包治理不够成熟Go 外面的工具链和包治理相对来说不太成熟,如果有用过咱们开源的 Kitex 框架的同学可能会十分理解。举个例子,比方在 Go 外面,想调一个 gRPC 的服务,或调一个 Thrift 的服务,须要调一个须要生成代码的服务,我须要先在开发的时候把代码生成好,要用一个命令行工具生成完之后,把生成代码一并地给提交到版本治理外面。直白来说,这是个很蠢的做法,像 C++、Java,还有 Python 兴许都会采纳一些其余的计划,然而 Go 就必须这么操作,因为它编译器就没有这个能力,没有方法在编译时去生成这个货色。还有一点,比方我在编译时兴许能够调个脚本去生成,但问题在于本地没有这个文件,代码生成、代码补全提醒都没有, IDE 会间接给你外面所有的就下划线飘红,这是个体验很差的事件。 形象能力较弱Go 外面的形象能力是比拟弱的,它没有零老本形象这么个概念。 深度优化艰难我分享一个之前遇到的实在、有意思的案例。咱们做序列化、反序列化的过程当中,可能会遇到一些出错的状况。在咱们之前的版本外面,代码是很简略的,在序列化、反序列化出错的时候,就间接把 error 返回来。起初咱们为了优化用户的体验,想多返回一些错误信息,比方咱们通知他是在哪个 struct 外面,在 read 哪一个字段的时候出的错。这是一个很好的初衷,然而当咱们新的代码上线了之后,有一个业务方就跑来说:“你这个新的代码是不是有问题?为什么咱们的性能降落了20%?”咱们认为不可能,咱们所有序列化、反序列化逻辑都没有改,只改了这一行。过后咱们也很纳闷,认为是不是业务方本人测试环境有问题,起初咱们查了半天,最初终于发现了状况。 ...

December 27, 2022 · 4 min · jiezi

关于rust:Rust-语言的全链路追踪库-tracing

Rust 语言的全链路追踪库 tracing在一个应用程序或库的开发过程中,除了其自身的逻辑以外,开发人员还须要做很多额定的工作,以保障编写的代码能够正确的运行,或者在出错时能够疾速定位到谬误的地位以及起因,这就须要引入一些额定的工具,trace 就是其中特地好用的一种,下文我将会简略介绍 trace,并以 Rust 为例,演示 trace 在 Rust 中的应用办法。 可观测性Logs、Metrics 和 Traces 并称为可观测性三大支柱,通过剖析它们输入的数据,开发人员可能更好的观测到零碎的运行状况,更快的定位问题,从而进步零碎的可靠性。 日志(Logs)日志作为最罕用的可观测性数据源之一,置信少数开发者都比拟相熟。其本质上就是一种带有工夫戳的离散事件记录,通常用于记录零碎的运行状态,日志的应用非常简略,只须要在代码中须要报告信息的点增加一行代码,就能够将这些信息输入到控制台或文件中,然而日志也有很大的毛病,它的输入是离散的,这意味着在记录的时候,无奈将日志信息互相关联,也无奈晓得日志信息的上下文,尤其是在多线程的环境下,最终输入的信息比拟凌乱,不便于检索和剖析。 指标(Metrics)指标是一种定量掂量,例如平均值、比率和百分比等。其值始终为数字而非文本,能够通过数学方法统计和剖析,其次要用于形容零碎运行状态的数据,比方 CPU 的使用率、内存的使用率、磁盘的使用率等,这些数据能够用来监控零碎的运行状态,也能够用来预警。 追踪(Traces)追踪是一种用于记录零碎中一次申请的残缺生命周期的数据,它能够记录下一个申请从开始到完结的所有信息,包含申请的发起者、接收者、申请的门路、申请的状态、申请的耗时、申请的错误信息等,这些信息能够用来剖析零碎的性能瓶颈,也能够用来剖析零碎的谬误。追踪实质上也是一种日志,他与日志的数据结构十分相似,然而它可能提供比日志更丰盛的信息。特地是在分布式系统中,追踪可能逾越多个服务,汇总出一次申请的残缺信息,让开发人员可能更不便的找到零碎中的问题。 Rust 中的 TraceRust 社区中比拟有名的 trace 实现有三个: tracing 由 tokio 团队保护,目前应用最宽泛,生态也比较完善rustracing 应用人数绝对较少minitrace tikv 团队打造,性能最好接下来就以 tracing 为例,介绍一下 trace 的外围概念以及应用办法: SpanSpan 能够说是 trace 中最要害的概念之一,它示意的是一个过程,也就是一段时间内产生的所有事件的汇合,其数据结构中蕴含着 Span 的开始工夫和完结工夫,在剖析数据是能够借助工具直观的看到某次申请或操作的耗时状况。在同一个 trace 流程中的所有 span 都共享这雷同的 Trace Id ,每个 Span 也有着本人的 Span Id,并且 Span 还反对嵌套,嵌套的 Span 中也会保留着相应的父子关系,最终能够靠这些信息,将申请的残缺生命周期串联起来,并且不会与雷同时间段内的其余申请产生烦扰。 use tracing::{span, Level};fn main() { let span = span!(Level::INFO, "span"); let _enter = span.enter(); // enter 后进入该 span 的上下文 // 能够记录信息到 span 中} // 来到作用域后,_enter 被 drop,对应的 span 在此完结以上代码是创立并应用一个 Span 最简略的形式,除此以外还有几种不同的形式 ...

December 23, 2022 · 3 min · jiezi

关于rust:初学-Rust-有感而发-20221221

前言最近,宇润忽然想学下很炽热的 Rust 语言,毕竟连驰名大喷子 linus 都接收了 Rust,必定有它的可取之处。 通过这篇文章来分享一下,我学习 Rust 语言的教训心得,如有说得不对请轻喷。 Rust 语言官网:https://www.rust-lang.org/zh-CN 居然有官网中文,褒扬!装置首先要来装置 Rust,我是打算在 wsl 里开发,所以装置了 Linux 版本。(当然 Windows 甚至有安装包,也是很不便) Rust 装置:https://www.rust-lang.org/zh-... 一句话装置:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 跟我设想中的齐全不一样,不必梯子也能够很快下载好,装置也不必很繁琐的步骤,让我不敢相信曾经装完了。 编辑器我是 VSCode 的忠诚用户,写 PHP、H5、C、C++ 都是用 VScode 写的,这次学 Rust 也不例外。 搜了一下 “Rust” 关键词,遇事不决,抉择下载量最多的:rust-analyzer 如何学习良久没有学过新的语言了,反正每次刚入门的时候都是最头大的。 我抉择间接看官网文档,通过一些例子来理解语言的根本个性和写法等等。 学习 Rust:https://www.rust-lang.org/zh-... 练手我的项目接下来就是找个小我的项目练练手,死记硬背,争取胜利入门。 当初新生代的语言出厂自带包管理器曾经成为了标配,Rust 的包管理器叫作 Cargo。 我先创立一个我的项目目录,而后在外面执行:cargo init 这样一个我的项目骨架就生成好了。 接下来就是将后面学习根本个性阶段的常识拿过去搭积木了,当然两头遇到了很多问题,通过查文档、百度、Google、一直调试最终都顺利解决。 cargo 拉依赖如果慢的话,须要在 ~/.cargo/config.toml 中配置国内镜像源: [source.crates-io]replace-with = 'ustc'[source.ustc]registry = "https://mirrors.ustc.edu.cn/crates.io-index"通过我的致力,终于实现了一个繁难 Webhook 服务,反对 Gitee 和 Github。 rust-webhook:https://github.com/Yurunsoft/... ...

December 21, 2022 · 2 min · jiezi

关于rust:GaiaX开源解读-给StretchRust编写的Flexbox布局引擎新增特性我掉了好多头发

GaiaX(盖亚),是在阿里娱乐内宽泛应用的Native动态化计划,其外围劣势是性能、稳固和易用。本系列文章《GaiaX开源解读》,带大家看看过来三年GaiaX的倒退过程。GaiaX的布局计划 - Flexbox阿里娱乐业务作为一个内容散发、生产综合体,不仅笼罩Phone端,在Pad、OTT、Mac、车机、IOT带屏设施上都为宽广用户提供在线视频媒体服务。GaiaX作为娱乐散发场景的一个重要端渲染解决方案,在进行布局技术方案设计时,必须充分考虑多端、多屏的响应式布局诉求。家喻户晓,浏览器场景很好的解决了屏幕窗口多尺寸的动静布局问题,其采纳的布局计划即为Flexbox。 挪动端原生Frame布局是Native计划的最优解,因为双端可最大限度的施展OS的渲染个性来保障渲染性能。为了验证Flexbox的实测性能,咱们针对单层及多层嵌套设计了测试用例,通过数据体现(耗时单位为ms)来进一步证实Flexbox计划是否能够作为GaiaX的布局计划。 试验后果的产出,齐全打消了咱们对Flexbox在性能上的顾虑,再加之其合乎W3C标准、社区丰盛、学习复杂度低等劣势,最终团队抉择Flexbox作为GaiaX的布局技术计划。 Flexbox高性能解析计划 - Stretch为什么抉择Stretch作为布局根底在确定了布局计划后,接下来要做的事就是确定解析的技术选型。 社区反对Flexbox布局解析的技术计划,最为大家耳熟能详的是facebook推出的yoga,这也是业内的支流技术选型。绝对于yoga来说,Strectch具备以下的劣势: ● 包大小体积 ● 反对多线程的部分计算 ● 反对跨平台的能力(iOS、Andriod、JS等) ● 基于rust语言实现,具备高性能,低内存占用等个性Stretch的这些的劣势是基于Rust语言个性所带来的:更平安的内存治理:与 C/C++ 语言相比,应用 Rust 语言来进行程序设计能够有助于从源头预防呈现诸如空指针,缓存溢出和内存透露的内存问题。更好的运行性能:与 Java/C# 等语言相比,Rust 语言的内存治理不是依附垃圾回收器机制( GC )来实现的。这个设计进步了程序运行的性能。原生反对多线程开发:Rust 语言的所有权机制和内存平安的个性为没有数据竞争的并发提供了语言层面上的原生反对。 网上曾经有了很多对于Rust性能剖析比照的文章,以下就是性能比照后果,性能上能够跟C++性能并驾齐驱,某些场景下效率甚至优于C++。 Rust vs C++: Stretch入门因为Stretch是采纳Flexbox布局的形式,在开始介绍Stretch外围布局计算逻辑之前,还须要简略理解一下Flexbox的根底概念 ● 采纳 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素主动成为容器成员,称为 Flex 我的项目(flex item)。 ● 容器默认存在两根轴: ○ 程度的主轴(main axis):主轴的开始地位(与边框的交叉点)叫做main start,完结地位叫做main end; ○ 垂直的穿插轴(cross axis):穿插轴的开始地位叫做cross start,完结地位叫做cross end。 ● 我的项目默认沿主轴排列。单个我的项目占据的主轴空间叫做main size,占据的穿插轴空间叫做cross size。 Flexbox解析布局逻辑流程,实际上就是解决Flex容器和Flex我的项目的尺寸、排列方向、对齐形式、比例关系、相对布局我的项目的代码逻辑。 Stretch实现原理Flexbox布局解析主链路 外围算法 Stretch重点分析在Stretch整个布局算法中,有9个次要的环节,接下来咱们重点介绍三个重要的环节, ● 确定Flex我的项目的基准值(flex_basis) ● Flex我的项目的主轴尺寸 ...

December 16, 2022 · 4 min · jiezi

关于rust:文盘Rust-给程序加个日志

作者:贾世闻 日志是应用程序的重要组成部分。无论是服务端程序还是客户端程序都须要日志做为谬误输入或者业务记录。在这篇文章中,咱们联合[log4rs](https://github.com/estk/log4rs)聊聊rust 程序中如何应用日志。 [log4rs](https://github.com/estk/log4rs)相似java生态中的log4j,应用形式也很类似 log4rs中的基本概念 log4rs 的性能组件也由 appender 和 logger形成。 ·appender   负责向指定文件或控制台追加日志  ·logger   蕴含多个 appender ,比方一条日志既要输入到控制台也要长久化到日志文件中,就能够在logger中同时绑定 ConsoleAppender 和 FileAppender  log4rs 应用示例 ·示例形容   咱们须要在工程中记录系统日志和业务日志,别离记录在logs/sys.log 和 logs/business.log ·定义 appender 和 logger 并初始化   代码地位 src/logger/logger.rs    let sys_file = FileAppender::builder()       .encoder(Box::new(PatternEncoder::new("{d} - {m}{n}")))       .build("logs/sys.log")       .unwrap();   let business_file = FileAppender::builder()       .encoder(Box::new(PatternEncoder::new("{d} - {m}{n}")))       .build("logs/business.log")       .unwrap();   let stdout = ConsoleAppender::builder().build();   let config = Config::builder()       .appender(Appender::builder().build("stdout", Box::new(stdout)))       .appender(Appender::builder().build("sys", Box::new(sys_file)))       .appender(Appender::builder().build("business", Box::new(business_file)))       .logger(           Logger::builder()               .appender("sys")               .build("syslog", LevelFilter::Info),       )       .logger(           Logger::builder()               .appender("business")               .build("businesslog", LevelFilter::Info),       )       .build(           Root::builder()               .appender("stdout")               .appender("file_out")               .build(LevelFilter::Info),       )       .unwrap();   let _ = log4rs::init_config(config).unwrap();代码中定义了 sys\_file 和 business\_file 两个FileAppender 别离用于像sys.log 和 business.log中追加日志。 config 中定义了两个logger 别离绑定 sys appender 和 business appender。 最初通过 init_config 初始化 log4rs。  ·在程序中输入日志    · 定义 uselog 命令及两个子命令,别离输出sys 日志和 business 日志。       代码地位 src/cmd/cmdusedifflogger.rs ...

November 25, 2022 · 1 min · jiezi

关于rust:Rust-China-Hackathon-2022-达坦科技组空中宣讲会来啦

Rust China Hackathon 2022 行将来袭! 本届Hackathon的主题为「Rust For Fun」,分为「社区组」与「企业组」。达坦科技作为本届Hackathon的协办方,资助参加本次企业组赛道,将基于Xline这个开源我的项目,就Concurrent Indexing,邀请你一起冲破固有的思维限度。 赛事日程表本次挑战赛于11月15日凋谢报名。赛事日程表曾经新鲜出炉:报名+组队:11.15~12.12组委会整顿报名材料:12.12-12.14开发:12.15~12.18作品提交:12.19作品初评:12.20~12.25 (评委会 + 社区投票)大赛线上路演:12.29(线上直播 :14:00 ~ 18:00)+ 观众投票 + 社区媒体作品颁奖:12.30 地面宣讲会通过近两周的预热,收到不少开发者的的踊跃报名,同时,咱们也收到大量对于较量赛制、赛题解读的征询和发问。为了更全面地向大家推介Rust China Hackathon 2022达坦科技组的较量,咱们特安顿此次地面宣讲会,向无意参赛的工程师解读赛制、介绍日程安排,分享比赛平台的相干资源,以帮忙工程师们顺利完赛。直播工夫:2022年12月4日下午16:00 达坦科技DatenLord赛题主题:Concurrent Indexing背景:Xline是达坦科技推出的分布式元数据KV存储器。在应用中,此零碎须要解决来自客户端的高并发申请,数目有时甚至能够扩大到数百至数千个。为了在内存中定位到相应KV数据,咱们保护了一个索引,而此索引也成为了整个零碎的瓶颈之一。在这样的状况下,如何进步索引在解决并发申请时的性能就成为了一个问题。挑战:在本次Hackathon中,你将须要通过创立这样一个并发索引来解决此问题,此索引应该满足以下要求:1、客户端将并发地发送申请,但并不会发送抵触的申请。2、无抵触的申请该当被并发执行,以进步生产量。 /// Operations of Indexpub(crate) trait IndexOperate<K: Ord, V> { /// Get a range of keys in [key, range_end] fn get(&self, key: &K, range_end: &K) -> Vec<&V>; /// delete a range of keys in [key, range_end] fn delete(&self, key: &K, range_end: &K) -> Vec<V>; /// insert of update a key fn insert_or_update(&self, key: K, value: V) -> Option<V>;}评估规范你的实现应听从上述 Trait 并满足上述要求。咱们将应用肯定基准测试来进行评估,并依据其后果评分。在基准测试中,咱们将发送大量并发申请,因而你也能够创立本人的性能测试来帮忙进行优化。 ...

November 25, 2022 · 1 min · jiezi

关于rust:Rust-You-Dont-Know

Rust语言作为一种强调性能、平安和并发性的新的编程语言,正日益受到程序员们的关注。Rust语言曾经间断7年蝉联 StackOverflow网站(寰球最大的编程问答网站)最受欢语言。甚至Linus Torvalds认为Rust行将成为Linux的官网第二语言。有理由置信越来越多的程序员将退出尝试学习Rust。但Rust语言的学习曲线比拟平缓,门槛不低。因而,达坦科技的联结创始人兼CTO施继成将本人学习和使用Rust语言的心得体会集结成书,咱们也将在达坦科技(DatenLord)公众号陆续连载。 这些思维的火花将不同于市面上其余对于学习Rust编程语言的教科书,它更多地将向程序员分享学习Rust语言的根本要义,以及在理论应用场景下如何使用Rust解决问题的思考,从而让Rust真正变成一种活生生的、有呼吸的、有用的语言。 本文是Rust You Don’t Know的第一章。 Chapter One: Process, Thread, and CoroutineBefore we start discussing the asynchronization of Rust, we'd better firstly talk about how the operating system organizes and schedules the tasks, which will help us understand the motivation of the language-level asynchronization mechanisms. Process and threadPeople always want to run multiple tasks simultaneously on the OS even though there's only one CPU core because one task usually can't occupy the whole CPU core at most times. Following the idea, we have to answer two questions to get the final design, how to abstract the task and how to schedule the tasks on the hardware CPU core. ...

November 18, 2022 · 6 min · jiezi

关于rust:asyncrdma使高性能网络应用开发更简单

王恒宇,中科院软件所根底软件实验室研究生。次要钻研方向为软硬件交融,对物联网、操作系统、Serverless等方向感兴趣。DatenLord社区async-rdma我的项目贡献者之一,曾获嵌入式芯片与零碎设计比赛一等奖等多项国家级奖项,参加编写《openEuler操作系统》一书。 async-rdma是由DatenLord社区发动的Rust异步RDMA编程库,致力于晋升高性能网络应用的开发效率。在介绍async-rdma之前咱们先来理解一下RDMA的概念及其应用形式。 RDMA简介RDMA(Remote Direct Memory Access)直译为近程间接内存拜访,是一种将一台主机内存中的内容间接传输到另一台主机内存中的技术。计算机中罕用的DMA技术防止了CPU忙于将数据从I/O设施拷贝到内存,RDMA则将这一能力拓展到了通过网络连接的多台主机之间。 RDMA在初始化阶段实现后能够由用户态程序通过用户态驱动间接操作RDMA网卡收发数据,无需陷入内核,防止了上下文切换,也无需CPU进行内存拷贝。凭借绕过内核(kernel bypass)和零拷贝(zero copy)等个性,RDMA能以极低的CPU占用率实现高吞吐、低时延网络通信。这里简要介绍下文中用到的RDMA的外围概念,若想进一步理解RDMA的细节能够关注知乎的系列博客,或更进一步翻阅RDMA协定标准理解细节。 MR(Memory Region):RDMA应用程序向操作系统申请和注册的一片内存,用于后续RDMA操作。MR不光有地址和长度,还蕴含其余RDMA特有的元数据,如权限位,除本地读写权限还有远端读写权限等。两种操作类型:1、单端操作(SEND & RECV) 发送、接收数据,一端Send前须要对端先Receive对端CPU须要感知每次收发操作用于替换元数据等小数据量操作2、双端操作(READ & WRITE) 间接对指标主机内存进行读写,申请发送前后对端无需进行操作对端CPU不感知单端操作,读写实现后网卡主动响应RDMA的次要劣势所在,实用于大数据量传输现有RDMA开发方法咱们应用Socket API编写基于TCP/IP的网络应用,基于RDMA的网络应用开发则应用由C语言编写的Verbs API。Verbs API提供了对立的编程接口,屏蔽了RDMA底层协定简单多样的实现,保障了应用程序的通用性。以下是两个Verbs API实例,暂且不关注其各个参数的具体含意,只察看其类型就能够发现其中隐含的内存平安问题。咱们无奈确定裸指针所指数据是否无效,在开发过程中很容易遇到空指针、野指针、内存泄露和屡次开释等常见内存平安问题。 // 注册MR,应用前需先申请内存struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr, size_t length, enum ibv_access_flags access)// 数据申请发送接口int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr, struct ibv_send_wr **bad_wr)Rust提供了以上内存平安问题的高效解决方案,从语言层面帮忙咱们防止了上述问题。DatenLord社区提供了Verbs API的Rust封装库:rdma-sys。 为什么要做async-rdma?然而,Verbs API低层级形象导致的开发效率低的问题是单纯应用Rust封装所无奈解决的。这就是为什么有了rdma-sys库后还要再做一个async-rdma。具体来说,就ibv_post_send()接口而言,参数所用到的数据结构是非常复杂的,间接操作这些参数须要对RDMA有很深刻的理解,这会给开发者带来很大认知累赘,并且应用时极易出错。以下是Verbs简单数据结构的一个例子供大家领会,其成员变量还蕴含其余让人头大的数据结构。 // Verbs简单数据结构示意,无需关注细节struct ibv_send_wr { uint64_t wr_id; struct ibv_send_wr *next; struct ibv_sge *sg_list; int num_sge; enum ibv_wr_opcode opcode; enum ibv_send_flags send_flags; uint32_t imm_data;/* network byte order */ union { struct { uint64_t remote_addr; uint32_t rkey; } rdma; struct { uint64_t remote_addr; uint64_t compare_add; uint64_t swap; uint32_t rkey; } atomic; struct { struct ibv_ah *ah; uint32_t remote_qpn; uint32_t remote_qkey; } ud; } wr; uint32_t xrc_remote_srq_num;};简化API每次发送数据申请都要解决这些简单的数据结构显然是十分苦楚的。因而async-rdma的首项工作就是对这些数据结构之间的关系进行整顿,简化操作逻辑。例如库中的Rdma数据结构记录了双端建设稳固连贯所需的各种参数,后续通信过程中用到相干数据可间接复用而无需用户填充。通过高层次形象的数据结构封装,使得每次数据操作只须要用户填入必要的信息。 ...

November 4, 2022 · 1 min · jiezi

关于rust:Rust教程四

枚举能够给成员增加元组属性,属性类型能够雷同,也能够不同。 enum FRUIT { APPLE = 0, BANANA = 1, ORANGE = 2, GRAPE =3,}#[derive(Debug)]enum IPADDR { V4(u8,u8,u8,u8), V6(String),}let myFavorite = FRUIT::APPLE;println!("My favorite fruit is {:?}",myFavorite);println!("{:?} value is {:?}", FRUIT::APPLE, FRUIT::APPLE as i32);let myIP = IPADDR::V4(192,168,21,1);println!("My ip addr:{:?}", myIP);通过match能够对enum中的值做相应解决,match不仅对enum也能够对根底类型进行对应解决。match能够看作是C/C++的switch(不须要break,每次匹配到对应的值解决完后主动break) match myFavorite { FRUIT::APPLE => { println!("Red"); }, FRUIT::BANANA => { println!("Yellow"); }, FRUIT::ORANGE => { println!("Orange"); }, FRUIT::GRAPE => { println!("Purple"); },}match的default的选项解决应用"_",示意除去下面列出的选项外所有值。 let num = 25; match num { 0..=9 => { println!("Num in [0..9]"); }, 10..=50 => { println!("Num in [10..50]"); }, 51..=100 => { println!("Num in [51..100]"); }, _ => { println!("Num out of valid range [0..100]"); } }因为rust为了平安勾销了null,然而在默写非凡状况下null依然非常不便。rust引入了None,None同样是一个确认值。例如一个函数,依据计算结果返回值,但如果出现异常或者参数谬误,则返回有效None ...

October 31, 2022 · 1 min · jiezi

关于rust:Rust原子类型和内存排序

简介原子类型在构建无锁数据结构,跨线程共享数据,线程间同步等多线程并发编程场景中起到至关重要的作用。本文将从Rust提供的原子类型和原子类型的内存排序问题两方面来介绍。 Rust原子类型Rust规范库提供的原子类型在std::sync::atomic模块下。Rust提供了AtomicBool, AtomicU8, AtomicU16, AtomicUsize等原子类型。上面咱们以AtomicUsize为例介绍原子类型提供的原子操作。根本的load,store, swap原子操作就不过多介绍了。第一个要介绍的就是重要的compare-and-swap(CAS)原子操作,绝大部分无锁数据结构都或多或少依赖CAS原子操作。Rust提供的compare_and_swap接口如下: pub fn compare_and_swap(&self, current: usize, new: usize, order: Ordering) -> usizecompare_and_swap承受一个冀望的值和一个新的值,这里咱们先疏忽掉Ordering,前面会具体介绍,如果变量的值等于冀望的值,就将变量值替换成新的值返回胜利,否则不做任何批改并返回失败。compare_and_swap从语义上蕴含了读(load)语义和写(store)语义,先读出变量的值,和期望值比拟,而后写入内存。原子操作保障了这三个步骤是原子的,在三个步骤之间不会插入其余指令从而导致变量值被批改。从1.50.0开始compare_and_swap被deprecated了,当初须要应用compare_exchange和compare_exchange_weak接口来实现CAS原子操作。 pub fn compare_exchange( &self, current: usize, new: usize, success: Ordering, failure: Ordering) -> Result<usize, usize>pub fn compare_exchange_weak( &self, current: usize, new: usize, success: Ordering, failure: Ordering) -> Result<usize, usize>compare_exchange比compare_and_swap多了一个Ordering,两个Ordering别离作为CAS胜利的Ordering和失败的Ordering,前面会有解说,这里先跳过。从源代码能够看出compare_and_swap就是用compare_exchange实现的,只是compare_and_swap间接用胜利状况下的Ordering生成在失败状况下的Ordering,compare_exchange则有更高的灵活性。 pub fn compare_and_swap(&self, current: $int_type, new: $int_type, order: Ordering) -> $int_type { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, Err(x) => x, }}既然有了compare_exchange,那compare_exchange_weak是做什么用的呢?从官网文档中能够看出两个API的惟一区别是compare_exchange_weak容许spuriously fail。那么什么是spuriously fail,在x86平台上CAS是一条指令实现的,这两个API在x86平台上成果没有区别,然而在arm平台上,CAS是由两条指令实现的LL/SC(Load-link/store-conditional),在arm平台下会产生spuriously fail,来自Wikipedia的解释 ...

October 28, 2022 · 2 min · jiezi

关于rust:Rust-使用-sccache-进行编译加速

我的项目产生的 target 目录十分占用磁盘空间, cargo clean 清理后, 又须要从新编译, 十分消耗工夫, 为此, 应用 sccache 来减速编译过程. sccache 是 Mozilla 开发的一个用于缓存编译工件的守护程序(编译器缓存工具). 装置# MacOSbrew install sccache# Windowsscoop install sccache# By cargocargo install sccache首次编译后, 编译的工件缓存在 ~/.cache/sccache 目录 装置后 sccache 二进制程序会装置到 ~/.cargo/bin/sccache 应用运行: sccache -s应用 watch 监督: watch -n 1 sccache -s在 Cargo.toml 我的项目文件中减少: [build]rustc-wrapper = "~/.cargo/bin/sccache"使 sccache 作为 rustc 的包装器, 开启编译器的缓存性能.

October 27, 2022 · 1 min · jiezi

关于rust:Rust-新手学习指南为什么学-Rust如何快速上手-Volo-框架

CloudWeGo Study Group 是由 CloudWeGo 社区发动的学习小组,发展以 30 天为一期的源码解读和学习流动,帮忙新成员融入社区圈子,和社区 Committer 互动交换,并学习上手 CloudWeGo 几大框架我的项目。 CSG 流动第三期次要以学习 Rust 语言为背景,对 Volo 和 Monoio 源码进行解读。本期流动期间将会安顿 4 期直播分享,围绕的主题别离为: Rust 语言的个性、CloudWeGo 抉择 Rust 语言进行深刻摸索的起因以及 Volo 框架产生的初衷;Rustcc 聊天室:Volo 框架的设计准则、如何上手以及框架设计特点;Go 工程师如何尝试应用 Rust,如何从 Go 转型 Rust、调用 Rust 办法,Go 尝试和迁徙应用 Volo 框架的应用老本和长处;基于 io-uring 的高性能 Rust Runtime:Monoio 的技术特点及设计实现。本文整顿自 CSG 第三期第一场直播中字节跳动架构研发工程师刘捷分享内容。 回放链接:https://meetings.feishu.cn/s/... 01 嘉宾介绍 本次分享内容次要分为以下两个局部: CloudWeGo 抉择 Rust 语言进行深刻摸索的起因;创立 RPC 框架 Volo 的起因。02 前言大家可能或多或少都接触过 Rust 语言的相干信息。 前段时间,微软 Azure CTO 呐喊应用 Rust 代替 C/C++。Elon Mask 说本人是 Rust 的粉丝,然而却抉择应用 C++。这种对于语言的口水战是长久以来都是不可避免的,大家感性对待就好。 ...

October 24, 2022 · 4 min · jiezi

关于rust:rust-各种冒号的用法

rust 充斥这大量的语法噪声 咱们统计一下 rust 各种冒号的用法: 单冒号双冒号

October 23, 2022 · 1 min · jiezi

关于rust:rust-各种括号的用法

rust 充斥这大量的语法噪声 咱们统计一下 rust 各种括号的用法: 花括号圆括号尖括号

October 23, 2022 · 1 min · jiezi

关于rust:taurivue3vite3封装多窗体tauri窗口多开器

Tauri 构建跨端桌面应用程序。具备 更小、更快、更平安 的个性。 tauri 相较于 electron 构建的利用更快、更小。同样的hello world我的项目,electron 打包后体积64M,而 tauri 打包后体积4M。 因为 electron 应用了体积宏大的 Chromium 内核和Nodejs。所以构建慢,打包后体积大。 目前在github下面star达到53K。而且增长趋势很快。 开始之前在开发之前您须要装置 Rust 及其他零碎依赖。 "C++ 生成工具" 和 Windows 10 SDK。Tauri 须要 WebView2 能力在 Windows 上出现网页内容,所以您必须先装置WebView2。Rusthttps://tauri.app/zh/v1/guide... 实现了以上几个步骤,接下来就能欢快的开发了。 tauri初始化我的项目 npm create tauri-app如下图:tauri提供了十分多的前端框架供选择。 运行调试 tauri dev打包构建 tauri build 上面就介绍通过封装 WebviewWindow 构建多窗口。 import { WebviewWindow } from '@tauri-apps/api/window'const webview = new WebviewWindow('theUniqueLabel', { url: 'index.html',})webview.once('tauri://created', function () { // webview window successfully created})webview.once('tauri://error', function (e) { // an error happened creating the webview window})createWin({ label: 'Home', title: '主页', url: '/home', width: 800, height: 600,}) ...

October 22, 2022 · 3 min · jiezi

关于rust:精彩回顾-l-Rust唠嗑室Xline跨数据中心一致性管理

2022年10月15日,达坦科技和Rust语言中文社区单干,在Rust唠嗑室流动中,由达坦科技(DatenLord)联结创始人施继成做了对于开源分布式存储技术的分享,着重介绍了达坦科技新的开源我的项目Xline,这一跨云的metadata(元数据)KV存储的产品是如何实现高性能跨数据中心的数据一致性治理的。 内容介绍施继成首先介绍了做Xline这个产品的动机。最后2021年UCBerkeley 提出了Sky Computing(“天空计算”)的概念。与咱们都熟知的cloud computing(“云计算”)不同的是,sky computing,如其外表意义所讲,是天空中有很多的云,是解决跨云的问题。如何突破不同云之间的隔膜,或者买通和最大化利用跨云数据是以后面临的一个难题,也是咱们的指标所在。现在议论云计算时,咱们不须要思考云资源的部署,可扩展性等问题,因为云厂商曾经都帮忙做了。然而,一旦跨云,则无论算力的迁徙,或数据的迁徙,都是摆在咱们眼前要攻克的难题。达坦科技在做的就是解决“如何做跨云数据交互”的问题,咱们致力于将分布式系统从数据中心范畴扩散至寰球范畴,这样即便单个数据中心宕机,却仍不影响用户应用数据。 跨云存储最重要的是解决共识一致性的问题。随着业务量的增长,server数量也从最早的一个增长到了起初的多个。尽管能够使算力离开,让申请不会集中在一个server上,但同时也带来了挑战,即不同server间如何保证数据一致性,以及在多数server宕机时先前的决定还可能保留。不会呈现“公说公有理、婆说婆有理”的场面,而是始终保留统一后果,且确保高可用性,这是共识算法想要达成的目标。 随即,施继成引入了Raft和Paxos算法的概念,简略介绍了二者的倒退以及操作过程。它们的思路和传递的message大同小异,然而后者没有一个确定的leader。就传递多少message而言,没有很大差别,两者均会通过两个Round Trip Time(2RRT)才实现一个共识协定的request。 在寰球数据中心间的提早问题重大的状况下,multi-raft解决方案应运而生,其不在协定上做深究,仅做数据切片。这种状况下尽管看似欠缺,然而依然存在问题。例如,如果某数据中心区域因为某些起因不available,那么运行在该数据中心的raft group就无奈响应申请,其对应的数据也就不可取得了。那是不是把该数据备份在不同的数据中心能够解决该问题呢?能够解决问题。然而正如后面提到的实现一次申请须要消耗2RRT。若搁置于不同的数据中心,Latency则太大。所以,咱们不经要问“是不是肯定要有2RRT”? 这个问题促使大家从新扫视Raft协定。须要回顾咱们领有两个RRT的起因到底是什么?一个是确定request在log中的地位,即全局程序,另一个是散发request给followers以确保数据不被失落。后者RRT作为共识算法的能力是无奈被放弃,因而,咱们就着手从前者进行欠缺。 就全局程序的起因,不得不提到MVCC的概念。MVCC要求系统维护物理或者逻辑上的时钟,而全局程序的version就是某种程度上的逻辑时钟,刚好共识协定的log id就能够被当作是version。此时问题看似并没有失去解决,但如果假如没有contention,那也就不须要version的爱护。论文“Exploiting Commutativity For Practical Fast Replication”凑巧讲的就是这个原理,即CURP协定。CURP的劣势在于一方面在无抵触的状况下,一个RRT就能够实现申请,另一方面,在有抵触的状况下,能够进化成后端协定,即Raft或者Paxos等,最终保障没有申请都能够具备全局的version。 咱们的产品:Xline基于CURP这套协定,达坦科技开发了咱们的产品Xline,它是兼容etcd接口的metadata存储接口。施继成最初提出,咱们最终的心愿是在跨云部署的状况下能够代替etcd获得更好的性能,同时可能将CURP协定剥离进去,后续能够被其他人复用。当初Xline我的项目依然处在晚期状态,曾经领有了几个接口并且做了根本的测试。然而接口方面还有待欠缺,以及后续稳定性方面还须要迭代。咱们手动搭建了一个容器环境模拟跨云场景,手动减少网络链接的提早,当Client和Leader在一起时,Xline提早性方面的优越还无奈体现,但当Client和Leader不在一个数据中心时,Xline的劣势就相当显著,这一测试后果也合乎最后咱们对原理的阐述。 Xline我的项目是以Rust语言写就,欢送大家参加咱们开源我的项目,GitHub链接: https://github.com/datenlord/...  欲观看此次Rust唠嗑室-Xline:跨数据中心一致性治理,请点击以下B站链接:https://www.bilibili.com/vide...

October 21, 2022 · 1 min · jiezi

关于rust:Rust教程三

构造体对于rust的构造体定义和应用只对于几个特地须要留神的点进行阐明,根本用法就不多叙述。 变量与字段名同名时简写语法能够间接对应各字段变量名称,不必采纳 字段名:变量名的形式 struct Book { name:String, price:f32, pages:u32, author:String, publishingHouse:String,}fn initBook(name:String, price:f32, pages:u32, author:String, publishingHouse:String) -> Book { Book { name, price, pages, author, publishingHouse, }}援用类型构造体字段存储援用数据须要加上生命周期,否则会在编译时报错(生命周期下一节阐明) struct DataRef{ elementRef1:&str, //Error:missing lifetime specifier elementRef2:&i32, //Error:missing lifetime specifier}更改为 struct DataRef<'a> { elementRef1:&'a str, elementRef2:&'a i32,}就能够编译通过。 其中'a是定义生命周期 构造体间赋值一个曾经存在的构造体的中的局部信息能够赋值给新的构造体 #[derive(Debug)] struct Book { name:String, price:f32, pages:u32, author:String, publishingHouse:String, } let book1 = initBook( String::from("Cray rust"), 88.0, 600, String::from("Jack"), String::from("xxx")); let book2 = Book{ name:String::from("Master rust"), price:96.0, pages: 800, ..book1 }; println!("{:?}", book2); //println!("{:?}", book1); //Error:borrow of partially moved value: `book1`book1中的作者和出版社信息与book2一样,咱们能够在book2赋值时,通过..book1将book1中的值进行复制。 ...

October 19, 2022 · 2 min · jiezi

关于rust:Rust教程二

所有权 先看一段代码 let s3 = "hello"; let s4 = s3; println!("{}", s3); let s1 = String::from("hello"); let s2 = s1; //println!("{}", s1); //Error:^^ value borrowed here after move let array1 = [0,1,2,3,4,5]; let ap = &array1; println!("{}", ap[3]) println!("{:p},{:p}", &array1, ap);打印s3的能够失常执行,打印s1的却报错。这是什么起因?<1>s3的内容是栈里调配的, s3 = s4这是copy操作,相似复制了一个字符类型的变量s4.如下类型的会是copy类型的。因为这些类型都是在栈里调配的,所以应用copy操作会很快 所有整数类型布尔浮点字符(是字符,不是string!!)元组 (元组内的元素也都是copy类型的, (i32, i32), (i32, 'aa')是copy类型。(i32,String)的不是copy类型<2>s1是String,不是字符类型。的内容是在堆里调配的,s2 = s1的操作是将s1指向内存"hello"的所有权转移给s2. 所以s1就被开释了 <3>借用操作符 &,这与C/C++相似,就是应用&获取内存地址。 ap = &array1理论就是获取array1的内存地址,付给ap. 所有权与函数函数参数所有权 函数会有参数传入,此时所有权是否会产生变更? 测试代码如下 U32FnGetOwner let v:u32 = 32; println!("v address before fn:{:p}", &v); getU32Owner(v); println!("v address after fn:{:p}", &v); println!("{}", v) fn getU32Owner(v:u32) { println!("v address in fn:{:p}", &v); println!("v value:{}", v); }失常执行 栈上调配的copy类型的变量,在函数内copy出新的变量。输入后果如下: ...

October 18, 2022 · 2 min · jiezi

关于rust:The-embedonomicon学习笔记

《The embedonomicon》学习笔记和原教程的一些差别重写了第五章,因为!asm和!global_asm曾经进入stable,原文那种形式切实太繁琐。Rust Edition原书采纳2018,本文采纳2021。依照官网的说法,Rust Edition和Rust的版本应该是独立的,基于任何一个Rust Edition的代码应该都能够在最新版本的Rust编译器上编译。(All Rust code, regardless of edition, is ultimately compiled to the same internal representation within the compiler.)原文中是通过cargo子命令的形式去调用cargo-binutils,例如应用cargo size而不是rust-size。集体感觉这样尽管简洁然而不够直观,因而我将应用间接调用的形式调用cargo-binutils,将编译和查看二进制两个过程分离出来。所有命令都是在powershell下运行的【0】前言《The embedonomicon》蕴含了以下内容: 率领你从头开始构建#![no_std]应用程序(裸机编程)开发基于特定架构的Cortex-M微控制器的应用程序,并一直迭代这个过程目标通过本文,你会学到: 如何构建一个#![no_std]程序(裸机编程,不依赖OS)。如何管制Rust程序的内存布局(在链接阶段确定),这须要接触链接器、链接脚本和一些跟ABI相干的Rust feature如何实现能够被动态笼罩(statically overridden)的函数,动态笼罩意味着没有运行时耗费前置条件因为本文是基于win10的,所以只介绍win10下相干工具的装置过程 Rust相干 Rust编译器:原书采纳1.31,本文采纳1.60.0cargo-binutils:间接应用最新QEMU模拟器 采纳7.0.0版本(qemu-w64-setup-20220419.exe) gdb工具 应用gcc-arm-none-eabi-10.3-2021.10-win32或arm-gnu-toolchain-11.3.rel1-mingw-w64-i686-arm-none-eabi。 留神不要应用gcc-arm-11.2-2022.02-mingw-w64-i686-arm-none-eabi,这个版本依赖过期的32位python2.7,在Win10上很难筹备相干的运行环境给它,相干探讨见这里【1】最小的#![no_std]程序这个章节次要是写一个#![no_std]版的hello world程序,残缺代码见:https://github.com/youth7/the-embedonomicon-note/tree/01-the-smallest-nostd-program std和corestd std意味着程序运行在通用OS上(通用OS通常提供线程,过程,文件系统,socket等API),它封装了OS形象层的拜访形式。除此还提供其它性能,包含: 栈溢出爱护命令行参数解决在main函数的调用前生成主线程core #![no_std]意味着程序将依赖core而不是std。core是std的子集,只提供语言的根本类型(如float、string、slice)以及裸露处理器的个性(如一些原子操作和SIMD指令)。core不提供规范的运行时,没有堆调配。因而,#![no_std]通常是零碎中的第一或惟一的程序,它能做一般Rust程序所不能的事件,例如: 内核或者OS固件bootloader例子当初咱们来看看这个程序 #![no_main]//通知编译器不要应用main函数作为程序的入口,因为main对运行时有要求#![no_std]//下面曾经解释过use core::panic::PanicInfo;#[panic_handler]//自定义程序奔溃时的行为,因为不足运行时的起因这个必须本人定义fn panic(_panic: &PanicInfo<'_>) -> ! { loop {}}顺次应用以下2个命令将源码编译为指标文件,并查看其中的符号 # 编译代码,--target是cargo命令的参数,指定了编译产物的指标平台,详情参考cargo book# --emit指定了编译产物的文件类型,详情参考rustc bookcargo rustc --target thumbv7m-none-eabi -- --emit=obj# 列出指标文件中的符号rust-nm target/thumbv7m-none-eabi/debug/deps/app-*.o此时的输入为 00000000 T rust_begin_unwind如果你装置了wsl2的话,能够用其它命令来查看符号,例如应用readelf来查看 readelf -s ./target/thumbv7m-none-eabi/debug/deps/*.o控制台输入: Symbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS 49d4frxgydk7ies3 2: 00000000 0 SECTION LOCAL DEFAULT 3 3: 00000000 0 NOTYPE LOCAL DEFAULT 3 $t.0 4: 00000000 0 SECTION LOCAL DEFAULT 6 5: 00000000 0 SECTION LOCAL DEFAULT 7 6: 00000000 0 SECTION LOCAL DEFAULT 11 7: 00000000 0 SECTION LOCAL DEFAULT 18 8: 00000000 0 SECTION LOCAL DEFAULT 20 9: 00000001 8 FUNC GLOBAL HIDDEN 3 rust_begin_unwind或者应用nm来查看 ...

October 17, 2022 · 16 min · jiezi

关于rust:Rust教程一

变量要点变量(let)默认不可变,如果要可变须要应用可变变量(关键字mut) 不可变变量 let x = 0; println!("The value of x is: {}", x); x = 1; //Error cannot assign twice to immutable variable `x` println!("The value of x is:{}", x);第四行 x = 1; 会报错 Error cannot assign twice to immutable variable x 可变变量在定义处加关键字“mut”则变量x变为可变变量 let mut x = 0; println!("The value of x is: {}", x); x = 1; println!("The value of x is:{}", x);暗藏同名变量能够屡次定义,最新定义的会笼罩之前定义的变量 let v = 2; let v = v+1; let v = v*10; println!("The value of v is:{}", v);v的后果为30 ...

October 17, 2022 · 1 min · jiezi

关于rust:rust-省略-return-关键字

在 rust 的函数中,能够不写 return 像在 python 中,不写 return 示意 return None 然而在 rust 中,rust 省略 return 关键字,『函数会默认应用最初一条语句的执行后果作为返回值』 参考:Rust 函数

October 12, 2022 · 1 min · jiezi

关于rust:Rust唠嗑室Xline跨数据中心一致性管理

内容简介随着互联网和云计算的业务规模越来越大,单个数据中心曾经无奈满足业务的需要,业务零碎从单数据中心向多数据中心倒退,多地多核心多活部署的需要也越来越广泛。多数据中心架构最大的挑战是,如何保证数据跨数据中心拜访的一致性和性能。比方索引、权限、配置等这类须要跨数据中心共享拜访的元数据,如何在多核心竞争批改的场景下,依然能放弃一致性,并且保障拜访性能。 传统单数据中心解决方案无奈满足跨数据中心的场景对性能和一致性的需要。DatenLord推出开源的分布式KV存储Xline,就是针对多数据中心场景,实现数据的高性能跨云、跨数据中心共享拜访,并且保证数据的一致性,不便业务零碎实现多地多核心多活部署。 本周六(10月15日)下午3点,达坦科技和Rust语言中文社区单干,由达坦科技的联结创始人施继成在Rust唠嗑室做开源分布式存储技术的分享,介绍Xline是如何实现高性能跨数据中心的数据一致性治理。欢送大家预约收看!

October 12, 2022 · 1 min · jiezi

关于rust:文盘Rust-struct-中的生命周期

最近在用rust 写一个redis的数据校验工具。redis-rs中具备 redis::ConnectionLike trait,借助它能够较好的来形象校验过程。在开发中,未免要定义struct 中的某些元素为 trait object,从而带来一些rust语言中的生命周期问题。本文不具体探讨 redis的数据校验过程,通过一个简略的例子来聊聊 struct 中 trait object 元素的生命周期问题。 首先来定义一个 base trait,该 trait 中只蕴含一个函数,返回String类型。 pub trait Base { fn say(&self) -> String;}接下来,定义两个实现了 Base trait 的 struct AFromBase 和 BFromBase pub struct AFromBase { content: String,}impl Base for AFromBase { fn say(&self) -> String { self.content.clone() }}pub struct BFromBase { text: String,}impl Base for BFromBase { fn say(&self) -> String { self.text.clone() }}接下来,定义一个struct 蕴含两个 Base trait 的 trait object ,而后实现一个函数是 say 函数输入的字符串的拼接后果.依照其余没有生命周期语言的编写习惯,直觉上这么写 ...

October 8, 2022 · 2 min · jiezi

关于rust:rust-双冒号运算符

第一次看到双冒号运算符 :: 是在教程的 Rust 程序设计语言 中文版 String 类型 在第 5 章的“办法语法”(“Method Syntax”)局部会着重解说这个语法而且在第 7 章的“门路用于援用模块树中的项”中会讲到模块的命名空间。想理解更多就点进去看看吧!

September 29, 2022 · 1 min · jiezi

关于rust:文盘Rust-如何把配置文件打包到二进制文件里

在理论开发中,常常会遇到各种不同的配置文件。通常,程序运行的各种配置从内部读取,以加强利用配置的灵活性。java 生态中的 springboot 提供了这种设计的榜样。springboot 的应用程序,默认通过 application.yml 加载配置。默认的 application.yml 文件打进 jar 包,如果想改变程序的行为,能够在jar 包的同级目录下创立 application.yml 文件或者通过参数指定配置文件地位。那么在 rust 生态里有没有方法把默认配置文件打包到二进制文件呢。咱们能够通过 rust-embed 第三方库来实现这一成果。在理论开发中的典型场景是: 不指定任何配置文件时,应用默认配置文件;当应用程序同级目录下蕴含配置文件时加载该配置文件。 定义嵌入文件的地位及获取函数  src/resources/embed_resource.rs 中定义了嵌入文件的地位及获取函数  `rust  use rust_embed::RustEmbed;   #[derive(RustEmbed)]  #[folder = "src/embedfiles/"]  struct Asset;   pub fn get_app_default() -> Option<rust_embed::EmbeddedFile> {    Asset::get("./app_default.yml")  }  ` 宏定义了嵌入文件的目录 '#[folder = "src/embedfiles/"]',获取文件函数以该目录为根。 应用嵌入文件  `rust  fn main() {    if Path::new("./app.yml").exists() {        let contents =            fs::read_to_string("./app.yml").expect("Read file error!");        println!("{}", contents);        return;    }    let app = get_app_default().unwrap();    let f = std::str::from_utf8(app.data.as_ref()).unwrap();    println!("{}", f);  }  ` ...

September 13, 2022 · 1 min · jiezi

关于rust:选择-Go-还是-RustCloudWeGoVolo-基于-Rust-语言的探索实践

本文整顿自 CloudWeGo 开源一周年技术沙龙流动中字节跳动基础架构服务框架资深研发工程师吴迪的演讲分享,技术沙龙主题为《字节高性能开源微服务框架:CloudWeGo》。 本文将从以下三个方面介绍 CloudWeGo 开源的国内首个 Rust RPC 框架 Volo: CloudWeGo 抉择 Rust 语言进行摸索的起因;创立 RPC 框架 Volo 的起因;Rust 语言和 Go 语言如何抉择。 CloudWeGo 抉择 Rust 语言进行摸索的起因CloudWeGo 正式官宣新一代 Rust RPC 框架 Volo 开源!很多敌人会有疑难,CloudWeGo 为什么会抉择 Rust 这门语言进行摸索呢?本文首先介绍一下其中的起因。 Volo 开源官宣:https://mp.weixin.qq.com/s/Xc... Go 的代价深度优化艰难Volo 晚期的团队成员来自于 Kitex 我的项目(CloudWeGo 开源的 Golang 微服务 RPC 框架)。过后咱们投入了大量的工夫和精力优化 Kitex 以及其余相干根底库的性能,最终却发现实现 Go 的深度优化有些艰难。咱们仅仅能够做一些算法层面和实现层面的优化,如果想往下持续做其余层面的优化,比方指令层面的优化,是很难以低成本的形式实现的。而且在大多数状况下很多优化是要和 runtime 以及编译器作奋斗的。 工具链和包治理不够成熟例如,应用 Kitex 框架时须要先应用对应的 Kitex 工具生成代码,能力失常编译应用。尽管这种状况可能在 Frugal 工具成熟之后有所改善,然而在 IDL 有更新的状况下,还是须要应用 Kitex 从新生成对应的构造体。这个问题并不是 Kitex 的问题,而是 Go 语言自身的问题,Go 语言在编译时没有提供相似的能力。、 形象能力较弱Go 语言的形象能力是比拟弱的,而且 Go 语言外面的形象并不是零老本形象,而是有代价的形象。 ...

September 7, 2022 · 4 min · jiezi

关于rust:DatenLord|Rust程序性能分析

首发|RustMagazine 简介程序的性能剖析是一个很广很深的话题,有各种各样的工具来对不同的指标进行测试剖析。本文次要介绍如何用profiling工具对Rust程序进行On-CPU和Off-CPU的性能剖析,以及如何绘制火焰图对后果测试进行可视化解决。 On-CPU性能剖析On-CPU的性能剖析为了找出占用CPU工夫多的工作或者函数,进而找出程序的性能瓶颈。这里次要介绍perf工具,perf是Linux提供的命令,也叫perf_events,它属于Linux kernel,在tools/perf目录下。perf提供了弱小的性能包含监测CPU performance counters, tracepoints, kprobes和 uprobes等。这里咱们应用perf的CPU profiling性能。因为perf会拿到零碎的信息,所以运行须要root权限。perf做On-CPU性能剖析的原理是以一个指定的频率对CPU进行采样,进而拿到正在CPU上运行的指令乃至整个函数调用栈的快照,最初对采样的数据分析,比如说在100次采样中有20次在运行A指令或者A函数,那么perf就会认为A函数的CPU使用率为20%。 上面咱们应用一个简略的程序来展现如何用perf来进行On-CPU的性能剖析,须要应用debug编译,程序如下: fn test2() { for _ in 0..200000 { () }}fn test1() { for _ in 0..100000 { () } test2();}fn main() { for _ in 0..10 { test1(); }}咱们在test1()函数和test2()函数中别离退出了一个段循环来耗费CPU资源,在test2()中咱们循环了200000次是在test1()中的两倍。咱们应用如下perf命令来做CPU profiling: $ sudo perf record --call-graph=dwarf ./target/debug/mytest采样的数据默认会存到perf.data文件中。参数--call-graph的目标是开启函数调用栈的记录,这样在profiling的后果中能够打印出残缺的函数调用栈。目前perf反对fp(frame pointer), dwarf(DWARF's CFI - Call Frame Information)和lbr(Hardware Last Branch Record facility)三种形式来获取函数调用栈。稍后咱们会简略介绍fp和dwarf的原理。因为Rust编译器默认生成了dwarf格局的调试信息,咱们能够间接应用--call-graph=dwarf。咱们能够应用如下命令来读取profiling的后果: $ sudo perf report --stdio这个命令会默认读取perf.data中的数据并格式化输入。命令的输入如下,因为输入很长,局部无关信息被省略掉, # Children Self Command Shared Object Symbol# ........ ........ ....... ................. .........................................................................................................# 77.57% 0.00% mytest mytest [.] _start | ---_start __libc_start_main main ...... mytest::main mytest::test1 | |--52.20%--mytest::test2 | | | --46.83%--core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next | |...... | --23.87%--core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next |...... |...... 从输入能够看出整个测试程序占用了77.57%的CPU资源,在mytest::test1函数中有23.87%的工夫在做for循环,有52.20%的工夫被调用的mytest::test2函数占用,而后在mytest::test2函数中,有45.32%工夫在做for循环,剩下的工夫是一些其余的开销。profiling的后果根本体现了咱们测试程序CPU占用率的理论状况。咱们在mytest::test2函数中for循环次数是mytest::test1函数中两倍,相应的咱们也看到了在CPU占用率上也简直是两倍的关系。 ...

September 3, 2022 · 2 min · jiezi

关于rust:国内首个基于-Rust-语言的-RPC-框架-Volo-正式开源

Volo 是字节跳动服务框架团队研发的轻量级、高性能、可扩展性强、易用性好的 Rust RPC 框架,应用了 Rust 最新的 GAT 和 TAIT 个性。 在字节外部,Volo 曾经落地多个业务和根底组件,并且获得了超预期的性能收益(与 Go 版本比照,不那么偏心)。 Volo 与其它 CloudWeGo 开源我的项目一样,保持内外保护一套代码,为开源应用提供了强有力的保障。同时,咱们察看到 Rust 开源社区在 RPC 框架这块还比拟单薄,Volo 的开源心愿能为社区的欠缺奉献一份力量,同时也能欠缺 CloudWeGo 生态矩阵,为谋求性能、安全性和最新技术的开发者、企业以及 Rustaceans 开发 RPC 微服务、搭建云原生分布式系统提供强有力的反对。 本文会为大家简略介绍 Volo 及其相干生态,并为大家提供一个简略的 Rust 与 Go 的选型倡议。 01 我的项目缘起其实 Volo 的开创成员来自于 Kitex 团队(CloudWeGo 开源的 Go RPC 框架),过后咱们在 Go 上做了十分深度的性能优化,也因而粗浅感触到了在 Go 上做性能优化所面临的妨碍。因而,咱们抉择了 Rust,冀望可能给需要极致性能、平安和指令级掌控能力的业务一个适合的抉择。而 RPC 框架是分布式系统中重要的组成部分,Volo 就这么诞生了。 02 个性高性能Rust 以高性能和平安著称,咱们在设计和实现过程中也时刻以高性能作为咱们的指标,尽可能升高每一处的开销,晋升每一处实现的性能。 首先要阐明,和 Go 的框架比照性能是极不偏心的,因而咱们不会着重比拟 Volo 和 Kitex 的性能,并且咱们给出的数据仅能作为参考,心愿大家可能主观对待。同时,因为在开源社区并没有找到另一款成熟的 Rust 语言的 Async 版本 Thrift RPC 框架,而且性能比照总是容易引战,因而咱们心愿尽可能弱化性能数据的比照,仅会颁布咱们本人极限 QPS 的数据。 ...

August 31, 2022 · 2 min · jiezi

关于rust:rskynet

rskynet 是用 Rust 语言编写的小程序,尽管它的名字叫天网(Skynet),但它确实是一个小程序,代码有余千行,当前也不会有更多的代码。之所以写这个程序,一是为了相熟 Rust 语言,二是为了便于可视化我的一些三维数据。rskynet 的前身是一份用 Python 3 写的脚本,名字叫 hamal [1]。二者性能基于一样,但 rskynet 在抉择三维场景的察看方位更为容易,因为它实现了当初我的一个构想 [2],即在场景的突围球上,以经纬度的形式结构察看方位。 源码的获取和编译$ git clone https://gitee.com/garfileo/rskynet.git$ cd rskynet$ rustc -O rskynet.rs用法在 rskynet/data 目录,我提供了 5 份三维数据文件作为示例,其类型别离是点集(points.asc)、矢量集(vectors.asc)、线段集(paths.asc)、轴向盒集(boxes.asc),曲面网格(mesh.off),要实现它们的可视化,只需 # 渲染点集$ rskynet --points points.asc$ povray +A +P points.pov# 渲染矢量集$ rskynet --vectors vectors.asc$ povray +A +P vectors.pov# 渲染门路集$ rskynet --paths paths.asc$ povray +A +P paths.pov# 渲染轴向盒集$ rskynet --boxes boxes.asc$ povray +A +P boxes.pov# 曲面网格$ rskynet --mesh mesh.asc$ povray +A +P mesh.povrskynet 输入了什么?以点集为例,将点集文件 foo.asc 输出 rskynet,亦即 ...

August 20, 2022 · 2 min · jiezi

关于rust:在Rust和C之间传递字符串有-7-种方法

Rust与C的互操作性,是Rust中最令人难以置信的事件之一。C能够平安地调用 Rust代码,且Rust能够应用具备C接口的出名库的能力,是整个行业疾速采纳 Rust的要害起因。 它还容许咱们通过为rust crate实现C接口来更好地散发代码,因而它能够被任何可能调用C语言编写的软件应用。 1.将Rust字符串传递给C的5种办法(查看图片):(1)提供创立和删除的办法;(2)调配缓冲区并复制数据;(3)将内存分配器办法传递给Rust;(4)从Rust调用glibc;(5)借用Rust string; 2.将C字符串传递给Rust的2种办法(查看图片):(1)将其转换为&str,不复制数据;(2)复制数据并接管string;

August 19, 2022 · 1 min · jiezi

关于rust:rust-微信支付

微信领取有很多接口,咱们就以jsapi为例,来展现小程序如何发动领取,和进行领取回调解密。 简略封装微信领取办法wx_pay.rs use reqwest::header::{CONTENT_TYPE, ACCEPT, HeaderMap, AUTHORIZATION, USER_AGENT};use reqwest::{Error, Response};use serde::{Serialize, Deserialize};use serde_json::value::Value;use rsa::{RsaPrivateKey, PaddingScheme, Hash, pkcs8::DecodePrivateKey};use crypto::sha2::Sha256;use crypto::digest::Digest;use std::iter::repeat;use crate::utils::rand_string;use crate::constants::WECHAT_PAY_APIV3;use chrono::Utc;use aes_gcm::{ aead::{Aead, KeyInit, generic_array::GenericArray, Payload}, Aes256Gcm, Nonce};pub struct WxPay<'a> { pub appid: &'a str, pub mchid: &'a str, pub private_key: &'a str, pub serial_no: &'a str, pub apiv3_private_key: &'a str, pub notify_url: &'a str, pub certificates: Option<&'a str>,}#[derive(Serialize, Debug)]pub struct WxData { pub sign_type: String, pub pay_sign: String, pub package: String, pub nonce_str: String, pub time_stamp: String}#[derive(Serialize, Deserialize)]pub struct Amount { pub total: u32,}#[derive(Serialize, Deserialize, Debug)]pub struct Payer { pub openid: String,}#[derive(Serialize, Deserialize)]pub struct JsapiParams { pub description: String, pub out_trade_no: String, pub amount: Amount, pub payer: Payer,}#[derive(Clone, Copy)]struct ApiBody<'a> { url: &'a str, method: Method, pathname: &'a str,}#[derive(Clone, Copy)]enum Method { GET, POST, } /// 微信领取,回调解密#[derive(Serialize, Deserialize, Debug)]pub struct WxNotifyData { pub mchid: String, pub appid: String, pub out_trade_no: String, pub transaction_id: String, pub trade_type: String, pub trade_state: String, pub trade_state_desc: String, pub bank_type: String, pub attach: String, pub success_time: String, pub payer: Payer, pub amount: WxNotifyDataAmount}#[derive(Serialize, Deserialize, Debug)]pub struct WxNotifyDataAmount { pub total: u32, pub payer_total: u32, pub currency: String, pub payer_currency: String,}#[derive(Serialize, Deserialize, Debug)]pub struct WxPayNotifyResource { pub algorithm: String, pub associated_data: String, pub ciphertext: String, pub nonce: String, pub original_type: String,}#[derive(Serialize, Deserialize, Debug)]pub struct WxPayNotify { pub create_time: String, pub event_type: String, pub id: String, pub resource: WxPayNotifyResource, pub resource_type: String, pub summary: String,}impl<'a> WxPay<'a> { fn rsa_sign(&self, content: String, private_key: &str) -> String { // let der_bytes = base64::decode(der_encoded).expect("Failed to decode base64 content"); // 获取私钥对象 let private_key = RsaPrivateKey::from_pkcs8_pem(private_key).expect("Failed to parse key"); // 创立一个Sha256对象 let mut hasher = Sha256::new(); // 对内容进行摘要 hasher.input_str(content.as_str()); // 将摘要后果保留到buf中 let mut buf: Vec<u8> = repeat(0).take((hasher.output_bits() + 7) / 8).collect(); hasher.result(&mut buf); // 对摘要进行签名 let sign_result = private_key.sign( PaddingScheme::PKCS1v15Sign { hash: Option::from(Hash::SHA2_256) }, &buf ); // 签名后果转化为 base64. let vec = sign_result.expect("Create sign error for base64"); base64::encode(vec) } fn get_headers(&self, api_body:ApiBody, params_string: String) -> Result<HeaderMap, Error> { let dt = Utc::now(); let timestamp = dt.timestamp(); let onece_str = rand_string(32); let method = match api_body.method { Method::GET => "GET", Method::POST => "POST" }; // 获取签名 let signature = self.rsa_sign( method.to_string() + "\n" + api_body.pathname + "\n" + timestamp.to_string().as_str() + "\n" + onece_str.as_str() + "\n" + params_string.as_str() + "\n" , &self.private_key ); // 组装header let authorization = "WECHATPAY2-SHA256-RSA2048 mchid=\"".to_string() + &self.mchid + "\",nonce_str=\"" + onece_str.as_str() + "\",timestamp=\"" + timestamp.to_string().as_str() + "\",signature=\"" + signature.as_str() + "\",serial_no=\"" + &self.serial_no + "\""; let mut headers = HeaderMap::new(); headers.insert(CONTENT_TYPE, "application/json; charset=utf-8".parse().unwrap()); headers.insert(ACCEPT, "application/json".parse().unwrap()); headers.insert(AUTHORIZATION, authorization.parse().unwrap()); headers.insert(USER_AGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71".parse().unwrap()); Ok(headers) } /// js 微信领取 pub async fn jsapi(&self, params: JsapiParams) -> Result<WxData, Error> { println!("aaaj jsapi {}", &self.appid); println!("aaaj jsapi {:#?}", params.payer.openid); #[derive(Serialize, Deserialize)] struct Jsapi<'a> { description: String, out_trade_no: String, amount: Amount, payer: Payer, appid: &'a str, mchid: &'a str, notify_url: &'a str, } let jsapi_params = Jsapi { description: params.description, out_trade_no: params.out_trade_no, amount: params.amount, payer: params.payer, appid: &self.appid, mchid: &self.mchid, notify_url: &self.notify_url, }; let jsapi_str = serde_json::to_string(&jsapi_params).unwrap(); let api_body = ApiBody { url: "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", method: Method::POST, pathname: "/v3/pay/transactions/jsapi", }; let headers_all = self.get_headers(api_body, jsapi_str).unwrap(); #[derive(Serialize, Deserialize, Debug)] struct JsapiRes { prepay_id: String } let client = reqwest::Client::new(); let pre_data: JsapiRes = client.post(api_body.url.clone()) .headers(headers_all) .json(&jsapi_params) .send() .await .unwrap() .json() .await.unwrap(); let ran_str = rand_string(32); // package: `prepay_id=${JSON.parse(preData.data).prepay_id}`, let pack = "prepay_id=".to_string() + pre_data.prepay_id.as_str(); let dt = Utc::now(); let now_time = dt.timestamp(); // 获取签名 let pay_si = self.rsa_sign( self.appid.to_string() + "\n" + now_time.to_string().as_str() + "\n" + ran_str.as_str() + "\n" + pack.as_str() + "\n" , &self.private_key ); let wx_data = WxData { sign_type: "RSA".into(), pay_sign: pay_si, package: pack, nonce_str: ran_str, time_stamp: now_time.to_string(), }; Ok(wx_data) }}/// 微信领取,回调解密pub fn decode_wx(params: WxPayNotify) -> Result<WxNotifyData, Error> { let auth_key_length = 16; let mut t_key = [0u8; 32]; hex::decode_to_slice(hex::encode(WECHAT_PAY_APIV3), &mut t_key as &mut [u8]).unwrap(); let key = GenericArray::from_slice(&t_key); let mut t_nonce = [0u8; 12]; hex::decode_to_slice(hex::encode(params.resource.nonce.clone()), &mut t_nonce as &mut [u8]).unwrap(); let nonce = GenericArray::from_slice(&t_nonce); let t_ciphertext_base = base64::decode(params.resource.ciphertext.clone()).unwrap(); let cipherdata_length = t_ciphertext_base.len() - auth_key_length; let cipherdata = &t_ciphertext_base[0..cipherdata_length]; let auth_tag = &t_ciphertext_base[cipherdata_length..]; let mut ciphertext = Vec::from(cipherdata); ciphertext.extend_from_slice(&auth_tag); let mut t_add = [0u8; 11]; // 这里可能会依据返回值 associated_data 长度而不同,目前应该是固定为 "transaction" 。 hex::decode_to_slice(hex::encode(params.resource.associated_data.clone()), &mut t_add as &mut [u8]).unwrap(); let payload = Payload { msg: &ciphertext, aad: &t_add, }; let cipher = Aes256Gcm::new(key); let plaintext = cipher.decrypt(nonce, payload).unwrap(); let content = std::str::from_utf8(&plaintext).unwrap(); let data: WxNotifyData = serde_json::from_str(content).unwrap(); Ok(data)}写领取接口,和回调接口pay.rs ...

August 18, 2022 · 5 min · jiezi

关于rust:与-Rust-勾心斗角-快没有爱了

基于 Rust 的 Vec 容器,能够表白数学里的 n 维点。上面的 foo 函数能够依据两个 n 维点 a 和 b,结构一个点集 {a, b, c},其中 c 是 a 和 b 的中点。 fn foo(a: &Vec<f64>, b: &Vec<f64>) -> Vec<Vec<f64>> { assert_eq!(a.len(), b.len()); let mut c: Vec<f64> = Vec::new(); for i in 0 .. a.len() { c.push(0.5 * (a[i] + b[i])); } let mut points: Vec<Vec<f64>> = Vec::new(); points.push(a.clone()); points.push(b.clone()); points.push(c); return points;}留神,points 存储的是 a 和 b 的正本,并非 a 和 b 自身。假使我心愿 points 里存储的是 a 和 b 自身,该如何做呢?我能想到的计划是 ...

August 15, 2022 · 2 min · jiezi

关于rust:当RDMA遇到Rust

2022年8月5日-6日,一年一度的中国开源基础设施流动日(OpenInfra Days China)行将在线上举办。本次会议没有限定一个对立的主题,次要聚焦云计算基础设施、云原生技术与利用实际、开源治理、5G、算力网络与边缘计算五大主题方向。 云计算基础设施分论坛次要聚焦云计算基础设施畛域的前沿技术和优良实际,围绕多硬件架构和多操作系统反对、人工智能技术利用、网络与存储,数据处理DPU及其他减速硬件、硬件自动化和智能运维等方面开展技术分享和探讨。达坦科技联结创始人施继成将在这一分论坛做题为当RDMA遇到Rust的专题分享。 在大会开始前,咱们请施继成就此次流动以关键词开源、基础设施、Rust、RDMA进行了一次快问快答的剧透式分享,欢送先睹为快:**问:达坦做存储的底层操作系统为什么抉择开源?答**:因为在服务器市场,开源是大家的次要抉择,抉择开源也就抉择了用户。另一方面,开源软件可能帮忙咱们构建衰弱倒退的社区,吸引更多的开发者来退出咱们,进一步倒退和欠缺我的项目。 问:达坦为什么抉择Rust做RDMA库呢?Rust语言有什么特点或劣势是能够解决RDMA目前的技术痛点和难点?答:次要是看重 Rust 语言的安全性,Rust 可能利用语言级别的个性对性能应用进行规约,达到内存和线程平安的目标。另一方面,Rust 语言还是零老本形象的,所以性能卓越,能够与 C 语言媲美。因而咱们抉择 Rust 语言来解决 RDMA 这个底层且高速的网络协议。 问:达坦通过Rust实现RDMA API治理库,次要解决了哪几个问题?答:首先,是实现Rust语言间接调用RDMA的API; 其次,实现了更平安、高效地治理RDMA的内存资源;最初,是在底层的RDMA ibverbs接口上封装高级的形象层,实现多台机器的内存资源能对立治理。 参会形式想要理解更多达坦科技为什么抉择Rust做RDMA库,以及开发设计背地的理念、逻辑、和实践经验,欢送扫描海报二维码,收费注册报名。无意退出Rust前沿交换探讨群,请增加小助手微信:

August 8, 2022 · 1 min · jiezi

关于rust:Rust-X-Datenlord-第二届中国Rust开发者大会回顾

达坦科技自成立以来积极探索软硬件深度交融,专一于打造新一代的开源跨云存储平台,以满足不同行业客户对数据跨云、跨数据中心高性能拜访的需要。 今年以来陆续发声,将达坦科技开源我的项目async-rdma的技术实际和案例对外输入,动摇地做Rust语言的布道,也将达坦科技摸索的新一代硬件麻利开发的研究成果在各硬件技术大会上做分享(本周的次条为达坦科技的团队在南京加入中国计算机学会芯片大会的回顾)。 专题演讲作为一家All in Rust的科技初创公司,上周日召开的第二届中国Rust开发者大会必定不会缺席,达坦科技更是在下午专题演讲和研讨会两个场次分享了公司使用这一在根底底层软件开发中日益受欢迎,行将无望成为Linux官网第二语言的实际开发教训。 首先,达坦科技联结创始人施继成在大会下午场-Rust在嵌入式、操作系统和物联网的利用实际的专题组做了题为Rust for Linux is Coming的专题分享。Rust for Linux 背地的逻辑是指不扭转 Linux 操作系统的接口,用渐进的形式最终齐全兼容现有 Linux 上的所有应用程序的计划。尽管这一工具目前还没有进入主分支,但曾经进入了 Linux-next 分支。施继成将Rust for Linux比作程序员进行软件开发的脚手架,并具体拆解了它的六个次要组件的核心内容和技术要点。 线上workshop正因为Rust语言的实用价值,吸引了越来越多的程序员想要尝试学习Rust。因而,在Rust大会上,达坦科技还举办了一场干货满满的线上workshop:用Rust实现RDMA高性能编程。达坦科技技术团队首先遍及了RDMA的设计理念、其自身的优缺点,以及目前支流的RDMA和以太网交融的两种计划及其优劣。 随着将来RDMA利用场景的大大拓展(例如:在广域网、跨数据中心场景中应用),进步RDMA编程性能,改善RDMA内存治理是要害。所以,在第二场研讨会技术演示阶段,达坦科技技术团队着重介绍了RDMA权限治理和远端内存操作,并就其目前曾经开源的我的项目为例,详解了async-rdma的设计理念和逻辑,包含RDMA异步I/O,RDMA高层通信协议等。 在workshop的最初还筹备了入手的试验环节,让参加探讨学习的与会者理论体验如何用Rust构建RDMA利用。 正是因为用Rust Bindgen 生成底层 RDMA 接口,并不平安。因而,达坦科技在此下面提供了 RDMA 高层异步接口进行封装。因为达坦科技专一于做软硬件联合的存储系统,不可避免地要和Linux内核打交道,所以,Rust for Linux帮忙咱们构建平安且有效率的存储系统。 欲观看完整版Workshop视频,请点击以下链接:Workshop One:用Rust实现RDMA高性能编程Workshop Two:Async RDMAWorkshop Three: Workshop入手试验环节 参加咱们目前,咱们将整个库放在了Github.com/datenlord/async-rdma上,并且也在继续迭代中,欢送感兴趣用Rust语言实现高性能编程的你前来探讨。 无意退出Rust前沿交换探讨群,请增加小助手微信:

August 8, 2022 · 1 min · jiezi

关于rust:文盘Rust-配置文件解析

解决配置文件是利用开发的惯例操作。成熟的开发语言都有本人解决配置文件的套路。golang 有 viper 这样的成熟第三方库来解决配置文件。rust 的第三方库并不成熟。 这篇文章咱们来聊聊 rust 如何解决配置文件。 解决yaml配置文件的流程 配置文件的作用是一系列应用程序相应性能的开关。在利用启动前配置,利用启动时加载,以备运行时应用。 咱们仍旧用interactcli-rs 为例,阐明一下配置文件的处理过程。 解析配置文件的次要逻辑在 src/configure 目录。 定义 config 构造体 首先,定义一个构造体用来承载配置项。因为 Config struct 须要与yaml文件交互,咱们定义一个具备序列化与反序列化能力的构造体。 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]pub struct Config { pub server: String, pub token: String,}为 Config 构造体定义必要的性能 impl Config { pub fn default() -> Self { Self { server: "http://127.0.0.1:8080".to_string(), token: "".to_string(), } } pub fn set_self(&mut self, config: Config) { self.server = config.server; self.token = config.token; } pub fn get_config_image(&self) -> Self { self.clone() } pub fn flush_to_file(&self, path: String) -> Result<()> { let yml = serde_yaml::to_string(&self)?; fs::write(path, yml)?; Ok(()) }}利用 lazy_static 初始化配置项单例 ...

August 5, 2022 · 1 min · jiezi

关于rust:如何在rust中调试结构

转载自集体网站:http://humblelei.com/posts/de... 在编写上面这段简短的代码时: fn main() { let student = Student{ name: "李寻欢".to_string() }; println!("{:?}", student);}struct Student{ name: String}我遇到一些谬误: error[E0277]: `Student` doesn't implement `Debug` --> src\main.rs:6:22 |6 | println!("{:?}", student); | ^^^^^^^ `Student` cannot be formatted using `{:?}`侥幸的是,rust 给了解决这个问题的一些提醒: = help: the trait `Debug` is not implemented for `Student`= note: add `#[derive(Debug)]` to `Student` or manually `impl Debug for Student`最简略的是把 #[derive(Debug)]增加到Student构造上: #[derive(Debug)]struct Student{ name: String}或者参考提醒来手动实现 std::fmt::Debug个性: use std::fmt::{Debug, Formatter, Result};struct Student{ name: String}impl Debug for Student { fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.debug_struct("Student") .field("name", &self.name) .finish() }}别离测试了两种形式,能够失常打印构造。 ...

August 3, 2022 · 1 min · jiezi

关于rust:OpenRaft-在交易撮合引擎中的应用

前言因为工作须要,始终对原子多播利用有十分浓重的趣味。通过一段时间的技术选型。咱们十分侥幸的失去了 Openraft 实操分享 Databend 社区的热心反对。我也想通过咱们的理论工作,对 Openraft 的将来利用尽一些微薄之力。 Openraft 是一个 Raft 的改进版(包含优化选举抵触, 解决网络抖动对 leadership 的影响), 它在 Databend 中为 db, table 等元数据提供分布式存储和强统一读写, 为 databend 的云端数据库集群提供事务性保障. 我的实际的上一篇文章反馈了咱们的选型过程,有趣味的人能够看一下。Raft in Rust (原子多播+撮合引擎)这篇文章更多的是想阐明咱们在应用 OpenRaft 的理论问题,并且通过咱们的实现,揭秘 OpenRaft 的一些机制。 代码仓库大家在应用 OpenRaft 的时候,我置信很多人都查看了手册:Getting Started - openraftThe openraft user guide. 当然,这是一个十分优良的手册。咱们从这个手册里,会学习到如何应用 OpenRaft 实现本人的利用。而且,openraft/example-raft-kv 这个例子的确可能很好的阐明如何实现一个简略的利用。然而,这个例子是应用的内存来做长久化实现。当然内存不会真正做长久化,所以很容易在节点退出后,失落状态。而咱们真正须要的示例是一个可能长久化的例子。 另外一个实例就是 databend/metasrv 而这个示例外面,咱们能够看到一个残缺的 metadata 存储服务的实现。实际上,metasrv 自身是一个相似于 etcd 的 kv 存储。存储整个 databend 集群的 metadata。这个示例外面,metasrv 应用了 sled 作为底层存储。sled 既存储 log,也存储 statemachine 的状态。这个例子,statemachine 所有的更新都间接在 sled 存储里通过 sled 的事物实现了。所以,对于如何存储 snapshot 这个问题,咱们并不太容易看清楚。所以 snapshot 的产生和传递次要是在节点间同步的时候应用。 ...

August 3, 2022 · 5 min · jiezi

关于rust:Rust中的Impls-Traits

✅impls常常被用来定义Rust的structs和enums办法✅ Traits有点儿像OOP语言中的interfaces。它们通常被用来定义必须被提供的功能性。大部分的traits能够为繁多类型实现 然而traits也能够蕴含默认办法实现,在实现类型的时候默认办法能够被重写1、Impl without traits struct Player { first_name: String, last_name: String,}impl Player { fn full_name(&self) -> String { format!("{} {}", self.first_name, self.last_name) }}fn main() { let player_1 = Player { first_name: "Rafael".to_string(), last_name: "Nadal".to_string(), }; println!("Player 01: {}", player_1.full_name());}// ⭐️ Implementation must appear in the same crate as the self type// And also in Rust, new traits can be implemented for existing types even for types like i8, f64 and etc.// Same way existing traits can be implemented for new types you are creating.// But we can not implement existing traits into existing types.Impls & traits,without default methods ...

July 29, 2022 · 2 min · jiezi

关于rust:Rust中的Some

1、首先要晓得什么是Option和Result起源:许多语言应用null/nil/undefined类型来代表空的输入和解决异样谬误。Rust跳过了,特地是避免空指针异样之类的问题,因为异样等起因导致敏感数据透露等等。相同,Rust提供了两个非凡的类枚举:Option和Result就是来解决以上的问题内容: 可选的值要么是Some要么是没有值/NoneResult要么用胜利/Ok要么是失败/Err // An output can have either Some value or no value/ None.enum Option<T> { // T is a generic and it can contain any type of value. Some(T), None,}// A result can represent either success/ Ok or failure/ Err.enum Result<T, E> { // T and E are generics. T can contain any type of value, E can be any error. Ok(T), Err(E),}并且不须要独自引入它们Option的根底用法:在写一个函数或者数据类型的时候: 如果一个函数的参数是可选的如果函数是非空的并且输入的返回可能不是空值如果一个值,活着是一个属性的数据类型可能是空2、咱们不得不应用Option作为它们的数据类型例如,一个函数的输入可能是&str类型或者是输入是空,函数的返回类型能够被设置为 Option<&str> fn get_an_optional_value() -> Option<&str> { //if the optional value is not empty return Some("Some value"); //else None}struct Name { first_name: String, middle_name: Option<String>, // middle_name can be empty last_name: String,}参考:https://learning-rust.github.io/docs/e3.option_and_result.html注:以上是集体学习的过程中翻译的,可能有些翻译不对,请见谅,欢送斧正 ...

July 29, 2022 · 1 min · jiezi

关于rust:Rust-并发安全相关的几个概念下

引言本文介绍 Rust 并发平安相干的几个概念:Send、Sync、Arc,Mutex、RwLock 等之间的分割。这是其中的下篇,次要介绍 Arc,Mutex、RwLock 这几个线程平安相干的类型。 在上一节1中,解说了 Send 和 Sync 这两个线程平安相干的 trait,在此基础上开展其它相干类型的解说。 RcRc 是 Reference Counted(援用计数)的简写,在 Rust 中,这个数据结构用于实现单线程平安的对指针的援用计数。之所以这个数据结构只是单线程平安,是因为在定义中显式申明了并不实现 Send 和 Sync 这两个 trait: #[stable(feature = "rust1", since = "1.0.0")]impl<T: ?Sized> !marker::Send for Rc<T> {}#[stable(feature = "rust1", since = "1.0.0")]impl<T: ?Sized> !marker::Sync for Rc<T> {}个中起因,是因为 Rc 外部的实现中,应用了非原子的援用计数(non-atomic reference counting),因而就不能满足线程平安的条件了。如果要在多线程中应用援用计数,就要应用 Arc 这个类型: Arc与 Rc 不同的是,Arc 外部应用了原子操作来实现其援用计数,因而 Arc 是Atomically Reference Counted(原子援用计数)的简写,能被应用在多线程环境中,缺点是原子操作的性能耗费会更大一些。尽管 Arc 能被用在多线程环境中,并不意味着 Arc<T> 人造就实现了 Send 和 Sync,来看看这两局部的申明: #[stable(feature = "rust1", since = "1.0.0")]unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}#[stable(feature = "rust1", since = "1.0.0")]unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}从申明能够看出:一个 Arc<T> 类型,当且仅当包裹(wrap)的类型 T 满足 Sync 和 Send 时能力被认为是满足 Send 和 Sync 的类型。来做一个试验: #![feature(negative_impls)]use std::sync::Arc;#[derive(Debug)]struct Foo {}impl !Send for Foo {}fn main() {    let foo = Arc::new(Foo {});    std::thread::spawn(move || {        dbg!(foo);    });}在以上的代码中,因为在第 8 行显示申明了 Foo 这个类型不满足 Sync,所以这段代码编译不过,报错信息如下:     = help: the trait `Sync` is not implemented for `Foo`    = note: required because of the requirements on the impl of `Send` for `Arc<Foo>`反之,如果把第 8 行去掉,代码就能编译通过了。于是,这就带来一个问题:Arc 尽管能被用在多线程环境中,但并不是所有Arc<T> 都是线程平安的,如果外面包裹的类型 T 并不满足多线程平安,是不是就不能应用了?解开这个问题的答案请应用 Mutex 类型:Mutex ...

July 27, 2022 · 2 min · jiezi

关于rust:极客专栏打包实时更新

download:极客专栏打包-实时更新剑指 Offer II 115. 重建序列 : 拓扑排序构造题这是 LeetCode 上的 剑指 Offer II 115. 重建序列 ,难度为 中等。Tag : 「图论」、「拓扑排序」、「建图」、「图论 BFS」给定一个长度为 n 的整数数组 nums ,其中 nums 是范畴为 1,n[1,n] 的整数的排列。还提供了一个 2D 整数数组 sequences,其中 sequences[i] 是 nums 的子序列。查看 nums 是否是唯一的最短 超序列 。最短 超序列 是 长度最短 的序列,并且所有序列 sequences[i] 都是它的子序列。对于给定的数组 sequences,可能存在多个无效的 超序列 。 例如,对于 sequences = [[1,2],[1,3]] ,有两个最短的 超序列,[1,2,3] 和 [1,3,2] 。而对于 sequences = [[1,2],[1,3],[1,2,3]],唯一可能的最短 超序列 是 [1,2,3] 。[1,2,3,4] 是可能的超序列,但不是最短的。 如果 nums 是序列的唯一最短 超序列 ,则返回 true ,否则返回 false 。子序列 是一个可能通过从另一个序列中删除一些元素或不删除任何元素,而不改变其余元素的次序的序列。示例 1:输出:nums = [1,2,3], sequences = [[1,2],[1,3]] 输入:false 解释:有两种可能的超序列:[1,2,3]和[1,3,2]。序列 [1,2] 是[1,2,3]和[1,3,2]的子序列。序列 [1,3] 是[1,2,3]和[1,3,2]的子序列。因为 nums 不是唯一最短的超序列,所以返回false。复制代码示例 2:输出:nums = [1,2,3], sequences = [[1,2]] ...

July 25, 2022 · 3 min · jiezi

关于rust:DatenLord|Understanding-Functor-in-Rust

Understanding Functor in RustIn this blog, we introduce the general concept of Functor and Natural Transformations. The blog provides examples of Rust, but we will explain more about its concepts and definitions in the following sections. In mathematics, a functor is a mapping between categories. It's an obscure definition and looks horrible if you don't like math. But don't worry. Let's look at an example. Suppose you have a mapping that plus one. Then if you pass an integer, it will plus it with 1. What if you pass a list of integers? It does not work if we add one to the list directly. However, we could use the map function. ...

July 22, 2022 · 6 min · jiezi

关于rust:Datenlord-Rust-无锁编程之Crossbeam-Epoch算法解析

作者 | 施继成 转自《Rust Magazine中文精选》 上次的文章介绍了无锁数据结构的内存管理机制 EBR,该机制相较于其余的内存管理机制具备更高的执行效率。然而因为理念的复杂性,EBR 的实现并不容易,为每一个无锁数据结构从头实现 EBR 也无必要,因而很天然得大家会思考将 EBR 的核心理念 epoch 抽取进去变成库,让大家可能复用。Crossbeam-epoch 是一套成熟的被大家宽泛应用的 EBR 库,本文将从实现原理局部进行较为具体的解析,并且在此过程中进行。 Guard 只是最外层的壳如前文所述,大家个别在和Crossbeam-epoch 进行交互时仅仅应用 guard,如下所示: /// delete data{ let guard = epoch::pin(); guard.defer(move || mem.release());}/// get data for reading{ let guard = epoch::pin(); let value = map.get(&key, &guard); /// ... Use the value}在读取数据的时候,guard表演的角色仅仅是生命周期守护者,其确保获取进去的data援用(上述代码中的 value)生命周期肯定不长于 guard,当 guard 被销毁时,value 也肯定被销毁。删除数据过程中,guard表演的角色要更简单一些,其负责将销毁函数注册到 defer 提早执行的队列中。至于该销毁函数何时被调用,则须要进一步深刻理解其外部实现细节。 Pin 到底做了什么epoch::pin() 到底做了什么,官网的代码正文中给出了解释,行将以后的 thread pin 住,以便将堆上数据的指针放到栈上。该解释其实只解释了上述读取数据本分的内容,其底层执行的操作如下: 将以后线程注册到 Global 收集器,该注册过程每个线程仅仅做一次。获取以后全局Epoch并设置到以后线程,示意在pin无效的这段时间,以后线程属于哪个Epoch。记录以后线程曾经被pin的次数,当次数达到肯定数量,尝试让 Global 收集器推动 Epoch 增长,回收垃圾。减少 guard_count 计数,记录有多少guard被创立进去且还没有被销毁。因为 pin() 能够重复调用,所以间断两次调用 epoch::pin() 也被容许。只是除了第一次调用,其余的调用都不会有任何作用,仅仅减少了guard_count 计数。具体实现参见 internal.rs 文件中 Local struct 的 pin 办法。 ...

July 21, 2022 · 1 min · jiezi

关于rust:Datenlord-创业公司为什么要选-Rust-做-RDMA-库

嘉宾:施继成编辑:李慧文 RDMA(Remote Direct Memory Access)是近年越来越热门的高速网络传输协定,被广泛应用于超算核心和高端存储畛域,用于缩短网络提早、进步网络带宽。然而 RDMA 的 API 接口十分难以使用,且谬误地应用很容易造成程序谬误甚至数据失落。 跨云存储厂商达坦科技(DatenLord)的联结创始人施继成曾在 Google、微软和阿里巴巴等一线大厂从事操作系统和分布式系统的钻研和开发工作,为了更好地专一于本人喜爱的畛域抉择了守业。同时他也是QCon+案例研习社的讲师,将在极客工夫分享他们在 RDMA 中应用 Rust 的教训。InfoQ有幸采访了他,请他来分享在云原生高性能存储平台方面守业的故事和教训。 InfoQ:您为什么抉择了云原生高性能存储平台这个赛道进行守业呢? 施继成:抉择云原生高性能存储的起因是这个畛域还有比拟多问题亟待解决,用户的应用还不太不便和快捷,比方咱们正在专一的跨云存储畛域现有的相干技术还不够成熟和欠缺。同时这些相干技术又很有深度和难度,这样有挑战性且能给用户提供帮忙的事件就十分吸引我。 从市场角度而言,跨云存储的需求量在最近几年将迎来微小的增长:首先越来越多的客户采纳多云或混合云架构,同时云厂商巨头因为商业利益的起因,在跨云场景不足技术革新的动机,这就激发出一片可观又值得进入的跨云市场。当初有一些守业公司在做离线冷数据的跨云迁徙和备份,然而对于热数据的跨云拜访问题还没有成熟的解决方案,这也正是咱们在尝试获得冲破的赛道。 InfoQ:RDMA 高速网络协议被宽泛应用于古代数据中心,它有什么技术痛点呢? 施继成:RDMA 现阶段曾经失去大家的宽泛认可,然而 RDMA 大规模应用的时候还存在一些技术痛点,例如大规模 RDMA 网络的流量管制、RDMA 利用的内存主动治理、如何让 RDMA 适配广域网场景等等。除了这些技术痛点,老手在接触 RDMA 相干技术时还面临着技术门槛高而导致的上手艰难问题,比方出错信息艰涩,进而导致纠错难之类的问题等等。 InfoQ:为什么您的团队抉择了 Rust 做 RDMA 库呢?Rust 有什么外围个性,吸引了您的团队呢?能介绍下您的团队过后选型语言的思考吗?比方横向比照一下 Rust、C、Go 等热门语言,给读者提供一些语言选型参考呢? 施继成:咱们团队抉择 Rust 语言是看好其在高性能根底软件中的发展势头。当然,咱们也思考过其余编程语言,例如 Go 语言和 C/C++ 语言。 Go 语言在云原生畛域具备统治位置,绝大多数的框架和库都是用 Go 语言实现的,然而 Go 语言的性能并不优异,和 C/C++ 这类语言比还有不小差距,而咱们须要提供的是极致性能的存储产品,所以 Go 语言没有成为咱们的次要编程语言。 C/C++ 性能十分好,也是根底零碎最常应用的语言,然而这两门语言在应用上的规约性较少,程序员很容易写出不自知的 Bug,找出这些问题十分费时费力,因而也会影响零碎的稳定性。 相比之下,Rust 语言在内存平安和多线程安全性方面有语言级别的反对,可能大大减少相干谬误产生的概率;而且其零代价高层形象的个性可能同时满足高性能需要和软件高级别形象的需要。 Rust 语言在我看来就是新时代的 C 语言。连 Linux 内核都开始尝试接管 Rust 语言作为第二门官网编程语言,可见其在根底底层软件开发上的受欢迎水平。 ...

July 20, 2022 · 1 min · jiezi

关于rust:Datenlord-在-Rust-中管理-RDMA-内存

RMDA 是近年越来越热门的高速网络传输协定,被广泛应用于超算核心和高端存储畛域。RDMA 的全称为 Remote Direct Memory Access,即容许本地内存被远端机器间接拜访,该拜访不通过被拜访机器的操作系统,间接由网卡代为实现。正式因为网卡实现了大部分的数据传输工作,操作系统的负载被升高,使得其在大量数据传输的状况下具备更好的拓展性(scalability)。为了保障远端可能正确和平安地拜访本地内存,RDMA 协定中有一系列标准来束缚用户的拜访,上面来简略介绍一下。 RDMA的内存治理远端想要拜访本地内存,首先须要本地的“批准”,即本地仅仅裸露想要裸露的内存,其余内存远端则不可拜访。该“批准”操作,咱们个别称为 Memory Region (简称 MR) 注册,操作系统在收到该申请时会锁住该段申请内存,避免内存被 swap 到硬盘上,同时将这个注册信息告知 RDMA 专用网卡,RDMA 网卡会保留虚拟地址到物理地址的映射。通过此番操作,由 MR 代表的内存裸露进去了,远端能够对其进行拜访。处于平安的思考,只有被容许的远端才能够拜访,这些远端持有远端拜访密钥,即Remote Key(简称 RKey),只有带有正确 RKey 的申请才可能拜访胜利。为了内存治理的细粒度化,RDMA 还提供了 Memory Window(简称 MW),一个 MR 上能够分列出多块 MW,并且每一块 MW 上都能够自定义拜访权限。 除了上述中的 MR 和 MW,RDMA 中的内存治理还和 Protect Domain(简称 PD) 和 Queue Pair (简称 QP) 相干,这里不具体论述这两个概念。下图具体介绍了,这些概念之间的依赖关系: 现有的 RDMA 开发接口,即 InfiniBand Verbs 接口(简称 IBV 接口)并没有显式地展示这种依赖关系,但在理论应用中,任何不按规定程序的资源开释都会造成谬误,而用户找到问题的根本原因则十分艰难。更进一步,当 MR 或者 MW 中的任何内存段被应用时,对应的 MR 和 MW 都不应该被开释或登记,这些在原有的 IBV 接口中也很难规范化。Rust 作为一门内存平安的语言,在解决相似问题上具备人造劣势,接下来咱们来剖析如何用 Rust 解决上述问题。 ...

July 19, 2022 · 2 min · jiezi

关于rust:DatenLord|Rust-for-Linux-要来了这对我们意味着什么

作者 | Tina 转自InfoQ 家喻户晓,Linux 是 C 语言的代言人。然而,时代变了,Rust 正在衰亡并博得越来越多人的反对,它开始逐步表演 Linux 零碎语言的角色。 在往年的 Linux 基金会开源峰会上,Linus Torvalds 提到他心愿看到在 Linux Kernel 5.20 中融入 Rust。内核公布周期个别是 9 到 10 周,这意味着咱们可能会在 8 月初看到 5.19。而后,如果一切顺利的话,咱们将在 10 月下旬或 2022 年 11 月上旬在 5.20 中看到 Rust。而仅在去年,Linus Torvalds 才刚对 Rust 发表过评论,示意本人绝不会推动 Linux 中的 Rust 静止,“Rust 劣势的背地必定存在复杂性,所以我会采取张望的态度,看看这些劣势是否真的见效。” 那么为什么 Rust 会如此快进入到 Linux 内核之中?这对社区、对应用 Linux 和 Rust 的公司来说意味着什么?对解答这些疑难,咱们采访了跨云存储厂商达坦科技(DatenLord)的联结创始人施继成。 采访嘉宾: 施继成,达坦科技(DatenLord)联结创始人兼 CTO,曾供职于 Google、Alibaba 等国内出名科技公司。善于操作系统内核开发、分布式系统、嵌入式零碎,对分布式数据一致性有深刻的钻研。发表多篇操作系统内核相干论文,累计数百次援用。 InfoQ:几年前,有一些声音示意“是时候用 Rust 重写操作系统了”。以您的察看来看,这可能实现吗?为什么? 施继成:如果咱们将“用 Rust 重写操作系统”定义为从零开始搭建一个基于 Rust 语言的操作系统且心愿其可能商业化是不太事实的。起因就在于商业化的操作系统是须要利用场景的,某一个利用场景在相当长的工夫内都会支流风行一个或几个操作系统,不轻易扭转,比方桌面操作系统中的 Windows 和 MacOS,手机操作系统中的 Android 和 iOS,以及服务器操作系统 Linux,BSD 和 Windows Server 等。咱们能够发现这些支流的操作系统是陪伴着该畛域的倒退成长起来的,往往都有长达几十年的历史,一旦造成主导地位不易撼动。 ...

July 19, 2022 · 2 min · jiezi

关于rust:DatenLord|重新思考Rust-Async如何实现高性能IO

作者: 王璞 长期以来,计算机系统IO的速度始终没能跟上CPU速度的晋升,相比而言IO往往成为零碎的性能瓶颈,计算工作期待IO存取数据,成为高性能零碎的一大性能瓶颈。本文先分析IO性能瓶颈的本源,而后举例说明如何解决IO瓶颈,最初简要介绍咱们在高性能IO方面的尝试。 IO性能瓶颈当用户程序执行IO操作时,绝大多数状况下是调用操作系统内核提供的零碎调用来执行IO操作,最常见的IO零碎调用是read和write。在古代计算机体系结构和操作系统的架构下,导致程序IO性能瓶颈次要有三大因素:阻塞、上下文切换、内存拷贝。上面别离简述为什么这三个因素会导致程序性能降落。 阻塞阻塞比拟好了解,比方用户程序调用read零碎调用来读取数据,如果要读取的数据没有筹备好(没有命中缓存),那用户程序就会被阻塞,导致用户程序休眠。等要读的数据加载到零碎态的内存之后,内核再唤醒用户程序来读取数据。 阻塞对用户程序性能最大的影响在于,用户程序会被强制休眠,而且用户程序什么时候被唤醒也无法控制,程序休眠期间什么都不能做。于是阻塞带来了大量的休眠等待时间。如果程序把大量工夫花在阻塞期待IO上,天然IO效率低下,进而导致程序性能受影响。 上下文切换上下文切换是操作系统的基本概念。内核运行在零碎态,用户程序运行在用户态,这么做次要是处于平安的思考,限度用户程序的权限。用户程序调用零碎调用执行IO操作,会产生上下文切换,比方用户程序调用read零碎调用来读取数据,用户程序的上下文被保存起来,而后切换到内核态执行read零碎调用,当read零碎调用执行结束,再切换回用户程序。 上下文切换的代价不小,一方面内核要保留上下文现场,另一方面CPU的流水线也会被上下文切换打断,须要从新加载指令。上下文切换等同一次中断操作,于是零碎调用也被称软中断。频繁的上下文操作对计算机系统带来很大的开销,导致程序执行效率大大降低,进而极大影响程序的性能。 此外,阻塞的时候,肯定会产生上下文切换。还是沿用read操作的例子,用户程序在调用read零碎调用后,内核发现要读的数据没有命中缓存,那用户程序会被强制休眠导致阻塞,内核调度其余程序来运行。然而上下文切换的时候不肯定有阻塞。比方read操作的时候,如果用户程序在调用read零碎调用之后,缓存命中,则read零碎调用胜利返回,把该用户程序的上下文切换回来持续运行。 内存拷贝内存拷贝对程序性能的影响次要源于内存的访问速度跟不上CPU的速度,加之内存的拜访带宽无限,亦称内存墙(Memory Wall)。 当初的CPU频率都是几个GHz,每个CPU指令的执行工夫在纳秒量级。然而CPU拜访内存要花很多工夫,因为CPU收回读取内存的指令后,不是马上能拿到数据,要等一段时间。CPU拜访内存的提早大概在几十纳秒量级,比CPU指令的执行工夫差不多慢一个数量级。 再者,内存的拜访带宽也是无限的,DDR4内存总的带宽大概几十GB每秒。尽管看着不小,然而每个程序在运行时都要拜访内存,不论是加载程序指令,执行计算操作,还是执行IO操作,都须要拜访内存。 当产生内存拷贝时,CPU把数据从内存读出来,再写到内存另外的中央。因为内存拜访提早比CPU指令执行工夫慢很多,再加上内存带宽无限,于是CPU也不是随时能拜访内存,CPU的访存指令会在DDR控制器的队列里排队。因而内存拷贝对于CPU来说是很花工夫的操作,数据没有从内存读出来就不能执行后续写入操作,导致大量CPU期待,使得程序性能降落。 如何实现高性能IO针对下面提到的三种影响IO性能的因素,上面举三个例子,Rust Async,io_uring和RDMA,别离来介绍如何解决这三种影响程序性能的IO问题。 Rust AsyncRust Async异步编程通过协程、waker机制,局部解决了阻塞和上下文切换的问题。 首先,Rust Async采纳协程机制,在某个异步工作被阻塞后,自行切换执行下一个异步工作,一方面防止了工作线程被阻塞,另一方面也防止了工作线程被内核上下文切换。Rust Async底层依附操作系统的异步机制,比方Linux的epoll机制,来告诉IO是否实现,进而唤醒waker来调度异步工作。 然而,Rust Async依然有阻塞。Rust Async里工作线程没有被阻塞,不过被阻塞的是waker,所以Rust Async是把阻塞从工作线程搬到了waker身上。 此外,Rust Async无奈防止上下文切换。Rust Async采纳Reactor的IO形式:比方用户程序要读取数据,发动read异步工作,假设该工作被阻塞放到期待队列,当该工作要读取的数据被内核筹备好之后,该工作被唤醒,持续调用read零碎调用把数据从内核里读到用户内存空间,这次read零碎调用因为要读的数据曾经被内核加载到零碎态内存里,所以不会产生阻塞,然而read零碎调用还会有上下文切换。 Rust Async运行在用户态,而阻塞和上下文切换是操作系统内核决定的。要想进一步防止阻塞和上下文切换,就得在内核上做文章。 io_uringio_uring是Linux提供的原生异步接口,不仅反对异步IO,还能够反对异步零碎调用。io_uring在内核与用户程序之间建设发送队列SQ和实现队列CQ,用户程序把IO申请通过SQ发给内核,而后内核把IO执行结束的音讯通过CQ发给用户程序。采纳io_uring,一方面防止了阻塞,另一方面也防止了上下文切换。 io_uring采纳Proactor的IO形式,Proactor是绝对Reactor而言。比方用户程序采纳io_uring来读取数据,先把read申请放到发送队列SQ,而后用户程序能够去执行其余工作,或者定期轮询实现队列CQ(当然用户程序也能够抉择休眠被异步唤醒,但这样就会有上下文切换,不过这个上下文切换是用户程序自行抉择的)。IO实现的时候,io_uring会把用户程序要读的数据加载到read申请里的buffer,而后io_uring在CQ里放入实现音讯,告诉用户程序IO实现。这样当用户程序收到CQ里的实现音讯后,能够间接应用read申请buffer里的数据,而不须要再调用read零碎调用来加载数据。 所以io_uring通过内核的反对,能够实现无阻塞和无上下文切换,进一步晋升了IO的性能。然而io_uring还无奈防止内存拷贝,比方read操作的时候,数据是先从IO设施读到内核空间的内存里,而后内核空间的数据再在复制到用户空间的内存。内核这么做是出于平安和简化IO的思考。然而要想防止内存拷贝,那就得实现内核旁路(kernel bypass),防止内核参加IO。 RDMARDMA是罕用于超算核心、高端存储等畛域的高性能网络计划。RDMA须要非凡的网卡反对,RDMA网卡具备DMA性能,能够实现RDMA网卡间接拜访用户态内存空间。在RDMA网卡和用户态内存之间的数据传输(即数据通路),齐全不须要CPU参加,更无需内核参加。用户程序通过RDMA传输数据时,是调用RDMA的用户态library接口,而后间接和RDMA网卡打交道。所以RDMA传输数据的整个数据通路是在用户态实现,没有内核参加,既没有阻塞也没有上下文切换,更没有内存拷贝,因而采纳RDMA能够取得十分好的网络IO性能。 尽管RDMA通过内核旁路防止了阻塞、上下文切换和内存拷贝,实现了高性能网络IO,然而RDMA也是有代价的。首先,RDMA编程复杂度大大提高,RDMA有本人的编程接口,不再采纳内核提供的socket接口,RDMA的接口偏底层,而且调试不够敌对。另外,用户程序采纳RDMA之后要自行治理内存,保障内存平安,防止竞争拜访:比方用户要通过RDMA网路发送数据,在数据没有发送实现前,用户程序要保障寄存待发送数据的用户内存空间不能被批改,不然会导致发送的数据谬误,而且即使用户程序在曾经开始发送但还没有发送实现前批改了待发送的数据,RDMA也不会报错,因为RDMA的用户态library也无法控制用户程序的内存空间来保证数据一致性。这极大地减少了用户程序的开发难度。比照内核执行写操作,用户程序调用write零碎调用之后,内核把待写的数据先缓存在内核空间的内存,而后就能够告诉用户程序写操作实现,回头内核再把写数据写入设施。尽管内核有做内存拷贝,然而保障了数据一致性,,也升高了用户程序执行IO操作的开发复杂度。 咱们的尝试DatenLord的指标是打造高性能分布式存储系统,咱们在开发DatenLord的过程中,始终在摸索如何实现高性能IO。 尽管Rust Async异步编程理念十分不错,用相似同步IO语意实现异步IO。然而咱们认为Rust Async更多是异步IO的编程框架,还称不上是高性能IO框架。于是咱们尝试把Rust Async跟io_uring和RDMA联合,以实现高性能IO。 首先,Rust Async与io_uring的联合工作,尽管Rust社区在这方面也有不少相似的尝试,然而咱们的重点是如何在io_uring执行异步IO的时候防止内存拷贝,这方面Rust社区的工作还很少。咱们尝试采纳Rust的ownership机制来避免用户程序批改提交给io_uring用于执行IO操作的用户态内存,一方面防止内存拷贝,一方面保障内存平安。感兴趣的敌人能够看下ring-io。 另外,咱们也在尝试联合Rust Async与RDMA,这方面Rust社区的工作不多。RDMA性能虽好,然而开发复杂度很大,而且调试不敌对。咱们尝试采纳Rust friendly的形式来实现RDMA接口的异步封装,同时解决RDMA程序须要开发者自行治理内存的问题,从而大大降低采纳Rust开发RDMA程序的难度。感兴趣的敌人能够看下async-rdma。 最初,欢送对高性能IO感兴趣的敌人们分割咱们,跟咱们一起交换探讨。 咱们的联系方式:dev@datenlord.io

July 19, 2022 · 1 min · jiezi

关于rust:DatenLord-Rust-实现K8S调度扩展

背景介绍K8S调度器(kube-scheduler)是K8S调度pod的控制器,它作为K8S外围组件运行。调度器基于肯定的调度策略为pod找到适合的运行节点。 调度流程K8S调度器调度一个pod时候次要分为三个阶段 过滤阶段:调用一系列predicate函数或者叫filter函数过滤掉不适合的节点,比如说某些节点上不满足pod申明的运行所须要的资源,如CPU,内存等资源,那么这些节点会在这个阶段被过滤掉。打分阶段:调用一系列priority函数或者叫score函数给通过第一步过滤的节点打分排序。比方有三个节点通过了过滤阶段,当三个节点通过资源平衡函数的打分,那么最终残余CPU,内存等资源更多的节点会取得更高的优先级评分。调度阶段:把pod调度到抉择优先级最高的节点上调度过程如下图所示: 调度算法前文提到,K8S调度器会调用一系列filter函数和priority函数,这些函数是K8S内置的调度算法, K8S会依据默认的调度算法将pod调度到最合适的节点上。filter函数的目标是过滤掉不合乎pod要求的节点,通常会有多个节点通过filter阶段,prioriry函数的目标就是在剩下的节点中选出最合适的节点。 咱们来介绍一下K8S默认的调度策略有哪些。 filter策略:  PodFitsResources: 这条策略是过滤掉所剩资源不满足pod要求的节点MatchNodeSelector: 这条策略是过滤掉不匹配pod nodeSelector要求的节点PodFitsHostPorts: 这条策略是过滤掉pod申明的HostPort曾经被占用的节点等等priority策略:  BalancedResourceAllocation: 这条策略心愿当pod被调度到一个节点后CPU,内存使用率是平衡的。LeastRequestedPriority: 这条策略基于节点的闲暇局部,闲暇局部根本算法就是(节点总容量 - 已有pod的申请 - 将要被调度的pod申请)/ 节点总容量,有更多的闲暇局部的节点会取得更高的优先级。等等K8S提供了很多调度策略,咱们在这里就不一一列举,K8S并不会应用所有的这些调度策略,它会默认应用局部调度策略,咱们能够通过K8S配置文件来组合应用这些策略来达到最合乎咱们利用场景的调度策略。 调度扩大前文中介绍到K8S会提供很多调度策略,它们很大水平上容许咱们管制K8S调度器的行为,然而K8S提供的调度策略也有它的局限性,它只能依据通用的规范如CPU,内存的使用率来设计调度策略,当咱们的利用须要更有针对性的调度策略时,比如说咱们想把一个pod调度到网路带宽更高,提早更低的节点上,这时候K8S提供的调度策略很难满足咱们的需要。侥幸的是K8S提供了K8S调度扩大机制。K8S调度扩大提供给用户扩大调度策略的办法。K8S调度扩大容许用户提供定制的predicate/filter函数和priority/score函数来扩大的调度策略。调度扩大的实现形式是用户提供一个web服务,并将web服务的url通过配置文件告诉K8S,K8S会在调度pod的过滤阶段和打分阶段通过RESTful API的POST办法来调用用户提供的自定义扩大函数,从而达到扩大K8S调度策略的成果。具体架构如下图所示: 在K8S过滤阶段,kube-scheculer发送 POST ${URL}/filter到scheduler-extender,申请中蕴含Json格局序列化的数据ExtenderArgs,scheduler-extender收到申请后,通过本地自定义的filter函数,产生filter后果ExtenderFilterResult并序列化成Json格局返回。在打分阶段,kube-scheculer发送 POST ${URL}/priority到scheduler-extender,申请中蕴含Json格局序列化的数据ExtenderArgs,scheduler-extender收到申请后,通过本地自定义的priority函数,产生score后果List<HostPriority>并序列化成Json格局返回。 数据结构如上所示,K8S在和用户调度扩大交互的过程中波及到三个数据结构,K8S应用go语言来定义它们,在通过http发送的时候会把它们序列化成Json格局。在Rust实现的调度扩大中需用将这些数据结构用Rust语言定义,并进行序列化和反序列化。 调度扩大申请这个数据结构是K8S发送的调度扩大申请,filter和priority申请的构造是雷同的。go语言定义如下: type ExtenderArgs struct { // Pod being scheduled Pod *v1.Pod // List of candidate nodes where the pod can be scheduled; to be populated // only if Extender.NodeCacheCapable == false Nodes *v1.NodeList // List of candidate node names where the pod can be scheduled; to be // populated only if Extender.NodeCacheCapable == true NodeNames *[]string}Pod示意须要调度的podNodes示意候选的节点列表NodeNames示意候选的节点名字列表这里须要留神的是Nodes和NodeNames只有一个会被填写,所以在Rust语言中须要将这两个域定义成Option,Rust的定义如下: ...

July 19, 2022 · 3 min · jiezi

关于rust:Datenlord-Rust实现RDMA异步编程一基于epoll实现RDMA-异步操作

RDMA是一套高性能网络协议栈,多用于高性能计算、高性能存储畛域。RDMA的library是用C实现的,然而没有很好用的Rust的binding,不不便Rust开发者应用。于是咱们正在封装一层合乎Rust格调、便于Rust开发者应用的RDMA Rust binding。特地的,异步编程是近几年很受关注的编程形式,用Rust异步编程来实现IO操作,能够防止操作系统的过程上下文切换,进步性能,而且Rust的异步编程框架也在逐渐成熟和欠缺。本系列文章探讨下如何用异步的形式实现RDMA的操作。本文先探讨下如何基于Linux的epoll机制实现RDMA异步操作,后续的文章再探讨如何用Rust异步编程来实现RDMA异步操作。 RDMA操作简介RDMA的编程模型是基于音讯的形式来实现网络传输,并且用队列来治理待发送的音讯和接管到的音讯。RDMA的网络传输相干操作基本上都是跟队列相干的操作:比方把要发送的音讯放入发送队列,音讯发送实现后在实现队列里放一个发送实现音讯,以供用户程序查问音讯发送状态;再比方接管队列里收到音讯,也要在实现队列里放个接管实现音讯,以供用户程序查问有新音讯要解决。 由下面的形容能够看出RDMA的队列分为几种:发送队列Send Queue (SQ),接管队列Receive Queue(RQ),和实现队列Completion Queue (CQ)。其中SQ和RQ统称工作队列Work Queue (WQ),也称为Queue Pair (QP)。此外,RDMA提供了两个接口,ibv_post_send和ibv_post_recv,由用户程序调用,别离用于发送音讯和接管音讯: 用户程序调用ibv_post_send把发送申请Send Request (SR)插入SQ,成为发送队列的一个新的元素Send Queue Element (SQE);用户程序调用ibv_post_recv把接管申请Receive Request (RR)插入RQ,成为接管队列的一个新元素Receive Queue Element (RQE)。SQE和RQE也统称工作队列元素Work Queue Element (WQE)。 当SQ里有音讯发送实现,或RQ有接管到新音讯,RDMA会在CQ里放入一个新的实现队列元素Completion Queue Element (CQE),用以告诉用户程序。用户程序有两种同步的形式来查问CQ: 用户程序调用ibv_cq_poll来轮询CQ,一旦有新的CQE就能够及时失去告诉,然而这种轮询形式很耗费CPU资源;用户程序在创立CQ的时候,指定一个实现事件通道ibv_comp_channel,而后调用ibv_get_cq_event接口期待该实现事件通道来告诉有新的CQE,如果没有新的CQE,则调用ibv_get_cq_event时产生阻塞,这种办法比轮询要节俭CPU资源,然而阻塞会升高程序性能。对于RDMA的CQE,有个须要留神的中央:对于RDMA的Send和Receive这种双边操作,发送端在发送实现后能收到CQE,接收端在接管实现后也能收到CQE;对于RDMA的Read和Write这种单边操作,比方节点A从节点B读数据,或节点A往节点B写数据,只有发动Read和Write操作的一端,即节点A在操作完结后能收到CQE,另一端节点B齐全不会感知到节点A发动的Read或Write操作,节点B也不会收到CQE。 Linux epoll异步机制简介Linux的epoll机制是Linux提供的异步编程机制。epoll专门用于解决有大量IO操作申请的场景,查看哪些IO操作就绪,使得用户程序不用阻塞在未就绪IO操作上,而只解决就绪IO操作。epoll比Linux之前的select和poll这两种异步机制要弱小,epoll特地适宜有大量IO操作的场景,比方RDMA的场景,每个RDMA节点同时有很多队列,用于大量传输数据,那么就能够用epoll来查问每个CQ,及时取得RDMA音讯的发送和接管状况,同时防止同步形式查问CQ的毛病,要么用户程序耗费大量CPU资源,要么用户程序被阻塞。 Linux的epoll机制提供了三个API接口: epoll_create用于创立epoll实例,返回epoll实例的句柄;epoll_ctl用于给epoll实例减少、批改、删除待查看的IO操作事件;epoll_wait用于查看每个通过epoll_ctl注册到epoll实例的IO操作,看每个IO操作是否就绪/有冀望的事件产生。具体的epoll这三个接口的应用,前面联合代码示例来解说。这里先解释下epoll的IO事件查看规定。如下图所示,epoll有两种查看规定:边际触发Edge Trigger (ET),和电平触发Level Trigger (LT)。边际触发和电平触发源自信号处理畛域。边际触发指信号一发生变化就触发事件,比方从0变到1就触发事件、或者从1到0就触发事件;电平触发指只有信号的状态处于特定状态就触发事件,比方高电平就始终触发事件,而低电平不触发事件。 对应到epoll,电平触发指的是,只有IO操作处于特定的状态,就会始终告诉用户程序。比方当socket有数据可读时,用户程序调用epoll_wait查问到该socket有收到数据,只有用户程序没有把该socket上次收到的数据读完,每次调用epoll_wait都会告诉用户程序该socket有数据可读;即当socket处于有数据可读的状态,就会始终告诉用户程序。而epoll的边际触发指的是epoll只会在IO操作的特定事件产生后告诉一次。比方socket有收到数据,用户程序epoll_wait查问到该socket有数据可读,不论用户程序有没有读完该socket这次收到的数据,用户程序下次调用epoll_wait都不会再告诉该socket有数据可读,除非这个socket再次收到了新的数据;即仅当socket每次收到新数据才告诉用户程序,并不关怀socket以后是否有数据可读。 RDMA实现队列CQ读取CQE的同步和异步办法本节用RDMA读取CQ的操作为例展现如何基于epoll实现异步操作。先介绍下RDMA用轮询和阻塞的形式读取CQ,再介绍基于epoll的异步读取CQ的办法。下文的代码仅作为示例,并不能编译通过。 RDMA轮询形式读取CQERDMA轮询形式读取CQ非常简单,就是不停调用ibv_poll_cq来读取CQ里的CQE。这种形式可能最快取得新的CQE,间接用户程序轮询CQ,而且也不须要内核参加,然而毛病也很显著,用户程序轮询耗费大量CPU资源。 loop { // 尝试读取一个CQE poll_result = ibv_poll_cq(cq, 1, &mut cqe); if poll_result != 0 { // 解决CQE }}RDMA实现事件通道形式读取CQERDMA用实现事件通道读取CQE的形式如下: 用户程序通过调用ibv_create_comp_channel创立实现事件通道;接着在调用ibv_create_cq创立CQ时关联该实现事件通道;再通过调用ibv_req_notify_cq来通知CQ当有新的CQE产生时从实现事件通道来告诉用户程序;而后通过调用ibv_get_cq_event查问该实现事件通道,没有新的CQE时阻塞,有新的CQE时返回;接下来用户程序从ibv_get_cq_event返回之后,还要再调用ibv_poll_cq从CQ里读取新的CQE,此时调用ibv_poll_cq一次就好,不须要轮询。RDMA用实现事件通道读取CQE的代码示例如下: // 创立实现事件通道let completion_event_channel = ibv_create_comp_channel(...);// 创立实现队列,并关联实现事件通道let cq = ibv_create_cq(completion_event_channel, ...);loop { // 设置CQ从实现事件通道来告诉下一个新CQE的产生 ibv_req_notify_cq(cq, ...); // 通过实现事件通道查问CQ,有新的CQE就返回,没有新的CQE则阻塞 ibv_get_cq_event(completion_event_channel, &mut cq, ...); // 读取一个CQE poll_result = ibv_poll_cq(cq, 1, &mut cqe); if poll_result != 0 { // 解决CQE } // 确认一个CQE ibv_ack_cq_events(cq, 1);}用RDMA实现事件通道的形式来读取CQE,实质是RDMA通过内核来告诉用户程序CQ里有新的CQE。事件队列是通过一个设施文件,/dev/infiniband/uverbs0(如果有多个RDMA网卡,则每个网卡对应一个设施文件,序号从0开始递增),来让内核通过该设施文件告诉用户程序有事件产生。用户程序调用ibv_create_comp_channel创立实现事件通道,其实就是关上上述设施文件;用户程序调用ibv_get_cq_event查问该实现事件通道,其实就是读取关上的设施文件。然而这个设施文件只用于做事件告诉,告诉用户程序有新的CQE可读,但并不能通过该设施文件读取CQE,用户程序还要是调用ibv_poll_cq来从CQ读取CQE。 ...

July 18, 2022 · 2 min · jiezi

关于rust:Datenlord-Rust实现RDMA异步编程二async-Rust-封装-UCX-通信库

UCX 是一个高性能网络通信库,它作为 MPI 所依赖的通信模块之一在高性能计算畛域失去宽泛的应用。UCX 应用 C 语言编写,为了在 Rust 我的项目中应用它,咱们须要将它的 C 接口包装成 Rust 库。在这个过程中咱们充分利用了 Rust 的杀手级个性—— async-await 协程来包装异步 IO 接口,从而极大升高了利用的编程复杂度。去年咱们用 Rust 实现的高性能分布式文件系统 MadFS,底层就应用了咱们本人包装过的 UCX 作为通信模块,它在大规模 RDMA 网络上展现出了良好的性能。UCX 官网在得悉这一音讯后也很开心地宣传了咱们这个我的项目 : ) 本文首先会介绍一下 UCX 通信库的性能和编程模型,而后介绍咱们用 async Rust 封装 UCX 的过程,具体代码能够参考 GitHub 仓库:async-ucx。值得注意的是,这里介绍的 IO 模型和封装异步 IO 的办法是通用的,能够实用到其它 IO 库当中。 UCX 通信接口简介UCX 的全称是 Unified Communication X。正如它名字所展现的,UCX 旨在提供一个对立的形象通信接口,可能适配任何通信设施,并反对各种利用的需要。下图是 UCX 官网提供的架构图: 能够看到,UCX 整体分为两层:下层的 UCP 接口和底层的 UCT 接口。 底层的 UCT 适配了各种通信设施:从单机的共享内存,到罕用的 TCP Socket,以及数据中心罕用的 RDMA 协定,甚至新兴的 GPU 上的通信,都有很好的反对。 ...

July 18, 2022 · 6 min · jiezi

关于rust:Datenlord-Rust-语言无锁数据结构的内存管理

无锁数据结构内存治理正如大家所熟知的,无锁数据结构在并发拜访中往往具备更好的拜访效率和并发度。无锁数据结构的性能劣势次要来自于以下两点: 1、数据结构的锁设计往往比拟粗粒度,在很多能够并发拜访的状况下,访问者被锁阻塞,无奈实现并发拜访。 2、无锁数据结构拜访不须要进行上下文切换,有锁数据结构在并发度高的时候往往会触发操作系统上下文切换。 然而无锁数据结构也带来了新的问题,即内存治理问题。举个例子:当线程 A 读取一块数据的时候,线程 B 要开释该数据块。在有锁数据结构中,这两个操作被串行了起来;无锁数据结构因为不足锁的爱护,这两个操作可能同时进行。为了保障线程 A 拜访数据的正确性,线程 B 的开释操作必须要延后执行,直到 A 实现了读取操作。为了达到上述延后开释内存的目标,大家个别采纳下列的几种办法: 1、语言自身的 GC 反对,如带有虚拟机 runtime 的语言,如 Java。2、援用计数(Reference Count)。3、基于代际的内存开释机制(Epoch-Based Reclamation),本文之后简称EBR。 语言自身的 GC 机制一方面有语言的限度,另外一方面全局的 GC 往往会造成肯定的性能损失,程序执行Latency不稳固。援用计数自身的性能开销不可漠视,特地是在读取操作较多的场景下,仅仅为了爱护数据安全,每次读取都须要进行计数减少,读完了再进行计数缩小,高并发的状况下效率不乐观。EBR则躲避了上述问题,一方面不须要语言层面的规约,另外一方面执行效率也绝对更好。这里为大家简略介绍一下 EBR, 更加具体的解释请参见论文《 Practical lock-freedom 》。 Epoch-Based Reclamation在 EBR 的概念中有代际(Epoch)的概念,Epoch 为数字,其代表了以后处于第几世代,该数字枯燥递增。全局具备一个Global Epoch, 代表全局以后是第几世代。每个线程的每次数据结构的拜访都蕴含一个Epoch,即Local Epoch,示意以后线程处在第几代。有了这些概念咱们来看一下上面的例子,就可能了解 EBR 的工作原理了。 如下图中的例子,线程 A 和 B 并发地拜访无锁数据中的内存块,自上而下为工夫的流逝方向。在工夫点 1 之前 Global Epoch 为 0。 工夫节点1:线程 A 发现没有其余线程正在发给拜访该数据结构,将Global Epoch 加 1,变成 1。同时线程 A Local Epoch 设置为 1. 工夫节点2:线程 B 删除数据块 M,因为 B 发现只有线程 A 在拜访数据结构,且 A 的Epoch 和 Global Epoch相等,都是1。线程 B 将 Global Epoch 再加 1,变成 2。B 线程 Local Epoch 和 Global Epoch 同步,也为 2. 因为 Epoch 的删除操作是延后的,须要放到一个收集器里,于是数据块 M 被放到收集器中,标记为 Epoch 1,意味着这个数据只有可能在Epoch 1中被应用,从 Epoch 2 开始数据结构中在没有数据块M(被线程 B 删除)。 ...

July 18, 2022 · 2 min · jiezi