作者 主題: [Perl]單一perl程式消耗大量cpu  (閱讀 6348 次)

0 會員 與 1 訪客 正在閱讀本文。

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
[Perl]單一perl程式消耗大量cpu
« 於: 2014-10-26 00:11 »
之前撰寫程式碼時只在乎perl程式消耗多少記憶體
而忽略CPU的使用情況
而目前單一一隻程式就占用CPU約65%的使用量
想請問有什麼辦法可將該程式消耗的CPU使用量降低?

為方便大家隔空抓藥
簡單說明一下該程式的功能:
1.連線至mysql資料庫建立資料表
2.開檔
3.無限迴圈讀檔
4.如果讀到關鍵訊息
5.建立與資料庫連線
6.寫入資料到資料庫
7.回到3.

« 上次編輯: 2015-03-02 17:34 由 logichom »

hoyo

  • 榮譽博士
  • 俺是博士!
  • *****
  • 文章數: 4050
  • 性別: 男
  • 有需要的時候,學習就不會分階段。
    • 檢視個人資料
    • 樂咖黑電腦學習網
Re: 單一perl程式消耗大量cpu
« 回覆 #1 於: 2014-10-26 00:14 »
無限迴圈內加個 sleep 讓程式睡一下就可以了

perl 不熟,自己找找相關指令
受人與魚,不如授人與漁
上海自來水來自海上;倫敦好奇人奇好敦倫

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #2 於: 2014-10-26 13:26 »
無限迴圈內加個 sleep 讓程式睡一下就可以了

perl 不熟,自己找找相關指令
好奇如果讓程式睡一下會不會因此錯過log?

hoyo

  • 榮譽博士
  • 俺是博士!
  • *****
  • 文章數: 4050
  • 性別: 男
  • 有需要的時候,學習就不會分階段。
    • 檢視個人資料
    • 樂咖黑電腦學習網
Re: 單一perl程式消耗大量cpu
« 回覆 #3 於: 2014-10-26 14:55 »
2. 開檔

開什麼檔? Log ???

不讀取會馬上刪除?

調整一下程式或是目前的程式寫法就可以解決的問題,不能解決就耗 CPU 啊
受人與魚,不如授人與漁
上海自來水來自海上;倫敦好奇人奇好敦倫

gwstudy

  • 活潑的大學生
  • ***
  • 文章數: 205
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #4 於: 2014-10-26 17:13 »
為方便大家隔空抓藥
簡單說明一下該程式的功能:
...
3.無限迴圈讀檔
4.如果讀到關鍵訊息
...
7.回到3.

我想問題出在 4 (他是待罪羔羊)。
如果沒讀到時,它會做什麼? 我想程式可能是直接跳到 7,7 馬上再跳到 3 -> 4
cpu 什麼也沒做,一直在跳來跳去。

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 單一perl程式消耗大量cpu
« 回覆 #5 於: 2014-10-26 20:30 »
用  nice 或  batch 去跑?

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #6 於: 2014-10-27 09:11 »
2. 開檔

開什麼檔? Log ???

不讀取會馬上刪除?

調整一下程式或是目前的程式寫法就可以解決的問題,不能解決就耗 CPU 啊
是log檔沒錯
目前想到是在某個時段將該天log讀一次
一天讀一次log然後寫到資料庫去應該loading就不會重了
但是讀的時間要抓好
不然漏掉訊息就糟了

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #7 於: 2014-10-27 09:17 »
為方便大家隔空抓藥
簡單說明一下該程式的功能:
...
3.無限迴圈讀檔
4.如果讀到關鍵訊息
...
7.回到3.

我想問題出在 4 (他是待罪羔羊)。
如果沒讀到時,它會做什麼? 我想程式可能是直接跳到 7,7 馬上再跳到 3 -> 4
cpu 什麼也沒做,一直在跳來跳去。
是的
但是光讀檔跟跳來跳去就吃cpu loading
不太能理解
至於為什麼要讀到關鍵訊息
因為log是由設備丟出來
其中參雜很多不必要的訊息
過濾就成為必要手段了

hoyo

  • 榮譽博士
  • 俺是博士!
  • *****
  • 文章數: 4050
  • 性別: 男
  • 有需要的時候,學習就不會分階段。
    • 檢視個人資料
    • 樂咖黑電腦學習網
Re: 單一perl程式消耗大量cpu
« 回覆 #8 於: 2014-10-27 09:43 »
一個東西讓你從右手拿到左手

明明就沒東西給你,你也要不斷的做動作,難道不會累嗎?

重點是,不斷的重複動作,就「一定」可以接收到資料?  誰跟你說的
受人與魚,不如授人與漁
上海自來水來自海上;倫敦好奇人奇好敦倫

gwstudy

  • 活潑的大學生
  • ***
  • 文章數: 205
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #9 於: 2014-10-27 13:22 »
喔,原來是這地方不理解。
cpu 只要在執行就會耗能,即使只是一個"跳"的動作。
你可以試試看,寫個程式,只是一直跳,什麼也不做。

