shell高效處理文本(1):xargs並行處理

来源:https://www.cnblogs.com/f-ck-need-u/archive/2018/10/08/9752365.html
-Advertisement-
Play Games

xargs具有並行處理的能力,在處理大文件時,如果應用得當,將大幅提升效率。 xargs詳細內容(全網最詳細): "https://www.cnblogs.com/f ck need u/p/5925923.html" 效率提升測試結果 先展示一下使用xargs並行處理提升的效率,稍後會解釋下麵的結 ...


xargs具有並行處理的能力,在處理大文件時,如果應用得當,將大幅提升效率。

xargs詳細內容(全網最詳細):https://www.cnblogs.com/f-ck-need-u/p/5925923.html

效率提升測試結果

先展示一下使用xargs並行處理提升的效率,稍後會解釋下麵的結果。

測試環境:

  1. win10子系統上
  2. 32G記憶體
  3. 8核心cpu
  4. 測試對象是一個放在固態硬碟上的10G文本文件(如果你需要此測試文件,點此下載,提取碼: semu)

下麵是正常情況下wc -l統計這個10G文件行數的結果,花費16秒,多次測試,cpu利用率基本低於80%

$ /usr/bin/time wc -l 9.txt
999999953 9.txt
4.56user 3.14system 0:16.06elapsed 47%CPU (0avgtext+0avgdata 740maxresident)k
0inputs+0outputs (0major+216minor)pagefaults 0swaps

通過分割文件,使用xargs的並行處理功能進行統計,花費時間1.6秒,cpu利用率752%

$ /usr/bin/time ./b.sh
999999953
7.67user 4.54system 0:01.62elapsed 752%CPU (0avgtext+0avgdata 1680maxresident)k
0inputs+0outputs (0major+23200minor)pagefaults 0swaps

用grep從這個10G的文本文件中篩選數據,花費時間24秒,cpu利用率36%

$ /usr/bin/time grep "10000" 9.txt >/dev/null
6.17user 2.57system 0:24.19elapsed 36%CPU (0avgtext+0avgdata 1080maxresident)k
0inputs+0outputs (0major+308minor)pagefaults 0swaps

通過分割文件,使用xargs的並行處理功能進行統計,花費時間1.38秒,cpu利用率746%

$ /usr/bin/time ./a.sh
6.01user 4.34system 0:01.38elapsed 746%CPU (0avgtext+0avgdata 1360maxresident)k
0inputs+0outputs (0major+31941minor)pagefaults 0swaps

速度提高的不是一點點。

xargs並行處理簡單示例

要使用xargs的並行功能,只需使用"-P N"選項即可,其中N是指定要運行多少個並行進程,如果指定為0,則使用儘可能多的並行進程數量。

需要註意的是:

  • 既然要並行,那麼xargs必須得分批傳送管道的數據,xargs的分批選項有"-n"、"-i"、"-L",如果不知道這些內容,看本文開頭給出的文章。
  • 並行進程數量應該設置為cpu的核心數量。如果設置為0,在處理時間較長的情況下,很可能會併發幾百個甚至上千個進程。在我測試一個花費2分鐘的操作時,創建了500多個進程。
  • 在本文後面,還給出了其它幾個註意事項。

例如,一個簡單的sleep命令,在不使用"-P"的時候,預設是一個進程按批的先後進行處理:

[root@xuexi ~]# time echo {1..4} | xargs -n 1 sleep
 
real    0m10.011s
user    0m0.000s
sys     0m0.011s

總共用了10秒,因為每批傳一個參數,第一批睡眠1秒,然後第二批睡眠2秒,依次類推,還有3秒、4秒,共1+2+3+4=10秒。

如果使用-P指定4個處理進程,它將以處理時間最長的為準:

[root@xuexi ~]# time echo {1..4} | xargs -n 1 -P 4 sleep
 
real    0m4.005s
user    0m0.000s
sys     0m0.007s

再例如,find找到一大堆文件,然後用grep去篩選:

find /path -name "*.log" | xargs -i grep "pattern" {}
find /path -name "*.log" | xargs -P 4 -i grep "pattern" {}

