京喜APP - 圖片庫優化

来源:https://www.cnblogs.com/jingdongkeji/archive/2023/05/11/17390442.html
-Advertisement-
Play Games

京喜APP早期開發主要是快速原生化迭代替代原有H5,提高用戶體驗,在這期間也積累了不少性能問題。之後我們開始進行一些性能優化相關的工作,本文主要是介紹京喜圖片庫相關優化策略以及關於圖片相關的一些關聯知識。 ...


作者:京東零售 何驍

介紹

京喜APP早期開發主要是快速原生化迭代替代原有H5,提高用戶體驗,在這期間也積累了不少性能問題。之後我們開始進行一些性能優化相關的工作,本文主要是介紹京喜圖片庫相關優化策略以及關於圖片相關的一些關聯知識。

圖片性能問題

作為電商APP,圖片在各個業務場景被大量使用。我們需要做到儘可能降低網路消耗/記憶體消耗/硬碟消耗,同時不降低圖片質量,提高圖片載入速度,給用戶帶來更好的使用體驗。基於這些性能目標,我們也通過初步性能評估梳理出了一些性能問題:

圖片載入慢/流量消耗高

圖片鏈接主要由後臺介面下發,下發圖片格式尺寸由每個業務後臺指定。部分業務沒有使用更小的圖片格式比如WebP,或圖片尺寸過大,都會使圖片過大導致網路消耗高。特別是網路狀況不佳的場景,圖片載入過慢給用戶帶來不好的體驗。同時也會導致更多的I/O讀寫解碼耗時,造成更多的電量消耗。

圖片記憶體占用高

經過初步的APP記憶體使用評估,圖片記憶體消耗占APP總記憶體消耗的比例最高,特別是大尺寸圖片會占用很多記憶體。一方面APP占用太高記憶體退到後臺容易被系統殺死,導致下次打開重新啟動影響體驗。另一方面APP大量使用記憶體,容易被系統殺死產生OOM。特別是我們目前有大量的低端設備用戶,設備記憶體相對比較低。

優化方向

基於上面分析出的一些性能問題,我們對圖片框架進行了整體重構優化。一方面是降低圖片網路傳輸,提高圖片載入速度。另一方面是減少圖片記憶體消耗。

圖片優化.png

最小化網路傳輸

京東圖片伺服器提供了多種處理功能,例如圖片格式轉換,圖片降質,圖片縮放,圖片圓角等功能。這些功能通過在圖片URL中添加特定參數實現,圖片伺服器會根據參數設置提前將圖片處理完成並保存到CDN伺服器。我們可以通過添加圖片處理參數,減少圖片傳輸大小。

雖然後臺可以提前進行URL預處理,下發已添加過圖片參數的圖片URL。但是由於對接後臺業務很多,每個業務圖片參數設置差異很大無法統一,而且可能會造成性能影響,例如沒有使用webP圖片格式,下發太大的圖片尺寸。同時考慮到推動各業務後臺修改成本也很高,並且前端機型多,不同機型需要使用不同的圖片尺寸。另外也不方便灰度降級功能,後續功能修改也不方便。所以在客戶端進行圖片URL預處理是更好的方式,可以統一控制,也方便之後功能更新。

圖片URL預處理

URL預處理

圖片庫在網路圖片載入前,檢測是否是京東功能變數名稱的圖片URL。如果功能變數名稱匹配,圖片框架先對圖片URL進行預處理,預處理包括功能變數名稱統一添加縮放參數添加webP參數添加降質參數的方式減少圖片網路傳輸大小。

提示:因為後臺返回的圖片URL可能會帶有一部分圖片處理參數,例如https://img11.360buyimg.com/img/pingou-head/25.jpg!webp,直接追加圖片參數可能會導致圖片處理參數不生效,或格式錯誤導致載入失敗。所以轉換時會先將所有圖片參數提前計算出來,之後一起處理,避免添加重覆參數。

功能變數名稱統一