// 語法忘了,請自行修正
while <TRUE> {
}
它會做到死,cpu loading 會飆高。

但是光讀檔跟跳來跳去就吃cpu loading
不太能理解

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
Re: 單一perl程式消耗大量cpu
« 回覆 #10 於: 2014-10-27 13:43 »
一開始 hoyo 老大就給解答了,樓主試過了嗎?

如果因為『空』迴圈 CPU 吃太重
最簡單的解法就是在迴圈裡加 sleep
下面兩個指令(ctrl-c停止)
自己比較看看吧

$ perl -e 'while(1){}'

$ perl -e 'use Time::HiRes qw(usleep); while(1){usleep(500);}'

hongbin

  • 憂鬱的高中生
  • ***
  • 文章數: 101
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #11 於: 2014-10-27 22:28 »
或者可用 cpulimit  限制程式執行的cpu 使用率
http://cpulimit.sourceforge.net/

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5394
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
Re: 單一perl程式消耗大量cpu
« 回覆 #12 於: 2014-10-28 09:58 »
sleep 加上去試看看不就知道了嗎?





經驗上來說, 就算只停個 1ms 的時間, 也會大幅改進吃 cpu 的時間.
問題是... 如果是這麼重要又急的事情, 似乎不是用這種寫法吧.... 通常這類的寫法, 停個 1s 再處理都算快的了.

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #13 於: 2014-10-28 10:02 »
這邊有個難言之隱
為什麼不加sleep
為什麼要用無限迴圈

因為受限於log
要過濾log是用時間來判斷
但是要判斷時間如果不讓他一直更新就無法取得最新的時間
除非有不用無限迴圈的方法
這個我還在思考中...
先謝謝各位前輩了

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #14 於: 2014-10-28 10:07 »
sleep 加上去試看看不就知道了嗎?





經驗上來說, 就算只停個 1ms 的時間, 也會大幅改進吃 cpu 的時間.
問題是... 如果是這麼重要又急的事情, 似乎不是用這種寫法吧.... 通常這類的寫法, 停個 1s 再處理都算快的了.

謝謝提醒了我
因為我一直以為sleep只能到秒
後來查了一下有可以到毫秒的用法
http://stackoverflow.com/questions/896904/how-do-i-sleep-for-a-millisecond-in-perl

davidju

  • 懷疑的國中生
  • **
  • 文章數: 33
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #15 於: 2014-10-28 13:42 »
有無程式碼PO來瞧瞧 :)

gwstudy

  • 活潑的大學生
  • ***
  • 文章數: 205
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #16 於: 2014-10-28 13:52 »
不是難言之隱,只是你用的方法不好,。

while <> {
}

或 tail -f logfile | yourprog.pl

建議你多看範例才能快速上手,自己摸索很容易卡關。
還有 sleep 是要減少 cpu 跳來跳去避免 cpu load 太高,你又想只睡幾毫秒,那又回到老問題了: cpu load 很高。
方法不好要改方法,不要去補丁,浪費你 coding 的生命。

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 單一perl程式消耗大量cpu
« 回覆 #17 於: 2014-10-28 23:35 »
最新的時間用 date 來取也可以,可以取過去5分鐘或1分鐘啊 ...
不用依賴 log

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 單一perl程式消耗大量cpu
« 回覆 #18 於: 2014-10-28 23:37 »
或是交給 cron 去跑,如果 log 沒變更,就直接結束。
如果擔心跑太久到下次cron還沒跑完,就用 lock file 來防止。

logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #19 於: 2014-10-28 23:56 »
程式碼在此:
引用
my $dsn="DBI:mysql:database=search;host=localhost";
my $userid="root";
my $password="password";
my $dbh=DBI->connect($dsn,$userid,$password) or print "Could not connect to database: $DBI::errstr";

eval{
$dbh->do('CREATE TABLE mytable(SN integer auto_increment primary key,Month CHAR(3),Day CHAR(2),
Time CHAR(8),MAC CHAR(17),Username VARCHAR(64))');
$dbh->disconnect or warn $dbh->errstr;
};
warn $@ if $@;

