精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

更快的tsv解析代碼分享

jf_wN0SrCdH ? 來源:Rust語言中文社區(qū) ? 2023-12-29 09:45 ? 次閱讀

最近在B站沖浪時發(fā)現(xiàn)一個 Rust 和 Go 解析 tsv 文件的視頻, 作者需要解析使用get-NetTCPConnection | Format-Table -Property LocalAddress,LocalPort,RemoteAddress,RemotePort,State,OwningProcess獲取的本地所有 TCP 連接信息, 文件輸出大致如下

LocalAddressLocalPortRemoteAddressRemotePortStateOwningProcess
--------------------------------------------------------------
192.168.1.454339104.210.1.98443Established4504

視頻作者使用 regex 正則庫處理輸出, 發(fā)現(xiàn)比 Go 版本慢, 優(yōu)化后雖然比 Go 快, 但并沒有領先多少, 于是我自己嘗試使用別的優(yōu)化方法, 解析耗時能優(yōu)化使用正則解析的 10% 左右. 下面來看看我的優(yōu)化過程.

?更快的 tsv 解析[1]

?項目搭建[2]

?regex 解析[3]

?減少內存分配[4]

?使用 ascii 正則[5]

?拋棄 regex[6]

?手寫解析狀態(tài)機[7]

?SIMD 加速?[8]

?總結[9]

項目搭建

進行性能時建議使用criterion[10], 它幫我們解決了性能的內存預加載, 操作耗時, 性能記錄, 圖表輸出等功能.

cargonew--libtsv
cdtsv
cargoaddcriterion--dev-Fhtml_reports
cargoaddregex

然后在 Cargo.toml 里添加如下bench 文件

[[bench]]
name="parse"
harness=false
//benches/parse.rs
#![allow(dead_code)]
usecriterion::{black_box,criterion_group,criterion_main,Criterion};

constOUTPUT:&str=include_str!("net.tsv");

fncriterion_benchmark(c:&mutCriterion){
todo!()
}

criterion_group!(benches,criterion_benchmark);
criterion_main!(benches);

測試使用的 tsv 一共 380 行.

regex 解析

使用正則解析的正則表達式很簡單, 這里直接給代碼, 為了避免重復編譯正則表達式和重新分配內存報錯結果列表, 這里將她們作為參數(shù)傳給解析函數(shù).

structOwnedRecord{
local_addr:String,
local_port:u16,
remote_addr:String,
remote_port:u16,
state:String,
pid:u64,
}
fnregex_owned(input:&str,re:®ex::Regex,result:&mutVec){
input.lines().for_each(|line|{
ifletSome(item)=re.captures(line).and_then(|captures|{
let(_,[local_addr,local_port,remote_addr,remote_port,state,pid])=
captures.extract();
letret=OwnedRecord{
local_addr:local_addr.to_string(),
local_port:local_port.parse().ok()?,
remote_addr:remote_addr.to_string(),
remote_port:remote_port.parse().ok()?,
state:state.to_string(),
pid:pid.parse().ok()?,
};
Some(ret)
}){
result.push(item);
}
});
assert_eq!(result.len(),377);
}

parse.rs 文件里要加上使用的正則和提前創(chuàng)建好列表, 并且將函數(shù)添加的 bench 目標里

fncriterion_benchmark(c:&mutCriterion){
letre=regex::new(r"(S+)s+(d+)s+(S+)s+(d+)s+(S+)s+(d+)").unwrap();
letmutr1=Vec::with_capacity(400);
c.bench_function("regex_owned",|b|{
b.iter(||{
//重置輸出vector
r1.clear();
regex_owned(black_box(OUTPUT),&re,&mutr1);
})
});
}

接著跑cargo bench --bench parse進行測試, 在我的電腦上測得每次運行耗時 450 μs 左右.

減少內存分配

一個最簡單的優(yōu)化是使用&str以減少每次創(chuàng)建String帶來的內存分配和數(shù)據(jù)復制.

structRecord<'a>{
local_addr:&'astr,
local_port:u16,
remote_addr:&'astr,
remote_port:u16,
state:&'astr,
pid:u64,
}