目前圖片伺服器提供了多個圖片功能變數名稱可使用,例如m.360buyimg.comimg10.360buyimg.com等多個功能變數名稱。m.360buyimg.com主要提供給移動端使用。但是由於對接了各種業務後臺,導致介面會下發不同的功能變數名稱圖片。圖片使用不同功能變數名稱可能會導致以下問題:

  • 不利於緩存復用- 圖片框架通常預設以URL字元串生成圖片緩存key,不同功能變數名稱導致生成不同的緩存key硬碟緩存無法復用會導致圖片重覆下載,記憶體緩存無法復用導致同樣的圖片占用多份記憶體。
  • 不利於HTTP/2連接復用- 大部分界面圖片比較多,很多場景都會同時載入多張圖片,特別是首屏通常會載入幾十張圖片。當載入多個圖片時,每個功能變數名稱都需要重新建立HTTPS連接,經歷DNS解析/TCP連接/TLS握手過程(目前一次HTTPS請求創建過程大概耗時50-150ms)。如果利用HTTP/2鏈接復用就只需要創建一次HTTPS請求,之後的圖片請求可以減少這部分的耗時。

所以在預處理時,如果是京東功能變數名稱的圖片,將圖片URL功能變數名稱統一替換為m.360buyimg.com

追加圖片參數

圖片縮放

很多業務後臺返回的原始圖片URLsize都比客戶端實際顯示的size要大。一方面導致使用更多的網路流量造成浪費。另一方面會導致占用更多記憶體。同時因為圖片size和實際顯示size不一致導致像素不對齊GPU需要做額外的插值處理,也會一定的影響渲染性能。所以我們通過添加縮放參數的方式,指定圖片伺服器下發更小和更匹配實際顯示size的圖片尺寸。

動態scale計算尺寸

因為iOS設備主要使用2x/3x的解析度,所以業務方使用API時需要傳入對應的ptsize大小,圖片庫內部根據設備的scale進行動態計算出真實的像素寬高。

提示:android設備因為屏幕差異比較大,更適合使用固定的scale。太多的圖片尺寸不利於CDN緩存,無緩存的時候需要對圖片進行相關參數處理,圖片處理本身是耗時操作。

Scale降級

  • 低端機降級- 對於部分3xscale的低端設備,因為機器本身記憶體比較低,使用3x解析度計算出來的圖片像素寬高比較大,會造成更多的記憶體消耗以及解碼/渲染更多的性能消耗。所以對於寬高超過一定要求的圖片,降級到使用2x解析度來計算像素寬高,減少設備性能消耗。
  • iPad降級- 因為目前APP並沒有針對iPad做特定優化,所以iPad設備下預設是放大顯示。這會導致在iPad下圖片尺寸計算出來特別大。所以也是針對iPad圖片尺寸做了特定限制,防止下發圖片尺寸過大。
  • 大圖片降級- 正常情況下圖片寬/高不應該超過屏幕寬/高。為了防止部分業務使用過大的圖片size,所以添加了一個限制,最終生成的圖片像素尺寸不能超過屏幕寬/高

降質

圖片伺服器支持0-100的圖片質量參數設置,通過降低圖片質量可以減少圖片大小,但是質量降低太多也會影響圖片的觀看體驗。我們將圖片質量參數設置為q70,指定圖片伺服器下發70%質量的圖片。對於大部分業務,一方面可以大幅減少圖片下載大小,同時也可以保證觀看體驗。通過添加圖片降質參數至少可以減少30-40%的圖片大小。

使用WebP

按照Google官方的數據,與PNG相比,WebP無損圖像的位元組數要少26%WebP有損圖像比同類JPG圖像位元組數少25-34%。圖片伺服器支持轉換webP格式,可以減少圖片大小。針對png/jpg圖片格式,添加webP參數,指定圖片伺服器下發webp格式。雖然webP相比png/jpg圖片解碼需要更長時間,但相對網路傳輸速度提升還是很大。

提示:由於目前圖片伺服器並不支持GIFwebP,GIF並沒有做處理。

URL預處理緩存

