<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們在編寫網路程式的時候,經常會進行如下操作:
申請一個緩衝區
從資料來源中讀入資料至緩衝區
解析緩衝區的資料
重複第2步
表面上看來這是一個很常規而簡單的操作,但實際使用過程中往往存在如下痛點:
可能不能在一次read操作中讀入所有需要的資料,因此需要在緩衝區中維護一個遊標,記錄下次讀取操作的起始位置,這個遊標帶了了不小的複雜度:
從緩衝區讀資料時,要根據遊標計算緩衝區起始寫位置,以及剩餘空間大小。增加了讀資料的複雜度。
解析資料也是複用這個緩衝區的,解析的時候也要判斷遊標起始位置,剩餘空間大小。同時增加了解析資料的複雜度。
解析玩了後還要移動遊標,重新標記緩衝區起始位置,再次增加了複雜度。
由於緩衝區有限,可能申請的緩衝區不夠用,需要引入動態緩衝區。這也大幅加大了程式碼的複雜度。
如果每次都申請更大的記憶體,一方面帶來的記憶體申請釋放開銷,另一方面需要將原來的資料移動,並更新遊標,帶來更復雜的邏輯。
如果靠多段的記憶體組成一個邏輯整理,資料的讀寫方式都比較複雜。
使用完後的記憶體要釋放,如果需要更高的效率還要維持一個記憶體池。
我們的業務本身只關心使用操作,但讀和用操作沒有分離,複雜的都操作導致用操作也變得複雜,並且嚴重干擾業務邏輯。
今天介紹微軟新推出的一個庫:System.IO.Pipelines(需要在Nuget上安裝),用於解決這些痛點。它主要包含一個Pipe物件,它有一個Writer屬性和Reader屬性。
var pipe = new Pipe(); var writer = pipe.Writer; var reader = pipe.Reader;
Writer物件用於從資料來源讀取資料,將資料寫入管道中;它對應業務中的"讀"操作。
var content = Encoding.Default.GetBytes("hello world"); var data = new Memory<byte>(content); var result = await writer.WriteAsync(data);
另外,它也有一種使用Pipe申請Memory的方式
var buffer = writer.GetMemory(512); content.CopyTo(buffer); writer.Advance(content.Length); var result = await writer.FlushAsync();
Reader物件用於從管道中獲取資料來源,它對應業務中的"用"操作。
首先獲取管道的緩衝區:
var result = await reader.ReadAsync(); var buffer = result.Buffer;
這個Buffer是一個ReadOnlySequence<byte>物件,它是一個相當好的動態記憶體物件,並且相當高效。它本身由多段Memory<byte>組成,檢視Memory段的方法有:
IsSingleSegment: 判斷是否只有一段Memory<byte>
First: 獲取第一段Memory<byte>
GetEnumerator: 獲取分段的Memory<byte>
它從邏輯上也可以看成一段連續的Memory<byte>,也有類似的方法:
Length: 整個資料緩衝區長度
Slice: 分割緩衝區
CopyTo: 將內容複製到Span中
ToArray: 將內容複製到byte[]中
另外,它還有一個類似遊標的位置物件SequencePosition,可以從其Position相關函數中使用,這裡就不多介紹了。
這個緩衝區解決了"資料讀不夠"的問題,一次讀取的不夠下次可以接著讀,不用緩衝區的動態分配,高效的記憶體管理方式帶來了良好的效能,好用的介面是我們能更關注業務。
獲取到緩衝區後,就是使用緩衝區的資料
var data = buffer.ToArray();
使用完後,告訴PIPE當前使用了多少資料,下次接著從結束位置後讀起
reader.AdvanceTo(buffer.GetPosition(4));
這是一個相當實用的設計,它解決了"讀了就得用"的問題,不僅可以將不用的資料下次再使用,還可以實現Peek的操作,唯讀但不改變遊標。
除了"讀"和"用"操作外,它們之間還需要一些互動,例如:
讀過程中資料來源不可用,需要停止使用
使用過程中業務結束,需要中止資料來源。
Reader和Writer都有一個Complete函數,用於通知結束:
reader.Complete(); writer.Complete();
在Writer寫入和Reader讀取時,會獲得一個結果
FlushResult result = await writer.FlushAsync(); ReadResult result = await reader.ReadAsync();
它們都有一個IsComplete屬性,可以根據它是否為true判斷是否已經結束了讀和寫的操作。
在寫入和讀取的時候,也可以傳入一個CancellationToken,用於取消相應的操作。
writer.FlushAsync(CancellationToken.None); reader.ReadAsync(CancellationToken.None);
如果取消成功,對應的Result的IsCanceled則為true(沒有驗證過)
到此這篇關於C#高效IO庫System.IO.Pipelines的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45