2011-09-01 56 views
2

有沒有一種方法可以輕鬆地在gradle任務中以明智的方式處理FileTree文件?我基本上需要等待所有文件的執行,就像使用GPars所做的一樣,但是如何使用FileTree執行此步驟?FileTree文件的異步操作?

task compressJs(dependsOn: [copyJsToBuild]) << { 
    println 'Minifying JS' 

    fileTree { 
     from 'build/js' 
     include '**/*.js' 
    }.visit { element -> 
     if (element.file.isFile()) { 
      println "Minifying ${element.relativePath}" 
      ant.java(jar: "lib/yuicompressor-2.4.6.jar", fork: true) { 
       arg(value: "build/js/${element.relativePath}") 
       arg(value: "-o") 
       arg(value: "build/js/${element.relativePath}") 
      } 
     } 
    } 
} 

這將是可愛的,如果我可以做類似.visit{}.async(wait:true),但我的谷歌搜索卻一無所獲。有沒有一種方法可以輕鬆實現這種多線程?一個元素的處理對任何其他元素的處理都沒有影響。

回答

3

之前想着去多線程,我會嘗試以下方法:

  • 在同一個JVM運行一切。爲每個輸入文件分配新的JVM效率非常低。
  • 使compressJs任務增量,以便它只在自上次運行後某些輸入文件已更改時才執行。
  • 直接運行minifier而不是通過Ant(保存爲每個輸入文件創建一個新的類加載器;不知道它是否重要)。

如果這仍然讓您對性能不滿意,並且您無法使用更高性能的縮小器,您仍然可以嘗試使用多線程。 Gradle不會幫助你,但是像GPars或Java Fork/Join框架這樣的庫。

+0

我失去了所有輸出,除非我指定'fork:true'並且運行'ant.java'。我想我可以直接使用gpars進行調查,但似乎這應該是gradle應該處理的。 –

+0

你是什麼意思你失去了所有的輸出?爲每個輸入文件分叉是非常低效的;必須有更好的方式(我希望)。此外,根據您傳遞給yuicompressor的參數來判斷,您似乎覆蓋了文件。這通常不是一個好主意;在這種情況下,這意味着copyJsToBuild和compressJs都不會是最新的。你不能擺脫copyJsToBuild並讓縮小器通過選擇不同的輸入和輸出文件來完成複製嗎?與一般的編程一樣,在進行多線程之前,您應該專注於改進單線程的情況。 –

+0

隨着JAR的任何其他調用,輸出至STDOUT的輸出將丟失。我之前把它作爲一個SO問題發佈;這是做這項工作的唯一方法。無論如何,文件處理應該是異步的。由於我使用堅固的SSD運行8個內核,因此我可能會獲得3-8倍的加速。現在我處理器綁定,這是愚蠢的。 –

1

GPars解決方案。請注意,可以修改compress()函數以正確接受源dir/target dir/etc,但由於我所有的名稱都是一致的,因此我現在只使用一個參數。我能夠將我的編譯時間從7.3s減少到5.4s,只有3個文件被縮小。我看到構建時間失控,所以我總是對這種行爲表現謹小慎微。

import groovyx.gpars.GParsPool 

buildscript { 
    repositories { 
     mavenCentral() 
    } 

    dependencies { 
     classpath 'org.codehaus.gpars:gpars:0.12' 
    } 
} 

def compress(String type) { 
    def elementsToMinify = [] 
    fileTree { 
     from type 
     include "**/*.$type" 
    }.visit { element -> 
     if (element.file.isFile()) { 
      elementsToMinify << element 
     } 
    } 

    GParsPool.withPool(8) { 
     elementsToMinify.eachParallel { element -> 
      println "Minifying ${element.relativePath}" 
      def outputFileLocation = "build/$type/${element.relativePath}" 
      new File(outputFileLocation).parentFile.mkdirs() 
      ant.java(jar: "lib/yuicompressor-2.4.6.jar", fork: true) { 
       arg(value: "$type/${element.relativePath}") 
       arg(value: "-o") 
       arg(value: outputFileLocation) 
      } 
     } 
    } 
} 

task compressJs { 
    inputs.dir new File('js') 
    outputs.dir new File('build/js') 

    doLast { 
     compress('js') 
    } 
} 

task compressCss { 
    inputs.dir new File('css') 
    outputs.dir new File('build/css') 

    doLast { 
     compress('css') 
    } 
}