ITPub博客

首页 > 应用开发 > Java > 外部排序优化

外部排序优化

原创 Java 作者:壹頁書 时间:2014-05-29 23:12:22 0 删除 编辑
优化外部排序
主要步骤重新拆分如下
第一阶段
1.将未排序的大文件切分(spilterReceiver)
2.一个线程池专门接收byte[],并将其转化为long[] (prepareReceiver)
3.一个线程池专门排序long[] (sortReceiver)
4.一个线程池专门将已经有序的long[]写入文件 (writerReceiver)

这个过程直接写long类型的数字到文件,因为写入文本占用IO资源比直接写入long型数字要多。

第二阶段
1.一个线程用于归并排序,将结果写入缓冲区 (mergerReceiver)
2.如果缓冲区快满了,就将其交给一个线程池用于写入最终的文件。 (mergerReceiver)

优化的重点是平衡CPU,内存和硬盘的资源使用。

每个电脑的配置不同,都需要进行不同的调整,才能达到最优化的效果。
单位的电脑是i5的CPU,8G内存,7200转硬盘。
我使用的虚拟机分配了2个核心,4G内存。
跑这个程序大致需要200s左右。
因为第二阶段的第一个步骤是非常消耗CPU资源的,单位电脑CPU主频很高,所以不会成为瓶颈。