添加輕量緩存,提高URL轉換性能。因為URL轉換本身有一定的耗時,而且單個圖片URL可能會多次載入/多次轉換。轉換後的URL會直接保存到緩存中,下次使用可以直接返回。緩存keyURL+相關圖片轉換參數拼接組成。

圖片API設計

圖片處理參數通過options設置,預設使用q70圖片質量以及webP格式。業務方在調用載入圖片方法時傳入,下麵是iOS端的API:

imageView6.jx.setImage(url: URL(string: "https://img11.360buyimg.com/img/pingou-head/25.jpg"), 
                       placeholder: nil, options: [.imageSize(CGSize(width: 40, height: 40))])


磁碟緩存優化

圖片緩存查找優化

設置圖片不同的size參數會導致更多的圖片下載和磁碟緩存,例如同樣一張圖片100px200px300px尺寸因為URL不同會下載3次,同時緩存也無法不同。由於圖片庫通常預設使用URL作為圖片緩存key,所以我們需要針對圖片緩存key查找圖片進行優化改造。簡單來講,相同的圖片小size的圖片可以直接復用更大size的緩存,這樣當存在更大尺寸圖片時,可以避免圖片直接下載並且復用磁碟緩存。

降低圖片記憶體消耗

png/jpg等圖片格式在顯示之前都需要經過解碼生成一張點陣圖,之後根據點陣圖創建紋理傳給GPU做渲染。一張點陣圖的記憶體消耗大概是像素寬x像素高x位深。通常圖片使用的是RGBA,位深為32位。一張500px_500px的大概1MB記憶體。對於GIF圖片因為本身有多幀,所以最終的記憶體消耗為單幀記憶體x幀數

我們的優化方向一方面是通過圖片縮放的方式,減少圖片點陣圖的記憶體消耗。另一方面限製圖片緩存上限避免緩存使用過高。

圖片縮放

通過上面URL預處理過程讓圖片伺服器下發更小的圖片格式,已經降低了一部分記憶體。但是URL預處理只處理了jd功能變數名稱的jpg/png圖片,對於GIF京東功能變數名稱外的圖片沒有處理,包括一部分URL轉換後載入失敗的圖片。所以對於這部分圖片,我們會在端側做圖片縮放的處理,降低記憶體消耗。例如一張300px_300px包含100幀的GIF圖片,實際顯示區域只有50px_50px,優化後總記憶體消耗可從30MB+記憶體降低到3MB

GIF動態幀率播放

之前根據線上監控數據發現,部分頁面場景偶爾會配置尺寸大/幀數多GIF圖片,導致記憶體占用極高。例如一張500x400px播放200幀的GIF圖片會占用100MB+記憶體消耗。所以針對這種場景,我們針對GIF做了減幀播放改造。當GIF圖片總記憶體消耗大於一定量級時(例如圖片記憶體緩存上線的20%),將GIF播放的幀數適當減少,每一幀的播放時間增加,這樣可以將記憶體控制在一定範圍之內。

提示:這裡也可以通過 GIF 圖片緩存 Buffer 控制記憶體總量,但是會導致更頻繁的解碼造成更多的 CPU 消耗。

圖片記憶體緩存上限

圖片緩存的設計目的是減少圖片解碼消耗。圖片第一次使用的時候,將圖片進行解碼後的點陣圖保存在記憶體中,這樣可以避免下次使用時避免重覆解碼。雖然圖片記憶體高可以儘量避免圖片重覆解碼,但是占用太高記憶體也會導致APP後臺被系統殺掉或產生OOM等問題。所以我們應該將記憶體緩存控制在一定範圍內。

例如iOS的第三方圖片庫SDWebImage/Kingfisher預設都使用系統庫NSCache來實現記憶體緩存。雖然NSCache會在設備記憶體緊張時回收記憶體,但是預設並不限制可保存記憶體最大位元組數,所以在設備記憶體可用的情況下記憶體可以一直增加。所以通過設置圖片緩存上限,防止圖片緩存占用太高記憶體。圖片緩存定義了一個預設的初始值上限,之後對於3x大屏幕設備和高端設備(記憶體比較高),適當增加更多記憶體上限。

