莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

              jruby本質上也是啟動一個jvm,然后去讀Ruby腳本并解釋執行(也可以編譯),因此jprofiler理所當然也可以去監控jruby腳本的執行。
          執行     
          jruby hello.rb
          等價于執行:
          java -Xmx378m -Xss1024k  -Djruby.home=/usr/local/jruby
                                             -
          Djruby.lib=/usr/local/jruby/lib Djruby.script=jruby org.jruby.Main hello.rb
          這一點,你可以通過ps aux |grep jruby 看到。因此配置jprofiler就簡單了,在VM arguments加上這些參數(可以包括jruby的參數),比如我的VM arguments配置如下:

          -server -Xmx378m -Xss1024k -Djruby.script=jruby -Djruby.thread.pooling=true
                            
          -Djruby.jit.threshold=-Djruby.compile.fastest=true
                             -
          Djruby.home=D:\jruby\jruby-1.1RC2 -Djruby.lib=D:\jruby\jruby-1.1RC2\lib

          Main class or executable JAR填上:org.jruby.Main。然后就是Arguments一欄填上你的腳本位置:
          D:\ruby\lib\hello.rb

          最后,別忘了將jruby/lib目錄下的bsf.jar和jruby.jar加入Class Path。

          大功告成,你可以用jprofiler去觀察GC、線程和鎖、Heap等等了。

          posted @ 2008-03-24 15:26 dennis 閱讀(1495) | 評論 (0)編輯 收藏

              看了javaeye上一個解決約瑟夫環的問題的帖子,就想能不能用scheme來解決。如果采用推導出的數學公式來處理當然很簡單了:
          (define (joseph n m)
            (define (joseph
          -iter init s)
              (
          if (> init n)
                  (
          + s 1)
                  (joseph
          -iter (+ init 1) (remainder (+ s m) init))))
            (joseph
          -iter 2 0))
              我想是否可以用一般的模擬算法來實現?也就是模擬一個循環鏈表,每次刪除第m個元素。弄了個比較丑陋的實現:

          (define (enumrate-interval low high)
            (
          if (> low high)
                
          '()
                (cons low (enumrate-interval (+ low 1) high))))
          (define (delete
          -last list)
            (
          if (eq? (cdr list) '())
                '()
                (cons (car list) (delete-last (cdr list)))))

          (define (joseph
          -iter init list it) 
            (let ((m (remainder it (length list))))
             (cond ((
          = m 0) (delete-last list))
                   ((
          = m 1) (append (cdr list) (reverse init)))
                   (
          else
                     (joseph
          -iter (cons (car list) init) (cdr list) (- m 1))))))
          (define (joseph n m)
              (define (joseph
          -list list m)
                (display list) 
                (newline)
                (
          if (eq? (cdr list) '())
                    (car list)
                    (joseph
          -list (joseph-iter '() list m) m)))

          計算(joseph 8 3)的過程如下:
          (1 2 3 4 5 6 7 8)
          (4 5 6 7 8 1 2)
          (7 8 1 2 4 5)
          (2 4 5 7 8)
          (7 8 2 4)
          (4 7 8)
          (4 7)
          (7)
          7

          看了這個計算過程就知道我這個方法多糟糕,每次都重新構造列表。不知道看blog的大大們有沒有更好的思路?

          posted @ 2008-03-20 19:15 dennis 閱讀(746) | 評論 (2)編輯 收藏

          1、應當有一個詳查表,關注reviewer過去遇到的問題和缺陷,對常見錯誤保持警惕

          2、詳查應當專注于檢測錯誤,而非修正

          3、詳查的角色包括:
          1)主持人:負責分配復查任務,報告詳查結果,主持詳查回憶,他需要能夠理解被詳查代碼的相關技術細節,整體上控制詳查進度
          2)作者:代碼的作者,負責陳述項目的概況,解釋設計和代碼中不清晰的部分
          3)復查者(reviewer,《代碼大全2》稱為評論員,感覺不是很恰當):負責實際復查的工作的執行,負責找出缺陷。
          4)記錄員:記錄發現的錯誤,記錄任務的指派情況,記錄會議
          5)管理人員:詳查是一個純技術性的復查,應當避免管理人員的介入。如果管理人員介入了詳查,那么參與的人可能會覺的在被評價,而不是去復查材料,導致焦點從技術問題轉移到行政問題。按國情,這種情況相當常見。

          4、明確詳查的目的是發現設計或者代碼的缺陷,而不是探索替代方案,或者爭論誰對誰錯,其目的絕不應該是批評作者的設計和代碼。如果出現復查者做出不恰當的評價和發言,主持人應該制止,引導詳查的活動的健康進行。這一點我覺的相當重要,對事而不對人。

          5、詳查會議后,主持人撰寫詳查報告,最好能提交給管理人員一份,并且應當及時進入返工環節,將缺陷分配給某人去修復(往往是原作者),并及時跟進監督缺陷的修復情況。


          posted @ 2008-03-20 10:27 dennis 閱讀(1491) | 評論 (1)編輯 收藏

              讀《代碼大全2》,已經讀了一半,喘口氣??偨Y八個字:百科全書,受益匪淺。小到一個賦值語句、一個循環的編寫,大到需求分析、架構設計,無所不包,看后半部分目錄,更是扯到了重構、軟件工藝、程序員的性格特征這樣的話題。恰好手邊的工作暫時比較有閑,可以實踐下“創建高質量的代碼”中的部分建議,晚上讀書,第二天就重構,樂在其中。這一部分中對設計、子程序、類、變量、語句的處理建議,可能你平常已經在這么做,可作者這么精辟地概括出來讓人嘆服,而有些地方是你平常絕對很少注意的,特別是在變量和三種常見控制語句的處理上。
            
              說說我認為是缺點的地方,就是作者貌似對函數式語言了解很少,舉的例子全部用的是廣泛應用的靜態語言(c/c++,java,vb)。例如作者有這么一句話:如果為我工作的程序員用遞歸去計算階乘,那么我寧愿換人。作者對遞歸的態度相當謹慎,這在靜態命令式語言中顯然是正確的,但是在函數式語言中,由于有尾遞歸優化的存在,遞歸反而是最自然的形式,況且我打心里認為遞歸更符合人類思維。請注意,在FP中只有尾遞歸的程序才是線性迭代的,否則寫出來的遞歸可能是線性遞歸或者樹形遞歸,兩種情況下都可能導致堆棧溢出并且性能較差。

          scheme寫階乘:
          (define (fac n)
            (
          if (= 1 n)
                
          1
                (
          * n (fac (- n 1)))))
          顯然這個版本不是尾遞歸,計算過程是一個線性遞歸過程,計算(fac 4)的過程如下:
          (* 4 (fac 3))
          (* 4  (3 * (fac 2)))
          (* 4  (3 * (* 2 (fac 1))))
          (* 4  (3 * (* 2 1)))
          (* 4  (3 * 2))
          (* 4 6)
          24
              因為解釋器是采用應用序求值,需要將表達式完全展開,然后依次求值,在這個過程中,解釋器內部需要保存一條長長的推遲計算的軌跡。
          改寫成一個尾遞歸版本:
          (define (fac n)
            (define (fac
          -iter product n)
              (
          if (= 1 n)
                  product
                  (fac
          -iter (* n product) (- n 1))))
            (fac
          -iter 1 n))
          我們來看看它的計算過程:
          (fac-iter 1 4)
          (fac-iter 4 3)
          (fac-iter 12 2)
          (fac-iter 24 1)
          24
          可以看到,在這個過程中,解釋器不需要保存計算軌跡,迭代的中間結果通過product變量來保存,這是一個線性迭代的計算過程。
          最后再看一個斐波拉契數列的例子:
          (define (fib n)
            (cond ((
          = n 0) 0)
                      ((
          = n 11)
                      (
          else
                           (+ (fib (- n 1))  (fib (- n 2))))))

          這個計算過程展開是一個樹形遞歸的過程(為什么說是樹形?展開下計算過程就知道),改寫為線性迭代:
          (define (fib n)
            (define (fib
          -iter a b count)
               (
          if (= count 0)
                   b
                   (fib
          -iter (+ a b) a (- count 1))))
           (fib
          -iter 1 0 n))

               上述的內容在sicp第一章里有更詳細的介紹和討論。

          posted @ 2008-03-18 19:34 dennis 閱讀(7704) | 評論 (11)編輯 收藏

              swf-util是一個使用Ruby讀取swf頭信息(高度、寬度、文件大小、幀數等等)、壓縮和解壓縮swf文件的工具類庫,改寫自java版本。
          項目主頁:http://code.google.com/p/swf-util/
          協議:MIT License
          平臺:JRuby or c ruby 1.8.x on linux
          依賴BitStruct,請到這里下載安裝bit-struct。在windows上的Ruby Zlib的實現有問題,linux下正常,使用JRuby也可以。
          使用例子:
          #read swf head
          require 'swf_util'

          header=SwfUtil::read_header("test.swf")
          puts header.inspect
          header.version
          header.frame_rate
          header.width
          header.frame_count


          #decompress swf
          SwfUtil::decompress_swf("test.swf")

          #compress swf
          SwfUtil::compress_swf("test.swf")


          posted @ 2008-03-11 14:41 dennis 閱讀(1126) | 評論 (0)編輯 收藏

             

               1908年的3月9日,四十多名“叛逃者”在奧雷菲奇的洛奧洛吉奧飯館聚會, 宣布成立國際米蘭足球俱樂部,吉奧瓦尼.帕拉米西奧蒂成為俱樂部第一任主席,俱樂部成立宣言如下:”nascerà qui, al ristorante “l'orologio”, ritrovo di artisti e sarà sempre una squadra di talento. Questa notte splendida darà i colori al nostro stemma: il nero e l'azzurro sullo sfondo d'oro delle stelle. Si chiamerà Internazionale, perchè noi siamo fratelli del mondo." ( 她在時鐘餐館出生,重新找到藝術而且將永遠是一支富有才華的球隊。這個精彩的夜晚給了我們徽章的顏色:藍色和黑色在金黃色的星狀背景上面。她叫國際,因為 我們是世界的兄弟?。┮獯罄睹滋m日報》的國際米蘭專家蒙蒂說:“他們選擇的新球衣的顏色反映了他們浪漫主義傾向,黑色代表黑夜,而藍色代表大海。”

              inter 100歲了,而我成為它的球迷也已經有10年了,怒過、罵過、笑過甚至哭過,多少個熬夜看球的夜晚,點點滴滴涌上心頭。

          posted @ 2008-03-10 18:38 dennis 閱讀(474) | 評論 (1)編輯 收藏

              最近一直在寫Ruby腳本,說出來你可能不相信,我用Ruby寫游戲腳本。用的是JRuby,采用JRuby是因為定時器的問題,Ruby1.8.6因為線程是用戶空間內的本地線程,標準庫沒有提供強大的定時器功能,而對于游戲邏輯有相當多的任務需要定時處理,權衡之下,最后決定使用JRuby,封裝了java的ScheduledExecutorService,等以后Ruby有更完善的定時器的時候就切換回來(我猜測引入了native thread的Ruby1.9應該有更強大的定時器),基本滿足了要求。這一過程也更讓我覺的JRuby是個非常有前途的項目,利用Ruby的語法以及動態語言的高效加上java極其豐富的類庫,這樣的組合有莫大的威力,況且 JRuby的性能比之c ruby在某些方面更有優勢,在1.1出來后應該可以有一個更大的提升。

              寫Ruby腳本唯一比較郁悶的是重構,盡管Netbeans比RDT提供了更好的重構功能,但是對于一些復雜重構仍然沒有比較好的支持,況且我也不敢完全信任IDE的自動化,這種時候更顯示出完備的單元測試的重要性,如果沒有單元測試,對Ruby腳本的重構簡直難以想象。另外一個比較麻煩的是,Ruby對二進制的處理并不是很方便,盡管使用了bit-struct,但是它只能支持定長的數據結構,而不是可變長度的array list,變長的string,或者switch結構;盡管我自己做了簡單的擴展,仍然很局限。幸好我遇到這樣的情況不多,通過其他手段變通處理也還能接受。后來javaeye上的莊表偉老大發布了DynamicStruct,這個才是根本解決之道,兩者結合使用應該可以處理所有情況了。不過那時我的協議處理部分都已經完成,下次有機會再試試。
              讀書嘛,最近終于開始讀買了許久的《代碼大全2》,以前是真怕這種大部頭,看著就沒信心讀完,哇哈哈,沒想到一讀下去就一發不可收拾,真是好書一本,就軟件構建中的設計一章就值回書錢了。又利用晚上在重讀sicp前三章,在注釋這樣的邊邊角角原來也非常有價值,例如對閉包和組合的解釋,靜態語言由于有太多的聲明式結構(struct、class etc.)反而對組合造成了阻礙和懲罰,而在Lisp中由于通用的組合粘合劑cons的存在,可以以一種統一的方式去處理組合結構,模擬各種復雜的數據結構。今天托同事在當當上買的書到了,《unix編程藝術》到手,這書按牛人的說法是sicp的實踐版,不讀就相當遺憾了。

          posted @ 2008-03-04 19:09 dennis 閱讀(686) | 評論 (1)編輯 收藏

          重定向標準輸入的實現:
          1)close-then-open: close(0) ; fd=open("test",O_RDONLY); fd將是stdin。
          2)open-close-dup-close:
          fd=open(file),打開stdin將要重定向的文件;close(0);new_fd=dup(file);close(fd);new_fd就是被重定向的stdin
          3)open-dup2-close:
          fd=open(file);new_fd=dup2(fd,0);close(fd);

          重定向標準輸出的實現:
            父進程fork();子進程close(1);create("g",0644),此時子進程的stdout被重定向到g;接下來子進程exec某個程序,文件描述符屬于進程屬性,exec調用不會改變他們,那么運行的程序的標準輸出將被送到g,由此實現了標準輸出重定向。

          本質上重定向的實現是依賴兩個原則:
          1、標準輸入、標準輸出和標準錯誤分別是0、1和2
          2、最低可用描述符:打開文件時,為此文件安排的描述符總是進程內打開文件數組的最低可用位置的索引。

          管道:
            匿名管道:適合于有親緣關系的進程,通過pipe函數實現。
            有名管道:通過mkfifo函數實現,實現進程間的雙向通訊可以采用兩個有名管道實現,也可以采用socketpair調用。

          posted @ 2008-02-29 11:16 dennis 閱讀(932) | 評論 (0)編輯 收藏

              今天有點空閑,想想用Ruby寫個NFA試試。從正則表達式構造NFA采用經典的Thompson算法:正則表達式 -> 后綴表達式 -> 構造NFA。構造了NFA后,用之匹配字符串。一句話,寫了個玩具的正則表達式引擎,支持concatenation、alternation以及*、?、+量詞,不支持反向引用和轉義符。測試了下與Ruby自帶的正則表達式引擎的性能對比,慢了3倍。構造NFA沒什么問題,主要是匹配運行寫的爛,有空再改改。

          nfa.rb

          module NFA
            
          class NFA
              
          def initialize(state)
                @state
          =state
              end
              
          def step(clist,c)
                
          return clist if clist.size==0;
                nlist
          =[] 
                allNull 
          = true
                matched 
          = false
                clist.each do 
          |t|
                  
          if !t.nil?
                    allNull 
          = false if t.c!=-1
                    
          if t.c == c && t.end.type ==1 then
                      matched 
          = true
                      nlist.push(t.end.out1) 
          if !t.end.out1.end.nil? 
                      nlist.push(t.end.out2) 
          if !t.end.out2.end.nil?
                    elsif (t.c 
          == c && t.end.type == 0) then
                      matched 
          = true;
                      
          return ListUitls.new_list(t);
                    elsif (t.c 
          == -1 && !t.end.nil?) then
                      nlist.push(t.end.out1);
                      nlist.push(t.end.out2);
                    end
                  end
                end        
                
          return step(nlist, c) if (allNull)
                
          return step(nlist, c) if (!matched)
                nlist
              end
              
          def test?(s)
                match(@state,s)
              end
              
          def match(state,s)
                clist 
          =[]
                clist.push(state.out1);
                clist.push(state.out2);
                s.each_byte do 
          |c|
                  c 
          =c&0xFF;
                  clist 
          = step(clist, c);
                  
          return false if clist.size==0
                end
                
          return is_match?(clist)
              end
              
          def is_match?(clist)
                clist.each  do 
          |t|
                  
          return true if !t.nil? and t.c==-1 and t.end and t.end.is_matched? 
                end
                false
              end
            end
            
          class Paren
              attr_accessor:n_alt,:n_atom
            end
            
          class State
              attr_accessor :out1,:out2,:type
              
          def initialize(out1,out2)
                @out1
          =out1
                @out2
          =out2
                @type
          =1
              end
              
          def is_matched?
                
          return @type==0
              end
            end
            
          class Transition
              attr_accessor :c,:end
              
          def initialize(c)
                @c
          =c
              end   
            end
            
          class Frame
              attr_accessor :start,:outs
              
          def initialize(start,outs)
                @start
          =start
                @outs
          =outs
              end
            end
            
          class ListUitls
              
          def self.link(list,state)
                list.each{
          |t| t.end=state}
              end
              
          def self.append(list1,list2)
                list1
          +list2
              end
              
          def self.new_list(out)
                result
          =[]
                result.push(out)
                result      
              end
            end
            
          def self.compile(re)
              post 
          = re2post(re)
              
          raise ArgumentError.new,"bad regexp!" if post.nil?
              state 
          = post2nfa(post);
              
          raise RuntimeError.new,"construct nfa from postfix fail!" if state.nil?        
              
          return NFA.new(state);
            end
            
          def self.post2nfa(postfix)
              stack
          =[]
              s
          =nil
              t
          =t1=t2=nil 
              e1
          =e2=e=nil 
              
          return nil if postfix.nil?
              postfix.each_byte do 
          |p|
                case p.chr
                when 
          '.':
                  e2 
          = stack.pop() 
                  e1 
          = stack.pop() 
                  ListUitls.link(e1.outs, e2.start) 
                  stack.push(Frame.new(e1.start, e2.outs)) 
                when 
          '|':
                  e2 
          = stack.pop() 
                  e1 
          = stack.pop() 
                  t1 
          = Transition.new(-1)
                  t2 
          = Transition.new(-1
                  t1.end 
          = e1.start 
                  t2.end 
          = e2.start 
                  s 
          = State.new(t1, t2) 
                  stack.push(Frame.new(s, ListUitls.append(e1.outs, e2.outs))) 
                when 
          '?':
                  e 
          = stack.pop() 
                  t1 
          = Transition.new(-1)
                  t2 
          = Transition.new(-1
                  t1.end 
          = e.start 
                  s 
          = State.new(t1, t2) 
                  stack.push(Frame.new(s, ListUitls.append(e.outs, ListUitls.new_list(t2)))) 
                when 
          '*':
                  e 
          = stack.pop() 
                  t1 
          = Transition.new(-1)
                  t2 
          = Transition.new(-1)
                  t1.end 
          = e.start 
                  s 
          = State.new(t1, t2) 
                  ListUitls.link(e.outs, s) 
                  stack.push(Frame.new(s, ListUitls.new_list(s.out2))) 
                when 
          '+':
                  e 
          = stack.pop() 
                  t1 
          = Transition.new(-1
                  t2 
          = Transition.new(-1)
                  t1.end 
          = e.start 
                  s 
          = State.new(t1, t2) 
                  ListUitls.link(e.outs, s) 
                  stack.push(Frame.new(e.start, ListUitls.new_list(t2))) 
                
          else
                  t 
          = Transition.new(p) 
                  s 
          = State.new(t, Transition.new(-1)) 
                  stack.push(Frame.new(s, ListUitls.new_list(s.out1))) 
                end
              end
              e 
          = stack.pop() 
              
          return nil if stack.size()>0
              end_state 
          = State.new(nil, nil) 
              end_state.type
          =0
              e.outs.each do 
          |tran|
                
          if tran.c!=-1
                  t1 
          = Transition.new(-1)
                  t2 
          = Transition.new(-1
                  s
          =State.new(t1,t2)
                  tran.end
          =s
                  s.out1.end
          =end_state
                  s.out2.end
          =end_state
                
          else
                  tran.end
          =end_state         
                end
              end
              start 
          = e.start 
              
          return start 
            end
            
          def self.re2post(re)
              n_alt 
          = n_atom = 0 
              result
          =""
              paren
          =[]
              re.each_byte do 
          |c|
                case c.chr  
                when 
          '(' then
                  
          if (n_atom > 1) then
                    n_atom
          -=1 
                    result
          <<"."
                  end
                  p 
          =Paren.new 
                  p.n_alt 
          = n_alt 
                  p.n_atom 
          = n_atom 
                  paren.push(p) 
                  n_alt 
          = n_atom = 0
                when 
          '|' then
                  
          if (n_atom == 0)
                    
          return nil
                  end
                  
          while (n_atom-=1> 0 
                    result
          <<"."
                  end
                  n_alt
          +=1
                when 
          ')' then
                  
          if (paren.size() == 0)
                    
          return nil
                  end                
                  
          if (n_atom == 0)
                    
          return nil 
                  end
                  
          while (n_atom-=1)>
                    result
          <<"." 
                  end
                  
          while(n_alt>0)  
                    result
          <<"|" 
                    n_alt
          -=1
                  end
                  p 
          = paren.pop()
                  n_alt 
          = p.n_alt 
                  n_atom 
          = p.n_atom 
                  n_atom
          +=1
                when 
          '*','+','?':
                  
          if (n_atom == 0)
                    
          return nil 
                  end
                  result
          <<
                
          else 
                  
          if (n_atom > 1
                    n_atom
          -=1 
                    result
          <<"."
                  end
                  result
          <<
                  n_atom
          +=1
                end
              end
              
          return nil if paren.size()>0
              
          while ( (n_atom-=1)> 0)
                result
          <<"." 
              end
              
          while(n_alt>0)
                n_alt
          -=1
                result
          <<"|" 
              end
              result
            end
          end

          使用:
           nfa = NFA::compile("a(bb)+a(cdf)*")
           
          assert nfa.test?("abba")
           
          assert nfa.test?("abbbba")
           
          assert !nfa.test?("a"
           
          assert !nfa.test?("aa"
           
          assert nfa.test?("abbacdf")
           
          assert nfa.test?("abbbbacdfcdf")
           
          assert !nfa.test?("bbbbacdfcdf")
           
          assert !nfa.test?("abbbacdfcdf")
           
          assert !nfa.test?("abbbbacdfdf")
           
          assert !nfa.test?("abbbbacdfdfg")


          posted @ 2008-02-25 17:46 dennis 閱讀(1338) | 評論 (1)編輯 收藏

              在《程序員》最新一期有個專題介紹java開源nio框架,其中談到了mina和grizzly。mina我還算比較熟悉,寫過一些代碼,也嘗試去讀過源碼。而grizzly是第一次聽說,這個項目是sun的一個開源nio框架,是2004年在GlassFish項目中誕生的,一開始是一個http web server,用于取代Tomcat的Coyote Connector和Sun WebServer,2007年7月1.5版本發布并宣布成為開源項目,項目主頁在https://grizzly.dev.java.net
              grizzly與mina的性能比較(基于2007年JavaOne會議上的ppt)


              GlassFish vs Tomcat


            
               grizzly的設計與一般的nio框架相比是比較不同的,主要不同點在于讀和寫都是采用blocking方式,并且使用臨時selector;線程模型可配置,不過據作者介紹在跑一個selector主線程處理ACCEPT,用線程池處理read和write性能表現最好,這點不出意料。

          posted @ 2008-02-23 19:13 dennis 閱讀(5091) | 評論 (2)編輯 收藏

          僅列出標題
          共56頁: First 上一頁 28 29 30 31 32 33 34 35 36 下一頁 Last 
          主站蜘蛛池模板: 乐至县| 汝阳县| 景宁| 乌恰县| 会同县| 沈丘县| 江华| 汝南县| 天柱县| 临沧市| 固原市| 山东| 安国市| 无棣县| 新津县| 内江市| 本溪| 临夏县| 尼勒克县| 万州区| 裕民县| 日喀则市| 丘北县| 麻城市| 晋江市| 唐海县| 靖边县| 新乡县| 文安县| 达孜县| 当阳市| 秀山| 社会| 丹江口市| 湾仔区| 义乌市| 乐清市| 湖南省| 曲松县| 保定市| 德化县|