而家里的电脑,应该配置更接近吴老师做实验的配置。主频比较低,32位系统,4G内存。
这个配置明显CPU成为瓶颈
在第一个阶段,切分出来的文件,由于CPU不能及时排序并输出,经常导致OOM
只能在切分一个文件出来之后,让切分线程sleep一段时间,大量测试得到的结果是这个线程至少sleep2500毫秒才能不导致OOM。
也就是说,CPU运算的速度跟不上IO的速度。后来想到一个方法,加大分片。原来4G文件使用15个分片,现在使用30个分片。数据快入快出,这样可以避免OOM。至于这个分片的数字,恐怕每个机器都需要实际的测试。
另外在第二阶段,也出现了CPU拖累IO,导致性能下降。
因为归并的时候,需要大量运算各个分片中最小的数据,经常看到计算50M数据,CPU需要2s,而写入一般1s就可以完成。
而这个过程是单线程的,CPU的主频直接决定了外部排序的总体时间。


  1. import java.io.BufferedInputStream;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.RandomAccessFile;
  6. import java.nio.ByteBuffer;
  7. import java.nio.MappedByteBuffer;
  8. import java.nio.channels.FileChannel;
  9. import java.nio.channels.FileChannel.MapMode;
  10. import java.util.ArrayList;
  11. import java.util.Arrays;
  12. import java.util.Collections;
  13. import java.util.List;
  14. import java.util.concurrent.BrokenBarrierException;
  15. import java.util.concurrent.CyclicBarrier;
  16. import java.util.concurrent.ExecutorService;
  17. import java.util.concurrent.Executors;

  18. public class Controller {
  19.     public static void main(String[] args) throws IOException {
  20.         new Controller().action(new File("/home/lihuilin/桌面/t.txt"), 30, "/home/lihuilin/桌面/");

  21.     }

  22.     public void action(File file, int pieces, String outDir) throws IOException {
  23.         Invoker invoker = new Invoker(pieces);
  24.         List<Command> commandList = blocking(file, pieces, outDir);
  25.         for (Command command : commandList) {
  26.             command.setInvoker(invoker);
  27.             invoker.executeCommand(command);
  28.         }
  29.     }

  30.     private List<Command> blocking(File file, int pieces, String outDir) throws IOException {
  31.         List<Command> result = new ArrayList<Command>();
  32.         List<Long> list = new ArrayList<Long>();
  33.         list.add(-1L);
  34.         long length = file.length();
  35.         long step = length / pieces;
  36.         long index = 0;
  37.         for (int i = 0; i < pieces; i++) {
  38.             BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
  39.             if (index + step < length) {
  40.                 index = index + step;
  41.                 in.skip(index);
  42.                 while (in.read() != 10) {
  43.                     index = index + 1;
  44.                 }
  45.                 list.add(index);
  46.                 index++;
  47.             }
  48.             in.close();
  49.         }
  50.         list.add(length - 1);
  51.         for (int i = 0; i < list.size() - 1; i++) {
  52.             long skipSize = list.get(i) + 1;
  53.             long l = list.get(i + 1) - list.get(i);
  54.             result.add(new SpilterCommand(file, skipSize, l, outDir));
  55.         }
  56.         return result;
  57.     }

  58. }

  59. interface Command extends Comparable<Command> {
  60.     public void setInvoker(Invoker invoker);

  61.     public void setReceiver(Receiver receiver);

  62.     public void execute() throws IOException;

  63.     public long getSkipSize();

  64.     public int getLength();

  65.     public String getOutDir();

  66.     public File getSourceFile();

  67.     public Invoker getInvoker();

  68.     public void clear();

  69.     public File getOutFile();

  70.     public File getTargetFile();
  71. }

  72. class Invoker {
  73.     private Receiver sortReceiver;
  74.     private Receiver spilterReceiver;
  75.     private Receiver writerReceiver;
  76.     private Receiver prepareReceiver;
  77.     private Receiver mergerReceiver;

  78.     public Invoker(int pieces) {
  79.         writerReceiver = new WriterReceiver(pieces);
  80.         spilterReceiver = new SpilterReceiver();
  81.         sortReceiver = new SorterReceiver();
  82.         prepareReceiver = new PrepareReceiver();
  83.         mergerReceiver = new MergerReceiver();
  84.     }

  85.     public void executeCommand(Command command) {
  86.         try {
  87.             if (command instanceof SpilterCommand) {
  88.                 spilterReceiver.action(command);
  89.             } else if (command instanceof PrepareCommand) {
  90.                 prepareReceiver.action(command);
  91.             } else if (command instanceof SortCommand) {
  92.                 sortReceiver.action(command);
  93.             } else if (command instanceof WriterCommand) {
  94.                 writerReceiver.action(command);
  95.             } else if (command instanceof MergeCommand) {
  96.                 mergerReceiver.action(command);
  97.             } else if (command instanceof KillCommand) {
  98.                 writerReceiver.shutdown();
  99.                 spilterReceiver.shutdown();
  100.                 sortReceiver.shutdown();
  101.                 prepareReceiver.shutdown();
  102.                 mergerReceiver.shutdown();
  103.             }
  104.         } catch (IOException ex) {
  105.             ex.printStackTrace();
  106.         }
  107.     }
  108. }

  109. class SpilterCommand extends AbstractCommand {

  110.     public SpilterCommand(File sourceFile, long skipSize, long length, String outDir) {
  111.         super(sourceFile, skipSize, length, outDir);
  112.     }

  113.     @Override
  114.     public void clear() {

  115.     }

  116. }

  117. abstract class AbstractCommand implements Command {
  118.     private Invoker invoker = null;
  119.     private Receiver receiver = null;
  120.     private long skipSize = 0L;
  121.     private int length = 0;
  122.     private String outDir = null;
  123.     private File sourceFile;
  124.     private File outFile = null;
  125.     public static final long START = System.currentTimeMillis();
  126.     private static int FLAG = 0;
  127.     private File targetFile = null;

  128.     private synchronized int getFlag() {
  129.         return FLAG++;
  130.     }

  131.     public AbstractCommand(Command command) {
  132.         this(command.getSourceFile(), command.getSkipSize(), command.getLength(), command.getOutDir());
  133.         this.invoker = command.getInvoker();
  134.         if (command.getOutFile() != null) {
  135.             this.outFile = command.getOutFile();
  136.         } else {
  137.             this.outFile = new File(this.outDir + getFlag() + ".temp");
  138.         }
  139.     }

  140.     public AbstractCommand(File sourceFile, long skipSize, long length, String outDir) {
  141.         if (length > Integer.MAX_VALUE) {
  142.             throw new RuntimeException("长度溢出");
  143.         }
  144.         this.skipSize = skipSize;
  145.         this.length = (int) length;
  146.         this.outDir = outDir;
  147.         this.sourceFile = sourceFile;
  148.         this.targetFile = new File(outDir + "result.temp");
  149.     }

  150.     public void setInvoker(Invoker invoker) {
  151.         this.invoker = invoker;
  152.     }

  153.     public void setReceiver(Receiver receiver) {
  154.         this.receiver = receiver;
  155.     }

  156.     public long getSkipSize() {
  157.         return skipSize;
  158.     }

  159.     public int getLength() {
  160.         return length;
  161.     }

  162.     public String getOutDir() {
  163.         return outDir;
  164.     }

  165.     public File getSourceFile() {
  166.         return sourceFile;
  167.     }

  168.     @Override
  169.     public String toString() {
  170.         return "Command [skipSize=" + skipSize + ", length=" + length + "]";
  171.     }

  172.     public void execute() throws IOException {
  173.         this.receiver.action(this);
  174.     }

  175.     public Invoker getInvoker() {
  176.         return invoker;
  177.     }

  178.     public File getOutFile() {
  179.         return this.outFile;
  180.     }

  181.     public File getTargetFile() {
  182.         return this.targetFile;
  183.     }

  184.     @Override
  185.     public int compareTo(Command o) {
  186.         if (this.skipSize < o.getSkipSize()) {
  187.             return -1;
  188.         }
  189.         return 1;
  190.     }
  191. }

  192. interface Receiver {
  193.     public void action(Command command) throws IOException;

  194.     public void shutdown();
  195. }

  196. class PrepareReceiver implements Receiver {
  197.     private ExecutorService prepareThreadPool;

  198.     public PrepareReceiver() {
  199.         prepareThreadPool = Executors.newFixedThreadPool(4);
  200.     }

  201.     @Override
  202.     public void action(final Command command) throws IOException {
  203.         prepareThreadPool.submit(new Runnable() {

  204.             @Override
  205.             public void run() {
  206.                 System.out.println("\t整理数据:" + command);
  207.                 long start = System.currentTimeMillis();

  208.                 byte[] data = ((PrepareCommand) command).getData();
  209.                 long[] result = new long[getObjectSize(data)];
  210.                 int resultIndex = 0;
  211.                 int index = 0;
  212.                 int first = 0;
  213.                 while (index < data.length) {
  214.                     if (data[index] == 10) {
  215.                         byte[] tmpData = Arrays.copyOfRange(data, first, index);
  216.                         String str = new String(tmpData);
  217.                         result[resultIndex] = Long.valueOf(str);
  218.                         resultIndex++;
  219.                         first = index + 1;
  220.                     }

  221.                     index++;
  222.                 }
  223.                 command.getInvoker().executeCommand(new SortCommand(command, result));

  224.                 result = null;
  225.                 data = null;
  226.                 command.clear();

  227.                 long end = System.currentTimeMillis();
  228.                 System.out.println("\t结束整理数据:" + command + ",用时:" + (end - start) / 1000);
  229.             }

  230.         });

  231.     }

  232.     private int getObjectSize(byte[] data) {
  233.         int size = 0;
  234.         for (byte b : data) {
  235.             if (b == 10) {
  236.                 size++;
  237.             }
  238.         }
  239.         return size;
  240.     }

  241.     @Override
  242.     public void shutdown() {
  243.         this.prepareThreadPool.shutdown();
  244.     }

  245. }

  246. class PrepareCommand extends AbstractCommand {

  247.     private byte[] data;

  248.     public PrepareCommand(Command command, byte[] data) {
  249.         super(command);
  250.         this.data = data;
  251.     }

  252.     public byte[] getData() {
  253.         return this.data;
  254.     }

  255.     @Override
  256.     public void clear() {
  257.         this.data = null;
  258.     }
  259. }

  260. class SpilterReceiver implements Receiver {
  261.     @Override
  262.     public void action(final Command command) throws IOException {
  263.         try {
  264.             System.out.println("开始读入:" + command);
  265.             long start = System.currentTimeMillis();
  266.             FileChannel in = new RandomAccessFile(command.getSourceFile(), "r").getChannel();
  267.             MappedByteBuffer inBuffer = in.map(MapMode.READ_ONLY, command.getSkipSize(), command.getLength());
  268.             byte[] data = new byte[inBuffer.limit()];
  269.             inBuffer.get(data);
  270.             command.getInvoker().executeCommand(new PrepareCommand(command, data));

  271.             data = null;
  272.             in.close();
  273.             command.clear();

  274.             long end = System.currentTimeMillis();
  275.             System.out.println("结束内存读入:" + (end - start) / 1000 + "s");

  276.         } catch (IOException e) {
  277.             e.printStackTrace();
  278.         }
  279.     }

  280.     @Override
  281.     public void shutdown() {
  282.     }
  283. }

  284. class MergeCommand extends AbstractCommand {
  285.     private List<Command> commandList = null;

  286.     public MergeCommand(List<Command> commandList) {
  287.         super(commandList.get(0));
  288.         this.commandList = commandList;
  289.     }

  290.     @Override
  291.     public void clear() {

  292.     }

  293.     public List<Command> getCommandList() {
  294.         return this.commandList;
  295.     }
  296. }

  297. class KillCommand extends AbstractCommand {

  298.     public KillCommand(Command command) {
  299.         super(command);
  300.     }

  301.     @Override
  302.     public void clear() {

  303.     }

  304. }

  305. class MergerReceiver implements Receiver {
  306.     private ExecutorService mergerThreadPool = Executors.newFixedThreadPool(4);
  307.     private List<Worker> workerList = new ArrayList<Worker>();
  308.     private ByteBuffer bb = null;

  309.     @Override
  310.     public void action(final Command command) throws IOException {
  311.         bb = ByteBuffer.allocate(50 * 1024 * 1024);
  312.         List<Command> list = ((MergeCommand) command).getCommandList();
  313.         for (Command historyCommand : list) {
  314.             Worker worker = new Worker(historyCommand.getOutFile(), workerList);
  315.             workerList.add(worker);
  316.         }

  317.         System.out.println("读取队列,写入目标文件");
  318.         long start = System.currentTimeMillis();
  319.         RandomAccessFile targetFile = new RandomAccessFile(command.getTargetFile(), "rw");
  320.         FileChannel channel = targetFile.getChannel();
  321.         MappedByteBuffer out = null;
  322.         long index = 0L;
  323.         while (workerList.size() != 0) {
  324.             Worker worker = Collections.min(workerList);
  325.             Long data = worker.poll();
  326.             if (data == null) {
  327.                 workerList.remove(worker);
  328.             } else {

  329.                 bb.put((data + "\n").getBytes());

  330.                 if (bb.position() > 49 * 1024 * 1024) {
  331.                     long end = System.currentTimeMillis();
  332.                     System.out.println("归并用时:" + (end - start)/1000 + "s");
  333.                     start = System.currentTimeMillis();
  334.                     bb.flip();
  335.                     long temp = bb.limit();
  336.                     MutiWriter writer = new MutiWriter(channel, bb, index);
  337.                     mergerThreadPool.submit(writer);
  338.                     index = index + temp;
  339.                     bb = ByteBuffer.allocate(50 * 1024 * 1024);
  340.                 }

  341.             }
  342.         }

  343.         bb.flip();

  344.         out = channel.map(MapMode.READ_WRITE, index, bb.limit());
  345.         int i = bb.limit();
  346.         while (i > .0) {
  347.             out.put(bb.get());
  348.             i--;
  349.         }
  350.         out.force();
  351.         channel.close();
  352.         targetFile.close();

  353.         KillCommand killCommand = new KillCommand(command);
  354.         command.getInvoker().executeCommand(killCommand);

  355.         long end = System.currentTimeMillis();
  356.         System.out.println("外部排序总用时:" + (end - AbstractCommand.START) / 1000);

  357.     }

  358.     private class MutiWriter implements Runnable {
  359.         private ByteBuffer buffer;
  360.         private MappedByteBuffer out = null;

  361.         public MutiWriter(FileChannel channel, ByteBuffer buffer, long index) {
  362.             this.buffer = buffer;
  363.             try {
  364.                 out = channel.map(MapMode.READ_WRITE, index, buffer.limit());
  365.             } catch (IOException e) {
  366.                 e.printStackTrace();
  367.             }
  368.         }

  369.         @Override
  370.         public void run() {
  371.             long a1 = System.currentTimeMillis();
  372.             int i = buffer.limit();
  373.             while (i > 0) {
  374.                 out.put(buffer.get());
  375.                 i--;
  376.             }
  377.             out.force();
  378.             out = null;
  379.             long a2 = System.currentTimeMillis();
  380.             System.out.println("内存映射写入:" + (a2 - a1) / 1000 + "s");
  381.         }

  382.     }

  383.     @Override
  384.     public void shutdown() {
  385.         mergerThreadPool.shutdown();
  386.     }

  387.     private class Worker implements Comparable<Worker> {
  388.         private long data;
  389.         private MappedByteBuffer buffer = null;
  390.         private List<Worker> workerList = null;
  391.         private boolean eof = false;

  392.         Worker(File file, List<Worker> workerList) {
  393.             try {
  394.                 RandomAccessFile rFile = new RandomAccessFile(file, "r");
  395.                 FileChannel channel = rFile.getChannel();
  396.                 buffer = channel.map(MapMode.READ_ONLY, 0, channel.size());

  397.                 this.workerList = workerList;
  398.                 data = buffer.getLong();

  399.                 rFile.close();
  400.                 channel.close();

  401.             } catch (IOException e) {
  402.                 // TODO Auto-generated catch block
  403.                 e.printStackTrace();
  404.             }
  405.         }

  406.         public long peek() {
  407.             return data;
  408.         }

  409.         public Long poll() {
  410.             long result = data;
  411.             if (buffer.position() != buffer.limit()) {
  412.                 data = buffer.getLong();
  413.             } else {
  414.                 if (eof == false) {
  415.                     eof = true;
  416.                 } else {
  417.                     return null;
  418.                 }
  419.             }

  420.             return result;
  421.         }

  422.         @Override
  423.         public int compareTo(Worker o) {
  424.             if (this.peek() > o.peek()) {
  425.                 return 1;
  426.             } else if (this.peek() < o.peek()) {
  427.                 return -1;
  428.             } else {
  429.                 return 0;
  430.             }
  431.         }
  432.     }

  433. }

  434. class WriterReceiver implements Receiver {
  435.     private ExecutorService writeThreadPool = null;;
  436.     private CyclicBarrier barrier = null;
  437.     private List<Command> commandList = new ArrayList<Command>();

  438.     public WriterReceiver(int pieces) {
  439.         writeThreadPool = Executors.newFixedThreadPool(pieces + 2);
  440.         barrier = new CyclicBarrier(pieces, new Runnable() {

  441.             @Override
  442.             public void run() {
  443.                 long end = System.currentTimeMillis();
  444.                 System.out.println("合并之前总用时:" + (end - AbstractCommand.START) / 1000);

  445.                 MergeCommand command = new MergeCommand(WriterReceiver.this.commandList);
  446.                 command.getInvoker().executeCommand(command);

  447.             }
  448.         });

  449.     }

  450.     @Override
  451.     public void action(final Command command) {
  452.         writeThreadPool.submit(new Runnable() {

  453.             @Override
  454.             public void run() {
  455.                 long[] data = ((WriterCommand) command).getData();

  456.                 try {
  457.                     System.out.println("\t\t\t开始写入:" + command);
  458.                     long start = System.currentTimeMillis();
  459.                     File outfile = command.getOutFile();
  460.                     FileChannel channel = new RandomAccessFile(outfile, "rw").getChannel();
  461.                     MappedByteBuffer buffer = channel.map(MapMode.READ_WRITE, 0, data.length * 8);
  462.                     for (int i = 0; i < data.length; i++) {
  463.                         buffer.putLong(data[i]);
  464.                     }
  465.                     buffer.force();
  466.                     WriterReceiver.this.commandList.add(command);
  467.                     long end = System.currentTimeMillis();
  468.                     System.out.println("\t\t\t结束写入:" + command + ",用时:" + (end - start) / 1000);

  469.                     command.clear();
  470.                     data = null;
  471.                     channel.close();
  472.                     buffer = null;

  473.                     barrier.await();
  474.                 } catch (IOException ex) {
  475.                     ex.printStackTrace();
  476.                 } catch (InterruptedException e) {
  477.                     e.printStackTrace();
  478.                 } catch (BrokenBarrierException e) {
  479.                     e.printStackTrace();
  480.                 }
  481.             }
  482.         });
  483.     }

  484.     @Override
  485.     public void shutdown() {
  486.         writeThreadPool.shutdown();
  487.     }
  488. }

  489. class SortCommand extends AbstractCommand {
  490.     private long[] data = null;

  491.     public SortCommand(Command command, long[] data) {
  492.         super(command);
  493.         this.data = data;
  494.     }

  495.     public long[] getData() {
  496.         return this.data;
  497.     }

  498.     @Override
  499.     public void clear() {
  500.         this.data = null;
  501.     }

  502. }

  503. class SorterReceiver implements Receiver {
  504.     private ExecutorService sortThreadPool = Executors.newFixedThreadPool(4);

  505.     public void action(final Command command) {
  506.         sortThreadPool.submit(new Runnable() {

  507.             @Override
  508.             public void run() {
  509.                 System.out.println("\t\t开始排序:" + command);
  510.                 long start = System.currentTimeMillis();

  511.                 long[] data = ((SortCommand) command).getData();
  512.                 Arrays.sort(data);

  513.                 command.getInvoker().executeCommand(new WriterCommand(command, data));

  514.                 data = null;
  515.                 command.clear();

  516.                 long end = System.currentTimeMillis();
  517.                 System.out.println("\t\t结束排序:" + command + ",用时:" + (end - start) / 1000);

  518.             }

  519.         });

  520.     }

  521.     @Override
  522.     public void shutdown() {
  523.         sortThreadPool.shutdown();
  524.     }
  525. }

  526. class WriterCommand extends AbstractCommand {
  527.     private long[] data;

  528.     public WriterCommand(Command command, long[] data) {
  529.         super(command);
  530.         this.data = data;
  531.     }

  532.     public long[] getData() {
  533.         return this.data;
  534.     }

  535.     @Override
  536.     public void clear() {
  537.         this.data = null;
  538.     }

  539. }