優化成果

圖片優化成果

其他收益

  • 功能變數名稱統一- 減少了10%+的重覆圖片下載和記憶體消耗。同時減少之前多功能變數名稱圖片載入時重覆創建HTTPS請求的過程,減少圖片載入時間。

其他策略

載入異常處理

因為少量圖片通過URL預處理轉換後,可能會存在圖片不存在的異常場景導致載入失敗。所以當發生圖片載入失敗時,我們還是需要載入原始圖片URL。但是這裡需要屏蔽一些特殊的載入錯誤,避免非必要的載入,例如無網路/網路超時/主動取消載入等錯誤。之後會將錯誤圖片URL上報到後臺,方便之後調整URL轉換策略,也可以發現一部分錯誤的圖片URL推動業務修改。同時將這部分連接加入到錯誤連接緩存中,避免下次重覆執行預處理和重覆上報。

線上配置

目前存在的一些功能,例如URL預處理/統一功能變數名稱/WebP使用等功能,都添加了線上配置,方便灰度/降級。一在出現問題時可以降級某些功能,新功能上線時也可以進行灰度測試。

大圖檢測

需要有一個機制及時發現圖片不符合規範的問題。一方面我們通過線上灰度檢測的方式,當發現大圖片時會進行上報,後續推動業務方進行優化。另一方面我們在日常測試階段,會開啟Debug檢測工具,當檢測到大圖片時,通過圖片翻轉/高亮背景顏色的方式提醒業務開發同學進行優化。

Flutter圖片庫優化

目前京喜APP有10+個二級界面是基於Flutter開發,所以我們也針對Flutter圖片載入做了一些優化。

對接原生圖片庫

因為Flutter框架自帶圖片庫只提供記憶體圖片緩存,並不支持硬碟緩存,所以會導致圖片重覆下載。所以我們通過重寫ImageProvider,當載入網路圖片時,通過Channel調用原生圖片庫,原生圖片庫下載圖片到本地磁碟後,返回圖片文件目錄。之後Flutter通過文件目錄載入解碼圖片顯示。這樣一方面可以利用原生圖片庫相關優化能力,同時也可以復用圖片硬碟緩存避免重覆下載。

減少記憶體消耗

使用Image組件時,通過設置cacheHeight/cacheWidth,將圖片解碼為置頂像素寬高的點陣圖尺寸,減少記憶體消耗。同時因為Flutter記憶體消耗相對原生更高,所以在Flutter界面關閉時,通過調用imageCache方法清除圖片記憶體消耗降低記憶體消耗。

GIF優化

  • 動畫優化- 因為通常使用Flutter都是混合棧的機制,原生Flutter界面在頁面導航中相互跳轉。所以當Flutter界面存在GIF圖片時,跳轉到原生以後GIF動畫還會一直執行。所以我們通過在Image組件內監聽Flutter engine發送的生命周期通知,當Flutter界面不在棧頂時,停止GIF動畫執行,減少記憶體和CPU消耗。
  • 減少解碼次數- Flutter框架內部對GIF渲染的處理方式,在屏幕每一幀判斷當前需要顯示的GIF幀,之後對該GIF幀進行解碼之後渲染。因為並不會把解碼過的幀保存,所以會導致頻繁解碼導致記憶體波動大。經過優化,對已經解碼過的幀進行保存,避免重覆解碼的消耗,同時避免記憶體的波動。

優化前記憶體波動很明顯
優化前
優化後記憶體傾於平穩
優化後
提示:保存每一幀也會導致更多的記憶體消耗。目前APP中通常是小尺寸的GIF所以整體可控。可以考慮設置緩衝區上限來控制緩存的圖片幀數避免記憶體過高。

後續優化方向

更優的緩存演算法

  • 優先移除最大記憶體- iOS系統NSCache實現。通過設置最大記憶體數,當記憶體不足時優先移除最大的值。
  • LRU緩存- 優先淘汰最久未使用的圖片記憶體。對於很多二級界面的場景,用戶打開界面後並不會再次打開。但是因為這些圖片緩存是最後使用,所以清除記憶體時也會最後移除,但是在這種場景下就不太合適。
  • 界面棧管理- 當界面關閉時將該界面的所有的圖片記憶體移除,但是對於經常會打開的界面會導致頻繁圖片編解碼也不太合適。