兩個函數(shù)代碼差不多, 所以這里不再列出來, 可以通過gits: tsv 解析[11]獲取完整代碼.

可惜這次改動帶來的優(yōu)化非常小, 在我的電腦上反復測量, 這個版本耗時在 440 μs 左右.

使用 ascii 正則

rust 的 regex 正則默認使用 unicode, 相比于 ascii 編碼, unicode 更復雜, 因此性能也相對較低, 剛好要解析的內容都是ascii字符, 使用 ascii 正則是否能提升解析速度呢? regex 有regex::bytes模塊用于 ascii 解析, 但為了適配字段, 這里不得不使用transmute將&[u8]強制轉換成&str

fncast(data:&[u8])->&str{
unsafe{std::transmute(data)}
}
fnregex_ascii<'a>(input:&'astr,re:®ex::Regex,result:&mutVec>){
input.lines().for_each(|line|{
ifletSome(item)=re.captures(line.as_bytes()).and_then(|captures|{
let(_,[local_addr,local_port,remote_addr,remote_port,state,pid])=
captures.extract();
letret=Record{
local_addr:cast(local_addr),
local_port:cast(local_port).parse().ok()?,
remote_addr:cast(remote_addr),
remote_port:cast(remote_port).parse().ok()?,
state:cast(state),
pid:cast(pid).parse().ok()?,
};
Some(ret)
}){
result.push(item);
}
});
assert_eq!(result.len(),377);
}

添加到 bench 后性能大概多少呢?, 很遺憾, 性能與 regex_borrow 差不多, 在 430 μs 左右.

拋棄 regex

鑒于內容格式比較簡單, 如果只使用 rust 內置的 split 等方法解析性能會不會更好呢? 解析思路很簡單, 使用lines得到一個逐行迭代器, 然后對每行使用 split 切分空格再逐個解析即可

