问题描述:

I have more than 2000 JS files in my web project to be formatted. I know that Google closure compiler is good at doing so and actually I am using it to write a tool for the whole JS files' formatting. My requirement is that the formatted JS files will replace the original ones at the same place.

I wrote a Java program to look up each JS file in the web project, when there is a file found, A thread will be responsible for executing the command

java -jar compiler.jar --js C:/project/xyz/abc.js --js_output_file C:/project/xyz/abc.js`

And the original JS file(abc.js) will be formatted.

But I find that this way is not so efficient. The thing is I am using ExecutorService to run the threads and each thread takes around 10 seconds to do the formatting for a file. So you can imagine how long it takes to finish more than 2000 files.

Below is the code snippet.

ExecutorService executor = Executors.newFixedThreadPool(10);

// ...

for(File jsFile : root.listFiles()) {

Runnable formatThread = new FormatThread(jsFilePath.getAbsolutePath());

//execute command "java -jar compiler.jar in run(), handled by ProcessBuilder

executor.execute(formatThread);

}

I have tried increasing the thread pool size, but CPU and memory are soon consumed highly after the program started.

My questions are

  1. What is the efficient way to format such a large number of files by application written in Java?
  2. Is the usage of ExecutorService in my program correct and suitable for my use case?
  3. Any other Java API can format Javascript files much quickly? Actually what I need is simply remove the empty lines and user comments but no need to compress the files.

网友答案:

Starting all those tasks via command line is producing a huge overhead, since it also needs to start up a new jvm.

You can run the main method of the main class (afaik com.google.javascript.jscomp.CommandLineRunner) from the jar manifest form java code though:

for(File jsFile : root.listFiles()) {
    Runnable formatThread = () -> com.google.javascript.jscomp.CommandLineRunner.main(new String[] {"--js", jsFilePath.getAbsolutePath(), "--js_output_file", jsFilePath.getAbsolutePath()}));
    executor.execute(formatThread);
}

There may even be a more efficient way of invoking the API...

Edit:

The API is better invoked in a different way. e.g.

CompilerOptions options = new CompilerOptions();
CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
options.setCheckGlobalThisLevel(CheckLevel.OFF);
options.setOutputCharset("utf-8");
com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler(System.err);
compiler.disableThreads();
compiler.compile(SourceFile.fromFile(externsFile),
        SourceFile.fromFile(jsFile),
        options);
String result = compiler.toSource();
// TODO: write result to file
相关阅读:
Top