所以針對不同的業務場景使用不同的回收方式可能更加合適:

  • 對於購物車/我的訂單這類界面,用戶每次載入的圖片基本固定,所以更適合在記憶體中常駐,當記憶體消耗過高時再回收。
  • 對於商詳/搜索商品列表這類界面,通常商品列表展示的圖片不一樣並且用戶也不會頻繁進某一個特定的商詳,所以更適合優先移除這部分的記憶體。
  • 對於部分彈窗功能,圖片顯示後並不會再次使用,可以考慮不添加到記憶體中。

使用更好的圖片格式

使用更好的圖片格式通常可以帶來更小的圖片位元組大小。同時因為壓縮率的提高,可以在減少大小的同時提高圖片質量。

提示:使用系統支持硬解碼的圖片格式更有優勢。硬解碼就是使用GPU進行解碼,相比使用CPU軟解碼性能更好更省電。

  • APNG/動畫WebP代替GIF- 按照Google官方的說法,GIF轉換為有損WebP的位元組數縮小了64%,而無損WebP位元組數縮小了19%。所以使用動畫WebP可以減少更多的網路流量傳輸。APNGMozilla推出的基於PNG的動圖格式並且完全支持RGBA,相比GIF可以減少20%+的圖片大小。而且GIF本身只支持256色索引顏色以及1位alpha(加上透明度後,邊緣會出現明顯的鋸齒),使用APNG/WebP也可以帶來相比GIF更好的顯示效果。

提示:相比GIFWebP的解碼比GIF占用更多的CPU資源。有損WebP的解碼時間是GIF的2.2倍,而無損WebP的解碼時間是GIF的1.5倍。

  • HEIC-HEIC是基於H.265視頻編碼格式推出的圖片格式。HEIC相比WebP可以減少20%+的圖片大小,並且編解碼性能更好。在系統相容性上,Android 9.0以上的系統支持HEIC。蘋果在iOS14以上系統才提供了WebP硬解碼,之前的系統只能使用軟解碼,而HEICiOS11之後的機器上都已經支持硬解碼,不過並不支持瀏覽器
  • AVIF-AVIF是基於AV1編碼格式推出的圖片格式。AVIF相比WebP可以減少30%+的圖片大小。不過目前只有Android 12以上的版本支持。

提示:這裡主要是以VP8編碼格式的WebPVP9編碼格式的WebP整體性能和HEIC差異不大。
不過這些圖片格式需要圖片伺服器支持之後才能使用。

Flutter

雖然我們對Flutter圖片庫做了一些優化,但總體上還有很多優化空間。包括業界有在使用的基於紋理的圖片方案。在原生側將圖片解碼後,通過Flutter引擎創建紋理。之後講圖片紋理id傳遞給Flutter進行渲染。這樣可以統一在原生側管理圖片記憶體緩存,優化之前Flutter原生都分別有一份記憶體緩存的方式。而且針對於混合棧的導航棧方式,也可以更好的進行圖片記憶體回收。另外針對Flutter,需要提供更靈活的圖片記憶體回收策略,避免記憶體消耗過高。

提示:紋理可以復用記憶體中的點陣圖緩存,所以並不會導致更多的記憶體占用。紋理方式大概能減少30%的記憶體消耗相比Flutter引擎圖片庫,主要是一些其他對象使用導致。

優化H5圖片載入

我們可以通過攔截WebView圖片載入的方式,讓原生圖片庫來下載圖片之後傳遞圖片二進位數據給WebView顯示。

減少流量消耗

通過這種方式,我們可以將原生圖片庫URL預處理相關功能支持到H5圖片,減少H5載入過程中圖片流量消耗,提高圖片載入速度。同時因為APP原生WebView圖片緩存機制是相互獨立的,所以通過統一在原生側管理圖片緩存,可以減少相同圖片的重覆下載。