my $file1="/var/log/xxx/mytable.log";
eval{ open(LOGFILE, $file1) or die "Can't open file , $!\n"; };
print "Error:$@" if $@;   
for(;;)
{
   while(<LOGFILE>)
   {
      chomp $_;
      ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
      my $dates = strftime "%H:%M",localtime;
       
        @array=split(' ', $_);
        if(@array[0] == "$months[$mon]" && @array[1] == "$mday" && @array[2] =~ /$dates/)
        {      
        if($_ =~ /Action=do/)
        {
         @array = split(' ', $_);
         $month=@array[0];
         $day=@array[1];
         $time=@array[2];
          
         @array = split(',', $_);         
         $mac=substr @array[3],7;
         $mac1=substr($mac,0,2).":".substr($mac,3,2).":".substr($mac,6,2).":"
         .substr($mac,9,2).":".substr($mac,12,2).":".substr($mac,15,2);
         $mac1=lc $mac1;     
         $username=substr @array[6],5;
         $username =~ s/[\r\n]//;
                           
         if($mac1 =~ /(?:[A-Fa-f0-9]{2}[:-]){5}(?:[A-Fa-f0-9]{2})/)
         {
         eval{   
         $dbh=DBI->connect($dsn,$userid,$password) or print "Could not connect to database:$DBI::errstr";
         $dbh->do("set names utf8");
         my $sth=$dbh->prepare("INSERT INTO mytable(Month,Day,Time,MAC,Username)values(?,?,?,?,?)");               
         $sth->execute($month,$day,$time,$mac1,$username)or print $DBI::errstr;
         $sth->finish();         
         $dbh->disconnect or warn $dbh->errstr;
         };
         warn $@ if $@;
         }         
        }
      }
      $month="";
      $day="";
      $time="";
      $mac="";
      $username="";
      $dates="";
      
   }
    $rotate=strftime "%H:%M:%S",localtime;
    if($rotate eq "03:XX:XX")
    {
          close(LOGFILE);
          sleep 1;
          eval{ open(LOGFILE, $file1) or die "Can't open file , $!\n"; };
          print "Error:$@" if $@;
    }   
}   
« 上次編輯: 2014-10-29 00:02 由 logichom »

gwstudy

  • 活潑的大學生
  • ***
  • 文章數: 205
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #20 於: 2014-10-29 03:45 »
方法有好幾種,我針對你寫法不好的地方提供一個樣本,參考看看。

程式: print.pl
===============
#!/usr/bin/perl
while(<STDIN>){
   print $_ ."\n";
}
===============

在 terminal 打
touch my.log; tail -f my.log | ./print.pl

再開一個 terminal, 輸入:
echo AA >> my.log
你會看到第一個 terminal 會輸出 AA

上面這樣寫,cpu 很輕鬆,不會有 load 飆高的現象。

davidju

  • 懷疑的國中生
  • **
  • 文章數: 33
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #21 於: 2014-10-29 13:57 »
在 chomp $_ 的上頭加上 sleep (1)  8) 8)

操練前先休息一下

dark

  • 俺是博士!
  • *****
  • 文章數: 1581
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #22 於: 2014-10-30 19:37 »
1. 接收資料部分使用 while read , 倒建議交給 socket
perl 開 socket 很容易 , 緩衝一定有餘又不浪費資源

2. 開 socket 接資料跟讀檔是兩件事
使用 tail -f  , 若檔案重頭開始 (如 syslog 的 logrot?? <- 怎麼拼 ??)
那將會有很多行送不出來

您 /var/log/xxx/mytable.log 是怎麼來的須留意
若是 syslog() , printk() ... 這類呼叫 log deamon 寫入
那讀檔部分就交由 linux 內建 log server 較佳

若不是 , 讀檔部分要考慮重複 , 漏掉問題 ... 那將是整體中最浪費資源的


logichom

  • 懷疑的國中生
  • **
  • 文章數: 87
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #23 於: 2014-10-31 09:19 »
1. 接收資料部分使用 while read , 倒建議交給 socket
perl 開 socket 很容易 , 緩衝一定有餘又不浪費資源

2. 開 socket 接資料跟讀檔是兩件事
使用 tail -f  , 若檔案重頭開始 (如 syslog 的 logrot?? <- 怎麼拼 ??)
那將會有很多行送不出來

您 /var/log/xxx/mytable.log 是怎麼來的須留意
若是 syslog() , printk() ... 這類呼叫 log deamon 寫入
那讀檔部分就交由 linux 內建 log server 較佳

若不是 , 讀檔部分要考慮重複 , 漏掉問題 ... 那將是整體中最浪費資源的
檔案是由設備丟出來的,我的server再去設定接收該log,該log會在半夜做輪替,然後我的程式要在輪替完從新開檔讀檔
« 上次編輯: 2014-10-31 09:22 由 logichom »

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 單一perl程式消耗大量cpu
« 回覆 #24 於: 2014-11-01 09:24 »
logrotate 可以設定 prerotate 跟 postrotate 的 script 啊~

asako

  • 活潑的大學生
  • ***
  • 文章數: 242
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #25 於: 2014-11-29 11:47 »
組合一下 tail -f | grep | awk | mysql -e
cpu 會非常低

rainday

  • 鑽研的研究生
  • *****
  • 文章數: 738
  • 性別: 男
  • enhancing and optimizing
    • 檢視個人資料
Re: 單一perl程式消耗大量cpu
« 回覆 #26 於: 2014-11-29 17:10 »
如dark說所
做成daemon加上socket才是最有效率的方式
如果流量與動作不多,pipe方式是能加減的用
<0  =_=  Don't learn to hack , hack to learn.