上面第一個語句,只有一個grep進程,一次處理一個文件,每次只被其中一個cpu進行調度。也就是說,它無論如何,都只用到了一核cpu的運算能力,在極端情況下,cpu的利用率是100%。

上面第二個語句,開啟了4個並行進程,一次可以處理從管道傳來的4個文件,在同一時刻這4個進程最多可以被4核不同的CPU進行調度,在極端情況下,cpu的利用率是400%。

並行處理示例

下麵是文章開頭給出的實驗結果對應的示例。一個10G的文本文件9.txt,這個文件里共有9.9億(具體的是999999953)行數據。

首先一個問題是,怎麼統計這麼近10億行數據的?wc -l,看看時間花費。

$ /usr/bin/time wc -l 9.txt
999999953 9.txt
4.56user 3.14system 0:16.06elapsed 47%CPU (0avgtext+0avgdata 740maxresident)k
0inputs+0outputs (0major+216minor)pagefaults 0swaps

總共花費了16.06秒,cpu利用率是47%

隨後,我把這10G數據用split切割成了100個小文件,在提升效率方面,split切割也算是妙用無窮:

split -n l/100 -d -a 3 9.txt fs_

這100個文件,每個105M,文件名都以"fs_"為首碼:

$ ls -lh fs* | head -n 5
-rwxrwxrwx 1 root root 105M Oct  6 17:31 fs_000
-rwxrwxrwx 1 root root 105M Oct  6 17:31 fs_001
-rwxrwxrwx 1 root root 105M Oct  6 17:31 fs_002
-rwxrwxrwx 1 root root 105M Oct  6 17:31 fs_003
-rwxrwxrwx 1 root root 105M Oct  6 17:31 fs_004

然後,用xargs的並行處理來統計,以下是統計腳本b.sh的內容:

#!/usr/bin/env bash

find /mnt/d/test -name "fs*" |\
 xargs -P 0 -i wc -l {} |\
 awk '{sum += $1}END{print sum}'

上面用-P 0選項指定了儘可能多地開啟併發進程數量,如果要保證最高效率,應當設置併發進程數量等於cpu的核心數量(在我的機器上,應該設置為8),因為在操作時間較久的情況下,可能會並行好幾百個進程,這些進程之間進行切換也會消耗不少資源。

然後,用這個腳本去統計測試:

$ /usr/bin/time ./b.sh
999999953
7.67user 4.54system 0:01.62elapsed 752%CPU (0avgtext+0avgdata 1680maxresident)k
0inputs+0outputs (0major+23200minor)pagefaults 0swaps

花了1.62秒,cpu利用率752%。和前面單進程處理相比,時間是原來的16分之1,cpu利用率是原來的好多好多倍。

再來用grep從這個10G的文本文件中篩選數據,例如篩選包含"10000"字元串的行:

$ /usr/bin/time grep "10000" 9.txt >/dev/null
6.17user 2.57system 0:24.19elapsed 36%CPU (0avgtext+0avgdata 1080maxresident)k
0inputs+0outputs (0major+308minor)pagefaults 0swaps

24秒,cpu利用率36%

再次用xargs來處理,以下是腳本:

#!/usr/bin/env bash

find /mnt/d/test -name "fs*" |\
 xargs -P 8 -i grep "10000" {} >/dev/null

測試結果:

$ /usr/bin/time ./a.sh
6.01user 4.34system 0:01.38elapsed 746%CPU (0avgtext+0avgdata 1360maxresident)k
0inputs+0outputs (0major+31941minor)pagefaults 0swaps

花費時間1.38秒,cpu利用率746%

這比用什麼ag、ack替代grep有效多了。

提升哪些效率以及註意事項

xargs並行處理用的好,能大幅提升效率,但這是有條件的。

首先要知道,xargs是如何提升效率的,以grep命令為例:

ls fs* | xargs -i -P 8 grep 'pattern' {}

之所以xargs能提高效率,是因為xargs可以分批傳遞管道左邊的結果給不同的併發進程,也就是說,xargs要高效,得有多個文件可處理。對於上面的命令來說,ls可能輸出了100個文件名,然後1次傳遞8個文件給8個不同的grep進程。