支持更多圖片格式

例如在iOS系統上,WKWebView目前只支持PNG/JPG/GIF圖片格式。所以我們可以通過在原生端實現下載WebP/HEIC圖片,之後對圖片進行解碼再傳給WebView,這樣就可以支持其他圖片格式的顯示。

提示:因為WebView不支持直接傳遞點陣圖二進位數據顯示,所以需要提前轉換為PNG/JPG二進位數據傳遞。所以對於其他圖片格式增加一次PNG/JPG編碼過程會造成更多的性能消耗。不過對於Android系統應該可以在web內核層優化減少這塊消耗。

總結

本文並沒有講底層圖片載入庫的具體實現,目前圖片庫不管是直接用第三方庫還是自研圖片庫實現方式通常差異不大。我們更多是關註自身業務以及如何利用圖片伺服器能力最大化改善網路圖片載入性能。所以部分策略可能不一定針對所有APP都合適,應該針對自身業務場景仔細評估優化方案。

擴展鏈接


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 索引介紹 索引是一種幫助查詢語句能夠快速定位到數據的一種技術。索引的存儲方式有行存儲索引、列存儲索引和記憶體優化三種存儲方式: 行存儲索引,使用B+樹結構,行存儲指的是數據存儲格式為堆、聚集索引和記憶體優化表的表,用於OLTP場景。行存儲索引按順序排列的值列表,每個值都有指向其所在的數據頁面的指針。 ...
  • (資料庫定時備份winserver2012篇) 1 序言 數據是無價的,所以生產環境中定時備份資料庫顯得尤為重要。備份能防止伺服器故障、天災人禍和人為誤操作帶來的數據丟失。 上一篇文章我們說了Linux環境下的數據備份。這一篇就把之前留下的坑給填上了。 這一篇我們說一說winserver2012環境 ...
  • 隨著世界經濟由工業經濟向數字經濟轉型,數據逐步成為關鍵的生產要素,企業開始將數據作為一種戰略資產進行管理。數據從業務中產生,在IT系統中承載,要對數據進行有效治理,需要業務充分參與,IT系統確保遵從,這是一個非常複雜的系統工程。 數據治理架構 實踐證明,企業只有構築一套企業級的數據治理綜合體系,明確 ...
  • 開源之夏 2023 學生報名已經正式開啟!Apache DolphinScheduler 今年繼續參與開源之夏的活動,2023 年 4 月 29 日-6 月 3 日 15:00 UTC+8,同學們可以在開源之夏官網 https://summer-ospp.ac.cn/ 找到 Apache Dolph ...
  • 摘要:金山辦公攜手華為雲完成金山辦公自主研發的“WPS文檔中心系統”與華為雲GaussDB相互相容性測試認證,並獲得華為雲授予的《技術認證書》。 本文分享自華為雲社區《共築數字化未來 金山辦公攜手華為雲完成文檔中心和GaussDB適配》,作者:GaussDB 資料庫。 近日,金山辦公攜手華為雲完成金 ...
  • 更多技術交流、求職機會,歡迎關註位元組跳動數據平臺微信公眾號,回覆【1】進入官方交流群 近期,火山引擎 DataLeap 上線“動態探查”能力,為用戶提供全局數據視角、完善的抽樣策略,提高數據探查的靈活度以及響應速率。 傳統的數據探查是基於庫表的全量探查,由後端引擎執行,通過自動化檢查數據成分、關係、 ...
  • (Oracle 定時任務job實際應用) 一、Oracle定時任務簡介 Oracle定時任務是在oracle系統中一個非常重要的子系統,運用得當,可以大大提高我們系統運行和維護能力。oracle定時任務的功能,可以在指定的時間點自行執行任務。 那麼在實際工作中,什麼樣的場景會用到定時任務呢?下麵是在 ...
  • HUAWEI Health Kit為開發者提供用戶自定義的跑步課程導入介面,便於用戶在華為運動健康App和華為智能穿戴設備上查看來自生態應用的訓練課表,開啟科學、適度的運動訓練。 跑步課程導入能力支持生態應用在獲取用戶的華為帳號授權後,將跑步課程數據寫入至華為運動健康App,併在已有的華為智能穿戴設 ...