fnsplit<'a>(input:&'astr,result:&mutVec>){
input
.lines()
.filter_map(|line|{
letmutiter=line.split(['','	','
']).filter(|c|!c.is_empty());
letlocal_addr=iter.next()?;
letlocal_port:u16=iter.next()?.parse().ok()?;
letremote_addr=iter.next()?;
letremote_port:u16=iter.next()?.parse().ok()?;
letstate=iter.next()?;
letpid:u64=iter.next()?.parse().ok()?;
Some(Record{
local_addr,
local_port,
remote_addr,
remote_port,
state,
pid,
})
})
.for_each(|item|result.push(item));
assert_eq!(result.len(),377);
}

注意line.split只后還需要過濾不是空白的字符串, 這是因為字符串"a b"split 之后得到["a", "", "b"].

經測試, 這個版本測試耗時大概為 53 μs, 這真是一個巨大提升, rust 的 regex 性能確實有些問題.

每次 split 之后還需要 filter 感覺有些拖沓, 剛好有個split_whitespace[12], 換用這個方法, 將新的解析方法命名為split_whitespace后再測試下性能

letmutiter=line.split_whitespace();

令人意想不到的是性能居然倒退了, 這次耗時大概 60 μs, 仔細研究下來還是 unicode 的問題, 改用 ascii 版本的split_ascii_whitespace之后性能提升到 45 μs.

手寫解析狀態(tài)機

除了上述的方法, 我還嘗試將 Record 的 local_addr 和 remote_addr 改成std::IpAddr, 消除next()?.parse().ok()?等其他方法, 但收益幾乎沒有, 唯一有作用的辦法是手寫解析狀態(tài)機.

大致思路是, 對于輸出來說, 我們只關系它是以下三種情況

1.換行符 NL

2.除了換行符的空白符 WS

3.非空白字符 CH

只解析 LocalAddr 和 LocalPort 解析狀態(tài)機如下, 如果要解析更多字段, 按順序添加即可.

094b06a8-a585-11ee-8b88-92fbcf53809c.png

因為代碼有些復雜, 所以這里不再貼出來, 完整代碼在 gits 上. 手寫狀態(tài)機的版本耗時大概在 32 μs 左右. 這版本主要性能提升來自手寫狀態(tài)機減少了循環(huán)內的分支判斷.

SIMD 加速?

在上面手寫解析的例子里, 處理過程類似與將輸出作為一個 vec, 狀態(tài)機作為另一個 vec, 將兩個 vec 進行某種運算后輸出結果, 應該能使用 simd 進行加速, 但我還沒想出高效實現(xiàn). 所以這里只給出可能的參考資料

1.zsv[13]使用 simd 加速的 csv 解析庫

2.simd base64[14]一篇介紹使用 simd 加速 base64 解析的博客, 非常推薦

總結

rust regex 在某時候確實存在性能問題, 有時候使用簡單的 split 的方法手動解析反而更簡單性能也更高, 如果情況允許, 使用 ascii 版本能進一步提升性能, 如果你追求更好的性能, 手寫一個狀態(tài)不失為一種選擇, 當然我不建議在生產上這么做. 同時我也期待有 simd 加速的例子.

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • TCP
    TCP
    +關注

    關注

    8

    文章

    1349

    瀏覽量

    78986
  • 函數(shù)
    +關注

    關注

    3

    文章

    4304

    瀏覽量

    62429
  • 內存分配
    +關注

    關注

    0

    文章

    16

    瀏覽量

    8295

原文標題:更快的 tsv 解析

文章出處:【微信號:Rust語言中文社區(qū),微信公眾號:Rust語言中文社區(qū)】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    TSV工藝流程與電學特性研究

    本文報道了TSV過程的細節(jié)。還顯示了可以在8-in上均勻地形成許多小的tsv(直徑:6 m,深度:22 m)。通過這種TSV工藝的晶片。我們華林科納研究了TSV的電學特性,結果表明
    發(fā)表于 06-16 14:02 ?3314次閱讀
    <b class='flag-5'>TSV</b>工藝流程與電學特性研究

    請問有TSV6390AIDT和/或TSV6290AIDT的SPICE型號嗎?

    你有TSV6390AIDT和/或TSV6290AIDT的SPICE型號嗎? 謝謝, 何魯麗 #運算放大器,香料宏模型
    發(fā)表于 08-06 14:07

    硅通孔(TSV)電鍍

    硅通孔(TSV)電鍍的高可靠性是高密度集成電路封裝應用中的一個有吸引力的熱點。本文介紹了通過優(yōu)化濺射和電鍍條件對完全填充TSV的改進。特別注意具有不同種子層結構的樣品。這些樣品是通過不同的濺射和處理
    發(fā)表于 01-09 10:19

    C++的G代碼解析算法研究

    在數(shù)控技術發(fā)展過程中,G 代碼解析優(yōu)劣是促進數(shù)控技術的發(fā)展因素之一。但目前的解析算法,并不能更高效的進行解析處理。經過對G 代碼進行分析,
    發(fā)表于 07-21 16:36 ?0次下載

    軌到軌輸入/輸出20 MHz的運算放大器TSV991/TSV992/TSV994

    The TSV99x and TSV99xA family of single, dual, and quad operational amplifiers offers low voltage
    發(fā)表于 09-04 14:51 ?12次下載
    軌到軌輸入/輸出20 MHz的運算放大器<b class='flag-5'>TSV</b>991/<b class='flag-5'>TSV</b>992/<b class='flag-5'>TSV</b>994

    通用輸入/輸出軌到軌低功耗操作放大器TSV321/TSV358/TSV324/TSV321A/TSV358A/TSV324A

    The TSV358, TSV358A, TSV324, and TSV324A (dual and quad) devices are low voltage versions of
    發(fā)表于 09-05 09:12 ?6次下載
    通用輸入/輸出軌到軌低功耗操作放大器<b class='flag-5'>TSV</b>321/<b class='flag-5'>TSV</b>358/<b class='flag-5'>TSV</b>324/<b class='flag-5'>TSV</b>321A/<b class='flag-5'>TSV</b>358A/<b class='flag-5'>TSV</b>324A

    微(60μ一)寬的帶寬(2.4 MHz)的CMOS運算放大器TSV6390/TSV6390A/TSV6391/TSV6391A

    The TSV6390, TSV6391, and their “A” versions are single operational amplifiers (op amps) offering
    發(fā)表于 09-05 09:34 ?4次下載
    微(60μ一)寬的帶寬(2.4 MHz)的CMOS運算放大器<b class='flag-5'>TSV</b>6390/<b class='flag-5'>TSV</b>6390A/<b class='flag-5'>TSV</b>6391/<b class='flag-5'>TSV</b>6391A

    高功因數(shù)(1.15兆赫為45微米)cmos運算放大器TSV521/TSV522/TSV524/TSV521A/TSV522A/TSV524A

    The TSV52x and TSV52xA series of operational amplifiers offer low voltage operation and rail-torail
    發(fā)表于 09-05 09:52 ?5次下載
    高功因數(shù)(1.15兆赫為45微米)cmos運算放大器<b class='flag-5'>TSV</b>521/<b class='flag-5'>TSV</b>522/<b class='flag-5'>TSV</b>524/<b class='flag-5'>TSV</b>521A/<b class='flag-5'>TSV</b>522A/<b class='flag-5'>TSV</b>524A

    軌到軌輸入/輸出60μ880千赫5V CMOS運算放大器TSV630/TSV630A/TSV631/TSV631A

    The TSV630 and TSV631 devices are single operational amplifiers offering low voltage, low power operation, and rail-to-rail input and ou
    發(fā)表于 09-05 10:04 ?16次下載
    軌到軌輸入/輸出60μ880千赫5V CMOS運算放大器<b class='flag-5'>TSV</b>630/<b class='flag-5'>TSV</b>630A/<b class='flag-5'>TSV</b>631/<b class='flag-5'>TSV</b>631A

    軌到軌輸入/輸出,29μ,420 kHz的CMOS運算放大器TSV62x,TSV62xA

    The TSV622, TSV622A, TSV623, TSV623A, TSV624, TSV
    發(fā)表于 09-05 10:58 ?4次下載
    軌到軌輸入/輸出,29μ,420 kHz的CMOS運算放大器<b class='flag-5'>TSV</b>62x,<b class='flag-5'>TSV</b>62xA

    軌到軌輸入/輸出29μ420 kHz的CMOS運算放大器TSV620,TSV620A,TSV621,TSV621A

    The TSV620, TSV620A, TSV621, and TSV621A are single operational amplifiers offering low volt
    發(fā)表于 09-05 11:01 ?6次下載
    軌到軌輸入/輸出29μ420 kHz的CMOS運算放大器<b class='flag-5'>TSV</b>620,<b class='flag-5'>TSV</b>620A,<b class='flag-5'>TSV</b>621,<b class='flag-5'>TSV</b>621A

    什么是TSV封裝?TSV封裝有哪些應用領域?

    硅通孔技術(Through Silicon Via, TSV)技術是一項高密度封裝技術,正在逐漸取代目前工藝比較成熟的引線鍵合技術,被認為是第四代封裝技術。TSV技術通過銅、鎢、多晶硅等導電物質
    發(fā)表于 08-14 15:39 ?9.1w次閱讀

    英特爾現(xiàn)代代碼:您的突破性創(chuàng)新更快

    了解英特爾的現(xiàn)代代碼計劃如何幫助開發(fā)人員為今天和明天創(chuàng)建更快代碼
    的頭像 發(fā)表于 11-13 06:38 ?1416次閱讀

    什么是硅或TSV通路?使用TSV的應用和優(yōu)勢

    TSV不僅賦予了芯片縱向維度的集成能力,而且它具有最短的電傳輸路徑以及優(yōu)異的抗干擾性能。隨著摩爾定律慢慢走到盡頭,半導體器件的微型化也越來越依賴于集成TSV的先進封裝。
    發(fā)表于 07-25 10:09 ?740次閱讀
    什么是硅或<b class='flag-5'>TSV</b>通路?使用<b class='flag-5'>TSV</b>的應用和優(yōu)勢

    單片機解析g代碼的方法

    的運動。 解析G代碼是將其轉化為單片機能夠理解和執(zhí)行的指令集。單片機解析G代碼的方法主要包括以下幾個方面:G代碼的格式
    的頭像 發(fā)表于 12-22 14:15 ?1662次閱讀