<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

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

        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 閱讀(1494) | 評論 (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 閱讀(744) | 評論 (2)編輯 收藏

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

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

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

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

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


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

        讀《代碼大全2》,已經讀了一半,喘口氣。總結八個字:百科全書,受益匪淺。小到一個賦值語句、一個循環的編寫,大到需求分析、架構設計,無所不包,看后半部分目錄,更是扯到了重構、軟件工藝、程序員的性格特征這樣的話題。恰好手邊的工作暫時比較有閑,可以實踐下“創建高質量的代碼”中的部分建議,晚上讀書,第二天就重構,樂在其中。這一部分中對設計、子程序、類、變量、語句的處理建議,可能你平常已經在這么做,可作者這么精辟地概括出來讓人嘆服,而有些地方是你平常絕對很少注意的,特別是在變量和三種常見控制語句的處理上。
      
        說說我認為是缺點的地方,就是作者貌似對函數式語言了解很少,舉的例子全部用的是廣泛應用的靜態語言(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 閱讀(7699) | 評論 (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 閱讀(1124) | 評論 (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." ( 她在時鐘餐館出生,重新找到藝術而且將永遠是一支富有才華的球隊。這個精彩的夜晚給了我們徽章的顏色:藍色和黑色在金黃色的星狀背景上面。她叫國際,因為 我們是世界的兄弟!)意大利《米蘭日報》的國際米蘭專家蒙蒂說:“他們選擇的新球衣的顏色反映了他們浪漫主義傾向,黑色代表黑夜,而藍色代表大海。”

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

    posted @ 2008-03-10 18:38 dennis 閱讀(473) | 評論 (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 閱讀(683) | 評論 (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 閱讀(927) | 評論 (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 閱讀(1335) | 評論 (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 閱讀(5090) | 評論 (2)編輯 收藏

    僅列出標題
    共56頁: First 上一頁 28 29 30 31 32 33 34 35 36 下一頁 Last 
    主站蜘蛛池模板: 国产一级一毛免费黄片| 亚洲日本中文字幕天天更新| 特级毛片在线大全免费播放| 啦啦啦手机完整免费高清观看| 亚洲日本视频在线观看| 亚欧免费视频一区二区三区| 亚洲宅男天堂a在线| 青青草a免费线观a| 亚洲国产精品无码久久久秋霞1| 在线观看免费a∨网站| 含羞草国产亚洲精品岁国产精品 | 一区二区三区免费在线观看| 毛茸茸bbw亚洲人| 日韩电影免费在线观看| 亚洲精品午夜在线观看| 在线观看无码的免费网站| 免费人成再在线观看网站| 久久久亚洲精品蜜桃臀| 在线免费播放一级毛片| 亚洲韩国在线一卡二卡| 国产成人免费网站| 老司机精品视频免费| 国产精一品亚洲二区在线播放| 久久精品国产免费观看| 精品亚洲456在线播放| 亚洲精品无码久久毛片| 黄页免费在线观看| 狠狠色伊人亚洲综合网站色| 免费人成激情视频| 久久久久久夜精品精品免费啦| 亚洲国产日韩精品| 国产乱辈通伦影片在线播放亚洲 | 日韩免费无码视频一区二区三区| 亚洲成a人片在线观看无码| 亚洲免费福利视频| 国产亚洲精品美女久久久久| 亚洲kkk4444在线观看| 亚洲专区先锋影音| 69天堂人成无码麻豆免费视频| APP在线免费观看视频| caoporn国产精品免费|