一周排行
    -Advertisement-
    Play Games
  • PasteSpider是什麼? 一款使用.net編寫的開源的Linux容器部署助手,支持一鍵發佈,平滑升級,自動伸縮, Key-Value配置,項目網關,環境隔離,運行報表,差量升級,私有倉庫,集群部署,版本管理等! 30分鐘上手,讓開發也可以很容易的學會在linux上部署你得項目! [從需求角度介 ...
  • SQLSugar是什麼 **1. 輕量級ORM框架,專為.NET CORE開發人員設計,它提供了簡單、高效的方式來處理資料庫操作,使開發人員能夠更輕鬆地與資料庫進行交互 2. 簡化資料庫操作和數據訪問,允許開發人員在C#代碼中直接操作資料庫,而不需要編寫複雜的SQL語句 3. 支持多種資料庫,包括但 ...
  • 在C#中,經常會有一些耗時較長的CPU密集型運算,因為如果直接在UI線程執行這樣的運算就會出現UI不響應的問題。解決這類問題的主要途徑是使用多線程,啟動一個後臺線程,把運算操作放在這個後臺線程中完成。但是原生介面的線程操作有一些難度,如果要更進一步的去完成線程間的通訊就會難上加難。 因此,.NET類 ...
  • 一:背景 1. 講故事 前些天有位朋友在微信上丟了一個崩潰的dump給我,讓我幫忙看下為什麼出現了崩潰,在 Windows 的事件查看器上顯示的是經典的 訪問違例 ,即 c0000005 錯誤碼,不管怎麼說有dump就可以上windbg開幹了。 二:WinDbg 分析 1. 程式為誰崩潰了 在 Wi ...
  • CSharpe中的IO+NPOI+序列化 文件文件夾操作 學習一下常見的文件、文件夾的操作。 什麼是IO流? I:就是input O:就是output,故稱:輸入輸出流 將數據讀入記憶體或者記憶體輸出的過程。 常見的IO流操作,一般說的是[記憶體]與[磁碟]之間的輸入輸出。 作用 持久化數據,保證數據不再 ...
  • C#.NET與JAVA互通之MD5哈希V2024 配套視頻: 要點: 1.計算MD5時,SDK自帶的計算哈希(ComputeHash)方法,輸入輸出參數都是byte數組。就涉及到字元串轉byte數組轉換時,編碼選擇的問題。 2.輸入參數,字元串轉byte數組時,編碼雙方要統一,一般為:UTF-8。 ...
  • CodeWF.EventBus,一款靈活的事件匯流排庫,實現模塊間解耦通信。支持多種.NET項目類型,如WPF、WinForms、ASP.NET Core等。採用簡潔設計,輕鬆實現事件的發佈與訂閱。通過有序的消息處理,確保事件得到妥善處理。簡化您的代碼,提升系統可維護性。 ...
  • 一、基本的.NET框架概念 .NET框架是一個由微軟開發的軟體開發平臺,它提供了一個運行時環境(CLR - Common Language Runtime)和一套豐富的類庫(FCL - Framework Class Library)。CLR負責管理代碼的執行,而FCL則提供了大量預先編寫好的代碼, ...
  • 本章將和大家分享在ASP.NET Core中如何使用高級客戶端NEST來操作我們的Elasticsearch。 NEST是一個高級別的Elasticsearch .NET客戶端,它仍然非常接近原始Elasticsearch API的映射。所有的請求和響應都是通過類型來暴露的,這使得它非常適合快速上手 ...
  • 參考delphi的代碼更改為C# Delphi 檢測密碼強度 規則(仿 google) 仿 google 評分規則 一、密碼長度: 5 分: 小於等於 4 個字元 10 分: 5 到 7 字元 25 分: 大於等於 8 個字元 二、字母: 0 分: 沒有字母 10 分: 全都是小(大)寫字母 20 ...