還有一些註意事項:

1.如果只有單核心cpu,像提高效率,沒門
2.xargs的高效來自於處理多個文件,如果你只有一個大文件,那麼需要將它切割成多個小片段
3.由於是多進程並行處理不同的文件,所以命令的多行輸出結果中,順序可能會比較隨機

例如,統計行數時,每個文件的出現順序是不受控制的。

10000000 /mnt/d/test/fs_002
9999999 /mnt/d/test/fs_001
10000000 /mnt/d/test/fs_000
10000000 /mnt/d/test/fs_004
9999999 /mnt/d/test/fs_005
9999999 /mnt/d/test/fs_003
10000000 /mnt/d/test/fs_006
9999999 /mnt/d/test/fs_007

不過大多數時候這都不是問題,將結果排序一下就行了。

4.xargs提升效率的本質是cpu的利用率,因此會有記憶體、磁碟速度的瓶頸。如果記憶體小,或者磁碟速度慢(將因為載入數據到記憶體而長時間處於io等待的睡眠狀態),xargs的並行處理基本無效

例如,將上面10G的文本文件放在虛擬機上,機械硬碟,記憶體2G,將會發現使用xargs並行和普通的命令處理幾乎沒有差別,因為絕大多數時間都花在了載入文件到記憶體的io等待上。

下一篇文章將介紹GNU parallel並行處理工具,它的功能更豐富,效果更強大。


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

-Advertisement-
Play Games
更多相關文章
  • socket 函數 system Call socket 函數原型: 參數adressfamily 舉例 | adress family種類 | 功能描述 | | | | | AF_INET | IPV4用socket | | AF_INET6 | IPV6用socket | | AF_UNIX | ...
  • 1 下載smarty3並將libs文件放在框架libraries目錄下重命名為smarty 2 在libraries下創建Ci_smarty.php文件,代碼如下 <?php if ( ! defined('BASEPATH')) exit('No direct script access allo ...
  • 本來是學著使用tesserocr來識別驗證碼的,但是由於tesserocr的識別率不高,還是學了一下使用雲打碼來識別驗證碼== 具體步驟如下: 1、首先是註冊賬號,然後進入這個網址(http://www.yundama.com/apidoc/YDM_SDK.html)選擇PythonHTTP示例下載 ...
  • 題意 "題目鏈接" Sol 欲哭無淚啊qwq。。。。昨晚一定是智息了qwq 說一個和標算不一樣做法吧。。 顯然$x$軸是可以三分的,半徑是可以二分的。 恭喜你獲得了一個TLE的做法。。 然後第二維的二分是沒有必要的,直接拿圓的標準方程推一下取個最大值就行了。。。。。昨晚沒想到qwq給數學老師丟臉了。 ...
  • 在開發中經常有遇到因為程式執行的時間過長,而造成程式假死的情況,這是因為我們的程式是同步執行的,當執行到需要長時間的操作時,程式就會等待當前的操作完成,從而造成程式假死。C#的非同步與多線程就是為瞭解決這個問題的。 多線程編程示例 .Net提供了多種方式實現多線程的編程,包括線程池,Thread,Ta ...
  • 最近聽了一節Java公開課,講的Tomcat8.0的,老師分享的學習方法很好, 時間和精力要用對地方 1.學習一個知識的廣度和深度,先學主要的主流的,不要學了很多不該學,沒必要學的東西 2.要花時間總結,實踐下,練習下,整理下,避免沒有收穫到本該收穫到的內容 ...
  • 示例使用的是最新 SqlRepoEx 2.0.2 可在:https://github.com/AzThinker/SqlRepoEx2.0Demo 或:https://gitee.com/azthinker/SqlRepoEx2.0Demo 演示模塊:GettingStartedNorthwind ...
  • 封裝:把事物封裝成類,私有化屬性. 繼承:共同的特性封裝在父類,子類就有父類的屬性 父類已經實現了的方法,子類也有需要前面+New 隱藏父類的方法,就不報錯了,有這個語法,面試的時候問過,不推薦用. 父類; public void Test() 子類:public New void Test() 多 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...