1 package shared; 2 3 import java.io.File; 4 import java.io.PrintStream; 5 import java.lang.management.ManagementFactory; 6 import java.lang.reflect.Method; 7 import java.net.UnknownHostException; 8 import java.util.ArrayList; 9 import java.util.Arrays; 10 import java.util.Collections; 11 import java.util.Comparator; 12 import java.util.List; 13 import java.util.Map; 14 import java.util.Random; 15 import java.util.concurrent.ThreadLocalRandom; 16 17 public class Shared { 18 19 20 /*--------------------------------------------------------------*/ 21 /*---------------- Environment ----------------*/ 22 /*--------------------------------------------------------------*/ 23 24 25 public static boolean ENV=(System.getenv()!=null); 26 public static boolean WINDOWS=envContainsPair("OS", "Win", true); 27 public static boolean MAC=envContainsPair("OS", "Mac", true); 28 //https://stackoverflow.com/questions/14288185/detecting-windows-or-linux 29 public static boolean LINUX=envContainsPair("OS", "nix", true) || envContainsPair("OS", "nux", true) || envContainsPair("OS", "aix", true); 30 public static boolean SOLARIS=envContainsPair("OS", "sunos", true); 31 public static boolean GENEPOOL=envContainsPair("NERSC_HOST", "genepool", false);//Probably deprecated 32 public static boolean DENOVO=envContainsPair("NERSC_HOST", "denovo", false);//Almost certainly deprecated 33 public static boolean CORI=envContainsPair("NERSC_HOST", "cori", false); 34 public static boolean NERSC=envContainsKey("NERSC_HOST"); 35 public static boolean AWS=envContainsKey("EC2_HOME"); 36 public static boolean AMD64="amd64".equalsIgnoreCase(System.getProperty("os.arch")); 37 private static String HOSTNAME; 38 setTaxServer(String path)39 public static void setTaxServer(String path){ 40 taxServerNersc=taxServerAws=path; 41 } 42 43 private static String taxServerNersc="https://taxonomy.jgi.doe.gov/"; 44 private static String ntSketchServerNersc="https://nt-sketch.jgi.doe.gov/"; 45 private static String riboSketchServerNersc="https://ribo-sketch.jgi.doe.gov/"; 46 private static String proteinSketchServerNersc="https://protein-sketch.jgi.doe.gov/"; 47 private static String refseqSketchServerNersc="https://refseq-sketch.jgi.doe.gov/"; 48 49 private static String taxServerAws="http://bbtaxonomy.org:3068/"; 50 private static String ntSketchServerAws="http://nt-sketch.org:3071/"; 51 private static String riboSketchServerAws="http://ribo-sketch.org:3073/"; 52 private static String proteinSketchServerAws="http://protein-sketch.org:3074/"; 53 private static String refseqSketchServerAws="http://refseq-sketch.org:3072/"; 54 taxServer()55 public static String taxServer(){return awsServers ? taxServerAws : taxServerNersc;} ntSketchServer()56 public static String ntSketchServer(){return awsServers ? ntSketchServerAws : ntSketchServerNersc;} riboSketchServer()57 public static String riboSketchServer(){return awsServers ? riboSketchServerAws : riboSketchServerNersc;} proteinSketchServer()58 public static String proteinSketchServer(){return awsServers ? proteinSketchServerAws : proteinSketchServerNersc;} refseqSketchServer()59 public static String refseqSketchServer(){return awsServers ? refseqSketchServerAws : refseqSketchServerNersc;} 60 61 public static boolean awsServers=false; 62 envContainsPair(String key, String value, boolean loose)63 public static boolean envContainsPair(String key, String value, boolean loose){ 64 Map<String, String> map=System.getenv(); 65 String v=map.get(key); 66 if(value==null || v==null){return v==value;} 67 return loose ? v.contains(value.toLowerCase()) : value.equalsIgnoreCase(v); 68 } 69 envContainsKey(String key)70 public static boolean envContainsKey(String key){ 71 Map<String, String> map=System.getenv(); 72 return map.containsKey(key); 73 } 74 HOSTNAME()75 public static String HOSTNAME(){ 76 if(HOSTNAME==null){ 77 try { 78 java.net.InetAddress localMachine = java.net.InetAddress.getLocalHost(); 79 HOSTNAME=localMachine.getHostName(); 80 } catch (UnknownHostException e) { 81 // TODO Auto-generated catch block 82 // e.printStackTrace(); 83 HOSTNAME="unknown"; 84 } catch (NullPointerException e) { 85 // TODO Auto-generated catch block 86 // e.printStackTrace(); 87 HOSTNAME="unknown"; 88 } catch (Throwable e) { 89 HOSTNAME="unknown"; 90 } 91 } 92 return HOSTNAME; 93 } 94 95 96 /*--------------------------------------------------------------*/ 97 /*---------------- Stuff ----------------*/ 98 /*--------------------------------------------------------------*/ 99 main(String[] args)100 public static void main(String[] args){ 101 COMMAND_LINE=args; 102 mainClass=Shared.class; 103 assert(false) : fullCommandline(); 104 } 105 106 public static int LOGICAL_PROCESSORS=CALC_LOGICAL_PROCESSORS(); 107 private static int THREADS=setThreads(-1); 108 109 private static int READ_BUFFER_NUM_BUFFERS=setBuffers(); 110 private static int READ_BUFFER_LENGTH=200; 111 private static long READ_BUFFER_MAX_DATA=400000; 112 113 public static boolean OUTPUT_KMG=true; 114 115 /** Temporary, for testing; should be made non-global */ 116 public static boolean AMINO_IN=false; 117 118 //TODO: For some reason, it seems as though GAPBUFFER must equal exactly 1/2 of GAPLEN. Not good; 1/4 would be far better. 119 120 public static final int GAPBUFFER=64; //TODO: Seems to break less than 64, for some reason 121 public static final int GAPBUFFER2=2*GAPBUFFER; 122 public static final int GAPLEN=128; //TODO: May break when over 128 123 public static final int MINGAP=GAPBUFFER2+GAPLEN; 124 public static final int GAPCOST=Tools.max(1, GAPLEN/64); 125 public static final byte GAPC='-'; 126 127 public static String BBMAP_VERSION_STRING="38.92"; 128 public static String BBMAP_VERSION_NAME="Stable Shuffle"; 129 130 public static boolean TRIM_READ_COMMENTS=false; 131 public static boolean TRIM_RNAME=false; //For mapped sam reads 132 133 public static boolean USE_JNI=(CORI || DENOVO || GENEPOOL || NERSC || AWS || (AMD64 && (LINUX || MAC))) && !WINDOWS; 134 public static boolean USE_MPI=false; 135 public static boolean MPI_KEEP_ALL=true; 136 /** Use ConcurrentReadInputStreamMPI instead of D for this instance */ 137 public static boolean USE_CRISMPI=true; 138 public static int MPI_RANK=0; 139 public static int MPI_NUM_RANKS=1; 140 141 public static int FASTA_WRAP=70; 142 public static byte FAKE_QUAL=30; 143 144 public static boolean FIX_EXTENSIONS=true; 145 146 /** True if assertions are enabled. */ 147 private static boolean EA=false; 148 EA()149 public static boolean EA(){return EA;} 150 151 public static String BBMAP_CLASS=null; 152 public static Class<?> mainClass=null; 153 public static String[] COMMAND_LINE=null; 154 155 public static final byte PLUS=0; 156 public static final byte MINUS=1; 157 /** Index with strand number */ 158 public static final String[] strandCodes={"+", "-", "?"}; 159 public static final char[] strandCodes2={'+', '-', '?'}; 160 JVM_ARGS()161 public static List<String> JVM_ARGS(){ 162 return ManagementFactory.getRuntimeMXBean().getInputArguments(); 163 } 164 fullCommandline()165 public static String fullCommandline(){ 166 StringBuilder sb=new StringBuilder(); 167 sb.append("java "); 168 for(String s : JVM_ARGS()) { 169 sb.append(s).append(' '); 170 } 171 sb.append("-cp "+System.getProperty("java.class.path")+" "); 172 sb.append(mainClass.getCanonicalName()).append(' '); 173 for(String s : COMMAND_LINE) { 174 sb.append(s).append(' '); 175 } 176 sb.setLength(sb.length()-1); 177 return sb.toString(); 178 } 179 180 /** Directory in which to write temp files */ 181 private static String TMPDIR=getTmpdir(); 182 // static{assert(false) : "TMPDIR="+TMPDIR;} 183 getTmpdir()184 private static String getTmpdir(){ 185 String s=System.getenv("SLURM_TMP"); 186 if(s==null){s=System.getenv("TMPDIR");} 187 if(s!=null){s=(s+"/").replaceAll("//", "/").replaceAll("\\\\", "/");} 188 return s; 189 } 190 tmpdir()191 public static String tmpdir(){return TMPDIR;} 192 setTmpdir(String s)193 public static String setTmpdir(String s){ 194 if(s==null){TMPDIR=null;} 195 else{ 196 s=s.replaceAll("\\\\", "/"); 197 if(!s.endsWith("/")){s=s+"/";} 198 TMPDIR=s.replaceAll("//", "/"); 199 } 200 return TMPDIR; 201 } 202 203 /** Anomaly probably resolved as of v.20.1 204 * This variable should be TRUE for normal users and FALSE for me. */ 205 public static boolean anomaly=!(System.getProperty("user.dir")+"").contains("/bushnell/") && !WINDOWS; 206 getTLCB(int len)207 public static final char[] getTLCB(int len){ 208 char[] buffer=TLCB.get(); 209 if(buffer==null || buffer.length<len){ 210 buffer=new char[len]; 211 if(len<1000000){TLCB.set(buffer);} 212 } 213 return buffer; 214 } 215 private static final ThreadLocal<char[]> TLCB=new ThreadLocal<char[]>(); 216 217 /*--------------------------------------------------------------*/ 218 /*---------------- Threads ----------------*/ 219 /*--------------------------------------------------------------*/ 220 capThreads(int t)221 public static int capThreads(int t) { 222 assert(THREADS>0) : THREADS; 223 final int old=THREADS; 224 THREADS=Tools.mid(1, t, old); 225 assert(THREADS>0) : THREADS; 226 return old; 227 } 228 setThreads(String x)229 public static int setThreads(String x){ 230 int y=LOGICAL_PROCESSORS; 231 if(x!=null && !x.equalsIgnoreCase("auto")){ 232 if(x.indexOf('.')>=0){ 233 double d=Double.parseDouble(x); 234 if(d>1){ 235 y=(int)d; 236 }else{ 237 y=(int)Tools.max(1, Math.ceil(d*y)); 238 } 239 }else{ 240 y=Integer.parseInt(x); 241 } 242 } 243 return setThreads(y); 244 } 245 setThreads(int x)246 public static int setThreads(int x){ 247 if(x>0){ 248 THREADS=x; 249 }else{ 250 THREADS=Tools.max(1, LOGICAL_PROCESSORS); 251 } 252 setBuffers(); 253 assert(THREADS>0) : THREADS; 254 return THREADS; 255 } 256 threads()257 public static int threads(){ 258 assert(THREADS>0) : THREADS; 259 return THREADS; 260 } 261 CALC_LOGICAL_PROCESSORS()262 public static int CALC_LOGICAL_PROCESSORS(){ 263 final int procs=Tools.max(1, Runtime.getRuntime().availableProcessors()); 264 int slots=procs; 265 Map<String,String> env=System.getenv(); 266 String s=env.get("NSLOTS");//Genepool 267 boolean success=false; 268 if(s!=null){ 269 int x=slots; 270 try { 271 x=Tools.max(1, Integer.parseInt(s)); 272 success=true; 273 } catch (NumberFormatException e) { 274 //ignore 275 } 276 if(x<=16){slots=x;} 277 } 278 if(!success){ 279 s=env.get("SLURM_CPUS_ON_NODE");//All SLURM systems 280 if(s!=null){ 281 int x=slots; 282 try { 283 x=Tools.max(1, Integer.parseInt(s)); 284 success=true; 285 } catch (NumberFormatException e) { 286 //ignore 287 } 288 slots=x; 289 } 290 } 291 292 // if(slots>8 && (slots*2==procs || (slots==16 && procs==40))){return procs;}//hyperthreading 293 return Tools.min(slots, procs); 294 } 295 296 /*--------------------------------------------------------------*/ 297 /*---------------- JNI ----------------*/ 298 /*--------------------------------------------------------------*/ 299 300 private static int loadedJNI=-1; loadJNI()301 public static synchronized boolean loadJNI(){ 302 return loadJNI("bbtoolsjni"); 303 } loadJNI(String name)304 public static synchronized boolean loadJNI(String name){ 305 if(loadedJNI<0){ 306 boolean success=false; 307 308 String libpath=System.getProperty("java.library.path"); 309 // System.err.println("libpath='"+libpath+"'"); 310 311 if(libpath==null || libpath.length()==0){ 312 libpath=System.getProperty("java.class.path").replace("/current", "/jni"); 313 }else if(!libpath.contains("/jni")){ 314 libpath=libpath+":"+System.getProperty("java.class.path").replace("/current", "/jni"); 315 } 316 317 //Normal load 318 try{ 319 System.loadLibrary(name); 320 success=true; 321 }catch(UnsatisfiedLinkError e){} 322 323 if(!success){ 324 // System.loadLibrary() does not work with MPI. 325 // Need to use System.load() with an explicit full 326 // path to the native library file for the MPI case. 327 // String libpath=System.getProperty("java.library.path"); 328 libpath=libpath.replace("-Djava.library.path=",""); 329 String[] libpathEntries=libpath.split(File.pathSeparator); 330 for(int i=0; i<libpathEntries.length && !success; i++){ 331 String lib=libpathEntries[i]+"/"+System.mapLibraryName(name); 332 try{ 333 System.load(lib); 334 success=true; 335 }catch(UnsatisfiedLinkError e2){ 336 success=false; 337 } 338 } 339 } 340 341 if(success){ 342 loadedJNI=1; 343 }else{ 344 loadedJNI=0; 345 System.err.println("Native library can not be found in java.library.path."); 346 new Exception().printStackTrace(); 347 System.exit(1); 348 } 349 } 350 return loadedJNI==1; 351 } 352 353 /*--------------------------------------------------------------*/ 354 /*---------------- Buffers ----------------*/ 355 /*--------------------------------------------------------------*/ 356 capBuffers(int num)357 public static int capBuffers(int num){ 358 return setBuffers(Tools.min(num, READ_BUFFER_NUM_BUFFERS)); 359 } 360 READ_BUFFER_NUM_BUFFERS()361 public static int READ_BUFFER_NUM_BUFFERS() { 362 return READ_BUFFER_NUM_BUFFERS; 363 } 364 setBuffers()365 public static int setBuffers(){ 366 return setBuffersFromThreads(THREADS); 367 } 368 setBuffersFromThreads(int threads)369 public static int setBuffersFromThreads(int threads){ 370 return setBuffers(Tools.max(4, (threads*3)/2)); 371 } 372 373 /** Number of read lists buffered in input streams */ setBuffers(int num)374 public static int setBuffers(int num){ 375 // assert(READ_BUFFER_NUM_BUFFERS==0 || READ_BUFFER_NUM_BUFFERS==num) : READ_BUFFER_NUM_BUFFERS+" -> "+num; //TODO: 123 376 num=Tools.max(2, num);//TODO: Interesting, this is min 2 instead of the expected 1; maybe 1 didn't work? 377 return READ_BUFFER_NUM_BUFFERS=num; 378 } 379 380 /** Number of read lists buffered in input streams */ numBuffers()381 public static int numBuffers(){ 382 return READ_BUFFER_NUM_BUFFERS; 383 } 384 bufferLen()385 public static int bufferLen(){ 386 return READ_BUFFER_LENGTH; 387 } 388 bufferData()389 public static long bufferData(){ 390 return READ_BUFFER_MAX_DATA; 391 } 392 capBufferLen(int x)393 public static void capBufferLen(int x){ 394 if(x!=READ_BUFFER_LENGTH){setBufferLen(Tools.min(x, READ_BUFFER_LENGTH));} 395 } 396 setBufferLen(int x)397 public static int setBufferLen(int x){ 398 // assert(false) : READ_BUFFER_LENGTH+" -> "+x; //TODO: 123 399 assert(x>0); 400 return READ_BUFFER_LENGTH=x; 401 } 402 setBufferData(long x)403 public static long setBufferData(long x){ 404 // assert(false) : READ_BUFFER_MAX_DATA+" -> "+x; //TODO: 123 405 assert(x>0); 406 return READ_BUFFER_MAX_DATA=x; 407 } 408 409 410 /*--------------------------------------------------------------*/ 411 /*---------------- Memory ----------------*/ 412 /*--------------------------------------------------------------*/ 413 414 public static boolean LOW_MEMORY=false; 415 416 /** Ratio of -Xms to -Xmx parameters */ xmsRatio()417 public static final double xmsRatio(){ 418 Runtime rt=Runtime.getRuntime(); 419 return rt.totalMemory()*1.0/rt.maxMemory(); 420 } 421 memAvailable(int readThreads)422 public static long memAvailable(int readThreads){ 423 long usableMemory; 424 { 425 long memory=Runtime.getRuntime().maxMemory(); 426 double xmsRatio=Shared.xmsRatio(); 427 usableMemory=(long)Tools.max(((memory-48000000-(Tools.max(readThreads, 4)*400000))*(xmsRatio>0.97 ? 0.82 : 0.72)), memory*0.45); 428 } 429 return usableMemory; 430 } 431 memTotal()432 public static long memTotal(){ 433 Runtime rt=Runtime.getRuntime(); 434 return rt.maxMemory(); 435 } 436 memFree()437 public static long memFree(){ 438 Runtime rt=Runtime.getRuntime(); 439 return rt.freeMemory(); 440 } 441 memAvailable()442 public static long memAvailable(){ 443 Runtime rt=Runtime.getRuntime(); 444 return rt.maxMemory()-rt.totalMemory()+rt.freeMemory(); 445 } 446 447 /** An estimate, for preallocation */ memAvailableAdvanced()448 public static long memAvailableAdvanced(){ 449 Runtime rt=Runtime.getRuntime(); 450 final long mmemory=rt.maxMemory(); 451 final long tmemory=rt.totalMemory(); 452 final long fmemory=rt.freeMemory(); 453 final long umemory=tmemory-fmemory; 454 455 double xmsRatio=Shared.xmsRatio(); 456 double usableMemory=Tools.max(((mmemory-96000000)*(xmsRatio>0.97 ? 0.82 : 0.72)), mmemory*0.45); 457 double availableMemory=Tools.max(fmemory*0.5, usableMemory-umemory); //The 0.5 is an untested conservative guess 458 459 460 return (long)availableMemory; 461 } 462 memUsed()463 public static long memUsed(){ 464 Runtime rt=Runtime.getRuntime(); 465 return rt.maxMemory()-rt.freeMemory(); 466 } 467 468 /** Print statistics about current memory use and availability */ printMemory()469 public static final void printMemory(){ 470 try{ 471 if(GC_BEFORE_PRINT_MEMORY){ 472 System.gc(); 473 System.gc(); 474 } 475 Runtime rt=Runtime.getRuntime(); 476 long mmemory=rt.maxMemory()/1000000; 477 long tmemory=rt.totalMemory()/1000000; 478 long fmemory=rt.freeMemory()/1000000; 479 long umemory=tmemory-fmemory; 480 System.err.println("Memory: "+"max="+mmemory+"m, total="+tmemory+"m, "+"free="+fmemory+"m, used="+umemory+"m"); 481 }catch(Throwable t){} 482 } 483 threadLocalRandom()484 public static final Random threadLocalRandom(){return threadLocalRandom(-1);} threadLocalRandom(long seed)485 public static final Random threadLocalRandom(long seed){ 486 Random randy; 487 if(seed>=0){return new Random(seed);}//ThreadLocalRandom does not support seeds 488 try { 489 randy=ThreadLocalRandom.current(); 490 } catch (Throwable e) {//In case the JVM does not support ThreadLocalRandom; 491 randy=new Random(); 492 } 493 return randy; 494 } 495 496 /** Do garbage collection prior to printing memory usage */ 497 public static boolean GC_BEFORE_PRINT_MEMORY=false; 498 499 /** For Matt N. */ 500 public static String comment; 501 502 /*--------------------------------------------------------------*/ 503 /*---------------- Java 8 ----------------*/ 504 /*--------------------------------------------------------------*/ 505 sort(int[] array)506 public static final void sort(int[] array){sort(array, 0, array.length);} sort(int[] array, int from, int to)507 public static final void sort(int[] array, int from, int to){ 508 try { 509 if(!parallelSort || array.length<=parallelSortLength){ 510 Arrays.sort(array, from, to); //Supported in pre-Java 8. 511 return; 512 } 513 Arrays.parallelSort(array, from, to); 514 } catch (OutOfMemoryError e) { 515 KillSwitch.memKill(e); 516 } 517 } 518 sort(long[] array)519 public static final void sort(long[] array){sort(array, 0, array.length);} sort(long[] array, int from, int to)520 public static final void sort(long[] array, int from, int to){ 521 try { 522 if(!parallelSort || array.length<=parallelSortLength || THREADS<2){ 523 Arrays.sort(array, from, to); //Supported in pre-Java 8. 524 return; 525 } 526 Arrays.parallelSort(array, from, to); 527 } catch (OutOfMemoryError e) { 528 KillSwitch.memKill(e); 529 } 530 } 531 sort(float[] array)532 public static final void sort(float[] array){sort(array, 0, array.length);} sort(float[] array, int from, int to)533 public static final void sort(float[] array, int from, int to){ 534 try { 535 if(!parallelSort || array.length<=parallelSortLength){ 536 Arrays.sort(array, from, to); //Supported in pre-Java 8. 537 return; 538 } 539 Arrays.parallelSort(array, from, to); 540 } catch (OutOfMemoryError e) { 541 KillSwitch.memKill(e); 542 } 543 } 544 sort(double[] array)545 public static final void sort(double[] array){sort(array, 0, array.length);} sort(double[] array, int from, int to)546 public static final void sort(double[] array, int from, int to){ 547 try { 548 if(!parallelSort || array.length<=parallelSortLength){ 549 Arrays.sort(array, from, to); //Supported in pre-Java 8. 550 return; 551 } 552 Arrays.parallelSort(array, from, to); 553 } catch (OutOfMemoryError e) { 554 KillSwitch.memKill(e); 555 } 556 } 557 sort(T[] array)558 public static final <T extends Comparable<? super T>> void sort(T[] array){sort(array, 0, array.length);} sort(T[] array, int from, int to)559 public static final <T extends Comparable<? super T>> void sort(T[] array, int from, int to){ 560 try { 561 if(!parallelSort || array.length<=parallelSortLength || THREADS<2){ 562 Arrays.sort(array, from, to); //Supported in pre-Java 8. 563 return; 564 } 565 Arrays.parallelSort(array, from, to); 566 } catch (OutOfMemoryError e) { 567 KillSwitch.memKill(e); 568 } 569 } 570 sort(ArrayList<T> list)571 public static final <T extends Comparable<? super T>> void sort(ArrayList<T> list){ 572 try { 573 if(!parallelSort || list.size()<=parallelSortLength || THREADS<2){ 574 Collections.sort(list); //Supported in pre-Java 8. 575 return; 576 } 577 578 {//If this block causes compile errors, just replace the whole function body with "Shared.sort(list, comparator);" 579 @SuppressWarnings("unchecked") 580 T[] array=list.toArray((T[])new Comparable[0]); 581 list.clear(); 582 Arrays.parallelSort(array); 583 for(T r : array){list.add(r);} 584 } 585 } catch (OutOfMemoryError e) { 586 KillSwitch.memKill(e); 587 } 588 } 589 sort(ArrayList<T> list, Comparator<? super T> comparator)590 public static final <T> void sort(ArrayList<T> list, Comparator<? super T> comparator){ 591 try { 592 if(!parallelSort){ 593 Collections.sort(list, comparator); //Supported in pre-Java 8. 594 return; 595 } 596 597 {//If this block causes compile errors, just replace the whole function body with "Shared.sort(list, comparator);" 598 if(list.size()<=parallelSortLength || THREADS<2){ 599 list.sort(comparator); 600 return; 601 } 602 @SuppressWarnings("unchecked") 603 T[] array=list.toArray((T[])new Object[0]); 604 list.clear(); 605 Arrays.parallelSort(array, comparator); 606 for(T r : array){list.add(r);} 607 } 608 } catch (OutOfMemoryError e) { 609 KillSwitch.memKill(e); 610 } 611 } 612 613 /** 614 * Close this output stream if it is not stderr or stdout. 615 * Intended for files. 616 * @param outstream 617 */ closeStream(PrintStream outstream)618 public static void closeStream(PrintStream outstream) { 619 if(outstream!=null){ 620 synchronized(outstream){ 621 if(outstream!=System.err && outstream!=System.out){ 622 outstream.close(); 623 } 624 } 625 } 626 } 627 628 public static final long MAX_ARRAY_LEN=Integer.MAX_VALUE-20; 629 630 public static final int parallelSortLength=10000; 631 public static boolean disableParallelSort=false; 632 public static boolean parallelSort=testParallelSort(); 633 634 public static double javaVersion=parseJavaVersion(); 635 parseJavaVersion()636 private static double parseJavaVersion(){ 637 String s=System.getProperty("java.version"); 638 if(s==null){return 1.6;} 639 int dots=0; 640 StringBuilder sb=new StringBuilder(); 641 for(int i=0; i<s.length() && dots<2; i++){ 642 char c=s.charAt(i); 643 if(c=='.'){dots++;} 644 else if(!Tools.isDigit(c)){break;} 645 if(dots>1){break;} 646 sb.append(c); 647 } 648 return Double.parseDouble(sb.toString()); 649 } 650 setParallelSort(boolean x)651 public static void setParallelSort(boolean x){ 652 if(x){ 653 disableParallelSort=false; 654 parallelSort=testParallelSort(); 655 }else{ 656 disableParallelSort=true; 657 parallelSort=false; 658 } 659 } 660 661 /** This tests to see if the java version supports parallel sort, which was not true prior to 1.8. */ testParallelSort()662 private static boolean testParallelSort(){ 663 Method m=null; 664 try { 665 m=Arrays.class.getMethod("parallelSort", new Class[] {Object[].class, Comparator.class}); 666 } catch (NoSuchMethodException e) { 667 // TODO Auto-generated catch block 668 // e.printStackTrace(); 669 } catch (SecurityException e) { 670 // TODO Auto-generated catch block 671 // e.printStackTrace(); 672 } catch (Throwable t) { 673 // TODO Auto-generated catch block 674 // e.printStackTrace(); 675 } 676 return m!=null; 677 } 678 679 static{ assert(EA=true)680 assert(EA=true);//Sets the EA flag KillSwitch.addBallast()681 KillSwitch.addBallast(); 682 } 683 684 } 685