最近真的很忙,我这一个单线程的CPU居然都跑出了双核的感觉。
我感觉优化就是找到慢的地方,看看是不是有无效的操作,如果都是有效运算,就只能想办法使用多线程,使压力分散在多个核心上。
之前吴老师说他用的是直接缓冲区+通道 IO的方式。自己写程序将long直接转化为byte。
这个优化的方式我试了一下,不能应用在我的场景。
他的本意是减少GC,但是在我的场景,这种方式更加剧了CPU的争用。
优化的本质应该是平衡资源

程序日志,相比最初的版本,性能提升了50s
因为将切分文件,byte数组转为long数组拆分为了两个操作,并且使用了多线程处理。
  1. 开始读入:Command [skipSize=0, length=135863265]
  2. 结束内存读入:3s
  3. 整理数据:Command [skipSize=0, length=135863265]
  4. 开始读入:Command [skipSize=135863265, length=135863254]
  5. 结束整理数据:Command [skipSize=0, length=135863265],用时:4
  6. 开始排序:Command [skipSize=0, length=135863265]
  7. 结束内存读入:4s
  8. 开始读入:Command [skipSize=271726519, length=135863267]
  9. 整理数据:Command [skipSize=135863265, length=135863254]
  10. 结束排序:Command [skipSize=0, length=135863265],用时:2
  11. 开始写入:Command [skipSize=0, length=135863265]
  12. 结束内存读入:3s
  13. 开始读入:Command [skipSize=407589786, length=135863268]
  14. 整理数据:Command [skipSize=271726519, length=135863267]
  15. 结束写入:Command [skipSize=0, length=135863265],用时:2
  16. 结束整理数据:Command [skipSize=135863265, length=135863254],用时:5
  17. 开始排序:Command [skipSize=135863265, length=135863254]
  18. 结束排序:Command [skipSize=135863265, length=135863254],用时:1
  19. 开始写入:Command [skipSize=135863265, length=135863254]
  20. 结束整理数据:Command [skipSize=271726519, length=135863267],用时:4
  21. 开始排序:Command [skipSize=271726519, length=135863267]
  22. 结束排序:Command [skipSize=271726519, length=135863267],用时:1
  23. 开始写入:Command [skipSize=271726519, length=135863267]
  24. 结束写入:Command [skipSize=135863265, length=135863254],用时:6
  25. 结束写入:Command [skipSize=271726519, length=135863267],用时:4
  26. 结束内存读入:11s
  27. 整理数据:Command [skipSize=407589786, length=135863268]
  28. 开始读入:Command [skipSize=543453054, length=135863264]
  29. 结束整理数据:Command [skipSize=407589786, length=135863268],用时:3
  30. 开始排序:Command [skipSize=407589786, length=135863268]
  31. 结束内存读入:4s
  32. 开始读入:Command [skipSize=679316318, length=135863268]
  33. 整理数据:Command [skipSize=543453054, length=135863264]
  34. 结束排序:Command [skipSize=407589786, length=135863268],用时:1
  35. 开始写入:Command [skipSize=407589786, length=135863268]
  36. 结束写入:Command [skipSize=407589786, length=135863268],用时:1
  37. 结束整理数据:Command [skipSize=543453054, length=135863264],用时:3
  38. 开始排序:Command [skipSize=543453054, length=135863264]
  39. 结束排序:Command [skipSize=543453054, length=135863264],用时:1
  40. 开始写入:Command [skipSize=543453054, length=135863264]
  41. 结束写入:Command [skipSize=543453054, length=135863264],用时:1
  42. 结束内存读入:7s
  43. 整理数据:Command [skipSize=679316318, length=135863268]
  44. 开始读入:Command [skipSize=815179586, length=135863264]
  45. 结束内存读入:3s
  46. 开始读入:Command [skipSize=951042850, length=135863270]
  47. 整理数据:Command [skipSize=815179586, length=135863264]
  48. 开始排序:Command [skipSize=679316318, length=135863268]
  49. 结束整理数据:Command [skipSize=679316318, length=135863268],用时:3
  50. 结束排序:Command [skipSize=679316318, length=135863268],用时:2
  51. 开始写入:Command [skipSize=679316318, length=135863268]
  52. 结束整理数据:Command [skipSize=815179586, length=135863264],用时:4
  53. 开始排序:Command [skipSize=815179586, length=135863264]
  54. 结束写入:Command [skipSize=679316318, length=135863268],用时:2
  55. 结束内存读入:5s
  56. 整理数据:Command [skipSize=951042850, length=135863270]
  57. 开始读入:Command [skipSize=1086906120, length=135863262]
  58. 结束排序:Command [skipSize=815179586, length=135863264],用时:1
  59. 开始写入:Command [skipSize=815179586, length=135863264]
  60. 结束写入:Command [skipSize=815179586, length=135863264],用时:1
  61. 整理数据:Command [skipSize=1086906120, length=135863262]
  62. 结束内存读入:3s
  63. 开始读入:Command [skipSize=1222769382, length=135863265]
  64. 开始排序:Command [skipSize=951042850, length=135863270]
  65. 结束整理数据:Command [skipSize=951042850, length=135863270],用时:4
  66. 结束内存读入:3s
  67. 开始读入:Command [skipSize=1358632647, length=135863256]
  68. 整理数据:Command [skipSize=1222769382, length=135863265]
  69. 结束排序:Command [skipSize=951042850, length=135863270],用时:2
  70. 开始写入:Command [skipSize=951042850, length=135863270]
  71. 结束写入:Command [skipSize=951042850, length=135863270],用时:1
  72. 结束整理数据:Command [skipSize=1086906120, length=135863262],用时:5
  73. 开始排序:Command [skipSize=1086906120, length=135863262]
  74. 结束排序:Command [skipSize=1086906120, length=135863262],用时:1
  75. 开始写入:Command [skipSize=1086906120, length=135863262]
  76. 结束内存读入:4s
  77. 整理数据:Command [skipSize=1358632647, length=135863256]
  78. 开始读入:Command [skipSize=1494495903, length=135863268]
  79. 结束写入:Command [skipSize=1086906120, length=135863262],用时:1
  80. 开始排序:Command [skipSize=1222769382, length=135863265]
  81. 结束整理数据:Command [skipSize=1222769382, length=135863265],用时:6
  82. 结束排序:Command [skipSize=1222769382, length=135863265],用时:1
  83. 开始写入:Command [skipSize=1222769382, length=135863265]
  84. 整理数据:Command [skipSize=1494495903, length=135863268]
  85. 结束内存读入:4s
  86. 开始读入:Command [skipSize=1630359171, length=135863255]
  87. 开始排序:Command [skipSize=1358632647, length=135863256]
  88. 结束整理数据:Command [skipSize=1358632647, length=135863256],用时:5
  89. 结束写入:Command [skipSize=1222769382, length=135863265],用时:1
  90. 结束排序:Command [skipSize=1358632647, length=135863256],用时:1
  91. 开始写入:Command [skipSize=1358632647, length=135863256]
  92. 结束整理数据:Command [skipSize=1494495903, length=135863268],用时:3
  93. 结束写入:Command [skipSize=1358632647, length=135863256],用时:2
  94. 开始排序:Command [skipSize=1494495903, length=135863268]
  95. 结束内存读入:4s
  96. 整理数据:Command [skipSize=1630359171, length=135863255]
  97. 开始读入:Command [skipSize=1766222426, length=135863271]
  98. 结束排序:Command [skipSize=1494495903, length=135863268],用时:1
  99. 开始写入:Command [skipSize=1494495903, length=135863268]
  100. 结束写入:Command [skipSize=1494495903, length=135863268],用时:1
  101. 结束整理数据:Command [skipSize=1630359171, length=135863255],用时:3
  102. 开始排序:Command [skipSize=1630359171, length=135863255]
  103. 整理数据:Command [skipSize=1766222426, length=135863271]
  104. 结束内存读入:4s
  105. 开始读入:Command [skipSize=1902085697, length=135863258]
  106. 结束排序:Command [skipSize=1630359171, length=135863255],用时:2
  107. 开始写入:Command [skipSize=1630359171, length=135863255]
  108. 结束写入:Command [skipSize=1630359171, length=135863255],用时:1
  109. 结束整理数据:Command [skipSize=1766222426, length=135863271],用时:3
  110. 开始排序:Command [skipSize=1766222426, length=135863271]
  111. 整理数据:Command [skipSize=1902085697, length=135863258]
  112. 结束内存读入:4s
  113. 开始读入:Command [skipSize=2037948955, length=135863254]
  114. 结束排序:Command [skipSize=1766222426, length=135863271],用时:1
  115. 开始写入:Command [skipSize=1766222426, length=135863271]
  116. 结束写入:Command [skipSize=1766222426, length=135863271],用时:1
  117. 结束整理数据:Command [skipSize=1902085697, length=135863258],用时:3
  118. 开始排序:Command [skipSize=1902085697, length=135863258]
  119. 整理数据:Command [skipSize=2037948955, length=135863254]
  120. 结束内存读入:4s
  121. 开始读入:Command [skipSize=2173812209, length=135863259]
  122. 结束排序:Command [skipSize=1902085697, length=135863258],用时:2
  123. 开始写入:Command [skipSize=1902085697, length=135863258]
  124. 结束写入:Command [skipSize=1902085697, length=135863258],用时:1
  125. 结束整理数据:Command [skipSize=2037948955, length=135863254],用时:3
  126. 开始排序:Command [skipSize=2037948955, length=135863254]
  127. 结束内存读入:4s
  128. 整理数据:Command [skipSize=2173812209, length=135863259]
  129. 开始读入:Command [skipSize=2309675468, length=135863260]
  130. 结束排序:Command [skipSize=2037948955, length=135863254],用时:2
  131. 开始写入:Command [skipSize=2037948955, length=135863254]
  132. 结束整理数据:Command [skipSize=2173812209, length=135863259],用时:3
  133. 开始排序:Command [skipSize=2173812209, length=135863259]
  134. 结束内存读入:4s
  135. 整理数据:Command [skipSize=2309675468, length=135863260]
  136. 开始读入:Command [skipSize=2445538728, length=135863266]
  137. 结束写入:Command [skipSize=2037948955, length=135863254],用时:2
  138. 结束排序:Command [skipSize=2173812209, length=135863259],用时:2
  139. 开始写入:Command [skipSize=2173812209, length=135863259]
  140. 结束写入:Command [skipSize=2173812209, length=135863259],用时:1
  141. 结束整理数据:Command [skipSize=2309675468, length=135863260],用时:3
  142. 开始排序:Command [skipSize=2309675468, length=135863260]
  143. 整理数据:Command [skipSize=2445538728, length=135863266]
  144. 结束内存读入:4s
  145. 开始读入:Command [skipSize=2581401994, length=135863268]
  146. 结束排序:Command [skipSize=2309675468, length=135863260],用时:2
  147. 开始写入:Command [skipSize=2309675468, length=135863260]
  148. 结束写入:Command [skipSize=2309675468, length=135863260],用时:1
  149. 结束整理数据:Command [skipSize=2445538728, length=135863266],用时:4
  150. 开始排序:Command [skipSize=2445538728, length=135863266]
  151. 结束内存读入:4s
  152. 整理数据:Command [skipSize=2581401994, length=135863268]
  153. 开始读入:Command [skipSize=2717265262, length=135863264]
  154. 结束排序:Command [skipSize=2445538728, length=135863266],用时:2
  155. 开始写入:Command [skipSize=2445538728, length=135863266]
  156. 结束写入:Command [skipSize=2445538728, length=135863266],用时:1
  157. 结束整理数据:Command [skipSize=2581401994, length=135863268],用时:3
  158. 开始排序:Command [skipSize=2581401994, length=135863268]
  159. 整理数据:Command [skipSize=2717265262, length=135863264]
  160. 结束内存读入:4s
  161. 开始读入:Command [skipSize=2853128526, length=135863258]
  162. 结束排序:Command [skipSize=2581401994, length=135863268],用时:2
  163. 开始写入:Command [skipSize=2581401994, length=135863268]
  164. 结束写入:Command [skipSize=2581401994, length=135863268],用时:1
  165. 结束整理数据:Command [skipSize=2717265262, length=135863264],用时:3
  166. 开始排序:Command [skipSize=2717265262, length=135863264]
  167. 整理数据:Command [skipSize=2853128526, length=135863258]
  168. 结束内存读入:4s
  169. 开始读入:Command [skipSize=2988991784, length=135863254]
  170. 结束排序:Command [skipSize=2717265262, length=135863264],用时:2
  171. 开始写入:Command [skipSize=2717265262, length=135863264]
  172. 结束写入:Command [skipSize=2717265262, length=135863264],用时:1
  173. 结束整理数据:Command [skipSize=2853128526, length=135863258],用时:3
  174. 开始排序:Command [skipSize=2853128526, length=135863258]
  175. 结束内存读入:4s
  176. 整理数据:Command [skipSize=2988991784, length=135863254]
  177. 开始读入:Command [skipSize=3124855038, length=135863260]
  178. 结束排序:Command [skipSize=2853128526, length=135863258],用时:2
  179. 开始写入:Command [skipSize=2853128526, length=135863258]
  180. 结束写入:Command [skipSize=2853128526, length=135863258],用时:1
  181. 结束整理数据:Command [skipSize=2988991784, length=135863254],用时:3
  182. 开始排序:Command [skipSize=2988991784, length=135863254]
  183. 整理数据:Command [skipSize=3124855038, length=135863260]
  184. 结束内存读入:4s
  185. 开始读入:Command [skipSize=3260718298, length=135863254]
  186. 结束排序:Command [skipSize=2988991784, length=135863254],用时:2
  187. 开始写入:Command [skipSize=2988991784, length=135863254]
  188. 结束写入:Command [skipSize=2988991784, length=135863254],用时:2
  189. 结束整理数据:Command [skipSize=3124855038, length=135863260],用时:4
  190. 开始排序:Command [skipSize=3124855038, length=135863260]
  191. 整理数据:Command [skipSize=3260718298, length=135863254]
  192. 结束内存读入:4s
  193. 开始读入:Command [skipSize=3396581552, length=135863262]
  194. 结束排序:Command [skipSize=3124855038, length=135863260],用时:1
  195. 开始写入:Command [skipSize=3124855038, length=135863260]
  196. 结束写入:Command [skipSize=3124855038, length=135863260],用时:2
  197. 结束整理数据:Command [skipSize=3260718298, length=135863254],用时:3
  198. 开始排序:Command [skipSize=3260718298, length=135863254]
  199. 结束内存读入:4s
  200. 整理数据:Command [skipSize=3396581552, length=135863262]
  201. 开始读入:Command [skipSize=3532444814, length=135863265]
  202. 结束排序:Command [skipSize=3260718298, length=135863254],用时:1
  203. 开始写入:Command [skipSize=3260718298, length=135863254]
  204. 结束写入:Command [skipSize=3260718298, length=135863254],用时:2
  205. 结束整理数据:Command [skipSize=3396581552, length=135863262],用时:3
  206. 开始排序:Command [skipSize=3396581552, length=135863262]
  207. 结束内存读入:4s
  208. 整理数据:Command [skipSize=3532444814, length=135863265]
  209. 开始读入:Command [skipSize=3668308079, length=135863273]
  210. 结束排序:Command [skipSize=3396581552, length=135863262],用时:2
  211. 开始写入:Command [skipSize=3396581552, length=135863262]
  212. 结束写入:Command [skipSize=3396581552, length=135863262],用时:2
  213. 结束整理数据:Command [skipSize=3532444814, length=135863265],用时:3
  214. 开始排序:Command [skipSize=3532444814, length=135863265]
  215. 结束内存读入:4s
  216. 整理数据:Command [skipSize=3668308079, length=135863273]
  217. 开始读入:Command [skipSize=3804171352, length=135863261]
  218. 结束排序:Command [skipSize=3532444814, length=135863265],用时:2
  219. 开始写入:Command [skipSize=3532444814, length=135863265]
  220. 结束写入:Command [skipSize=3532444814, length=135863265],用时:1
  221. 结束整理数据:Command [skipSize=3668308079, length=135863273],用时:3
  222. 开始排序:Command [skipSize=3668308079, length=135863273]
  223. 整理数据:Command [skipSize=3804171352, length=135863261]
  224. 结束内存读入:4s
  225. 开始读入:Command [skipSize=3940034613, length=135862991]
  226. 结束排序:Command [skipSize=3668308079, length=135863273],用时:2
  227. 开始写入:Command [skipSize=3668308079, length=135863273]
  228. 结束写入:Command [skipSize=3668308079, length=135863273],用时:2
  229. 结束整理数据:Command [skipSize=3804171352, length=135863261],用时:3
  230. 开始排序:Command [skipSize=3804171352, length=135863261]
  231. 结束内存读入:4s
  232. 整理数据:Command [skipSize=3940034613, length=135862991]
  233. 结束排序:Command [skipSize=3804171352, length=135863261],用时:1
  234. 开始写入:Command [skipSize=3804171352, length=135863261]
  235. 结束写入:Command [skipSize=3804171352, length=135863261],用时:1
  236. 结束整理数据:Command [skipSize=3940034613, length=135862991],用时:3
  237. 开始排序:Command [skipSize=3940034613, length=135862991]
  238. 结束排序:Command [skipSize=3940034613, length=135862991],用时:1
  239. 开始写入:Command [skipSize=3940034613, length=135862991]
  240. 结束写入:Command [skipSize=3940034613, length=135862991],用时:1
  241. 合并之前总用时:143
  242. 读取队列,写入目标文件
  243. 归并用时:2s
  244. 内存映射写入:1s
  245. 归并用时:2s
  246. 内存映射写入:1s
  247. 归并用时:2s
  248. 内存映射写入:1s
  249. 归并用时:2s
  250. 内存映射写入:1s
  251. 归并用时:2s
  252. 内存映射写入:1s
  253. 归并用时:2s
  254. 内存映射写入:1s
  255. 归并用时:2s
  256. 内存映射写入:1s
  257. 归并用时:2s
  258. 内存映射写入:2s
  259. 归并用时:2s
  260. 内存映射写入:1s
  261. 归并用时:2s
  262. 内存映射写入:1s
  263. 归并用时:2s
  264. 内存映射写入:1s
  265. 归并用时:2s
  266. 内存映射写入:1s
  267. 归并用时:2s
  268. 内存映射写入:1s
  269. 归并用时:2s
  270. 内存映射写入:1s
  271. 归并用时:2s
  272. 归并用时:1s
  273. 内存映射写入:3s
  274. 归并用时:2s
  275. 归并用时:2s
  276. 内存映射写入:5s
  277. 内存映射写入:3s
  278. 归并用时:2s
  279. 内存映射写入:2s
  280. 内存映射写入:2s
  281. 归并用时:2s
  282. 内存映射写入:2s
  283. 归并用时:2s
  284. 归并用时:2s
  285. 内存映射写入:2s
  286. 内存映射写入:1s
  287. 归并用时:2s
  288. 归并用时:2s
  289. 内存映射写入:2s
  290. 内存映射写入:2s
  291. 归并用时:2s
  292. 归并用时:2s
  293. 内存映射写入:2s
  294. 内存映射写入:2s
  295. 归并用时:2s
  296. 内存映射写入:2s
  297. 归并用时:2s
  298. 内存映射写入:2s
  299. 归并用时:2s
  300. 内存映射写入:2s
  301. 归并用时:2s
  302. 内存映射写入:2s
  303. 归并用时:2s
  304. 归并用时:2s
  305. 内存映射写入:2s
  306. 内存映射写入:2s
  307. 归并用时:2s
  308. 归并用时:2s
  309. 内存映射写入:2s
  310. 归并用时:2s
  311. 内存映射写入:2s
  312. 内存映射写入:2s
  313. 归并用时:2s
  314. 内存映射写入:2s
  315. 归并用时:2s
  316. 内存映射写入:2s
  317. 归并用时:2s
  318. 内存映射写入:2s
  319. 归并用时:2s
  320. 内存映射写入:2s
  321. 归并用时:2s
  322. 内存映射写入:2s
  323. 归并用时:2s
  324. 内存映射写入:2s
  325. 归并用时:2s
  326. 内存映射写入:2s
  327. 归并用时:2s
  328. 内存映射写入:2s
  329. 归并用时:2s
  330. 内存映射写入:2s
  331. 归并用时:2s
  332. 内存映射写入:2s
  333. 归并用时:2s
  334. 内存映射写入:2s
  335. 归并用时:2s
  336. 内存映射写入:2s
  337. 归并用时:2s
  338. 内存映射写入:2s
  339. 归并用时:2s
  340. 归并用时:2s
  341. 内存映射写入:4s
  342. 内存映射写入:2s
  343. 归并用时:3s
  344. 内存映射写入:2s
  345. 归并用时:2s
  346. 归并用时:2s
  347. 内存映射写入:2s
  348. 内存映射写入:2s
  349. 归并用时:2s
  350. 内存映射写入:2s
  351. 归并用时:2s
  352. 内存映射写入:2s
  353. 归并用时:2s
  354. 内存映射写入:2s
  355. 归并用时:2s
  356. 内存映射写入:2s
  357. 归并用时:2s
  358. 内存映射写入:2s
  359. 归并用时:2s
  360. 内存映射写入:2s
  361. 归并用时:2s
  362. 内存映射写入:2s
  363. 归并用时:2s
  364. 归并用时:1s
  365. 归并用时:2s
  366. 归并用时:4s
  367. 内存映射写入:6s
  368. 内存映射写入:8s
  369. 内存映射写入:4s
  370. 归并用时:2s
  371. 归并用时:2s
  372. 内存映射写入:3s
  373. 内存映射写入:5s
  374. 内存映射写入:2s
  375. 归并用时:3s
  376. 归并用时:2s
  377. 内存映射写入:2s
  378. 内存映射写入:2s
  379. 归并用时:2s
  380. 内存映射写入:1s
  381. 归并用时:3s
  382. 归并用时:2s
  383. 内存映射写入:2s
  384. 归并用时:2s
  385. 内存映射写入:2s
  386. 内存映射写入:2s
  387. 归并用时:2s
  388. 归并用时:2s
  389. 内存映射写入:2s
  390. 内存映射写入:2s
  391. 归并用时:2s
  392. 内存映射写入:1s
  393. 归并用时:2s
  394. 内存映射写入:2s
  395. 归并用时:2s
  396. 内存映射写入:2s
  397. 归并用时:2s
  398. 内存映射写入:2s
  399. 归并用时:2s
  400. 内存映射写入:1s
  401. 外部排序总用时:351

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-1172752/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 外部排序
下一篇: JAVA操作MongoDB
请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    620
  • 访问量
    6339987