001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.codec; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertTrue; 022 023import java.io.ByteArrayInputStream; 024import java.io.ByteArrayOutputStream; 025import java.io.IOException; 026 027import org.apache.yetus.audience.InterfaceAudience; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030import org.apache.hadoop.hbase.Cell; 031import org.apache.hadoop.hbase.CellScanner; 032import org.apache.hadoop.hbase.KeyValue; 033import org.apache.hadoop.hbase.codec.CellCodec; 034import org.apache.hadoop.hbase.codec.Codec; 035import org.apache.hadoop.hbase.codec.KeyValueCodec; 036import org.apache.hadoop.hbase.codec.MessageCodec; 037import org.apache.hadoop.hbase.io.CellOutputStream; 038import org.apache.hadoop.hbase.util.Bytes; 039 040/** 041 * Do basic codec performance eval. 042 */ 043@InterfaceAudience.Public 044public class CodecPerformance { 045 /** @deprecated LOG variable would be made private. since 1.2, remove in 3.0 */ 046 @Deprecated 047 public static final Logger LOG = LoggerFactory.getLogger(CodecPerformance.class); 048 049 static Cell [] getCells(final int howMany) { 050 Cell [] cells = new Cell[howMany]; 051 for (int i = 0; i < howMany; i++) { 052 byte [] index = Bytes.toBytes(i); 053 KeyValue kv = new KeyValue(index, Bytes.toBytes("f"), index, index); 054 cells[i] = kv; 055 } 056 return cells; 057 } 058 059 static int getRoughSize(final Cell [] cells) { 060 int size = 0; 061 for (Cell c: cells) { 062 size += c.getRowLength() + c.getFamilyLength() + c.getQualifierLength() + c.getValueLength(); 063 size += Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE; 064 } 065 return size; 066 } 067 068 static byte [] runEncoderTest(final int index, final int initialBufferSize, 069 final ByteArrayOutputStream baos, final CellOutputStream encoder, final Cell [] cells) 070 throws IOException { 071 long startTime = System.currentTimeMillis(); 072 for (int i = 0; i < cells.length; i++) { 073 encoder.write(cells[i]); 074 } 075 encoder.flush(); 076 LOG.info("" + index + " encoded count=" + cells.length + " in " + 077 (System.currentTimeMillis() - startTime) + "ms for encoder " + encoder); 078 // Ensure we did not have to grow the backing buffer. 079 assertTrue(baos.size() < initialBufferSize); 080 return baos.toByteArray(); 081 } 082 083 static Cell [] runDecoderTest(final int index, final int count, final CellScanner decoder) 084 throws IOException { 085 Cell [] cells = new Cell[count]; 086 long startTime = System.currentTimeMillis(); 087 for (int i = 0; decoder.advance(); i++) { 088 cells[i] = decoder.current(); 089 } 090 LOG.info("" + index + " decoded count=" + cells.length + " in " + 091 (System.currentTimeMillis() - startTime) + "ms for decoder " + decoder); 092 // Ensure we did not have to grow the backing buffer. 093 assertTrue(cells.length == count); 094 return cells; 095 } 096 097 static void verifyCells(final Cell [] input, final Cell [] output) { 098 assertEquals(input.length, output.length); 099 for (int i = 0; i < input.length; i ++) { 100 input[i].equals(output[i]); 101 } 102 } 103 104 static void doCodec(final Codec codec, final Cell [] cells, final int cycles, final int count, 105 final int initialBufferSize) 106 throws IOException { 107 byte [] bytes = null; 108 Cell [] cellsDecoded = null; 109 for (int i = 0; i < cycles; i++) { 110 ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); 111 Codec.Encoder encoder = codec.getEncoder(baos); 112 bytes = runEncoderTest(i, initialBufferSize, baos, encoder, cells); 113 } 114 for (int i = 0; i < cycles; i++) { 115 ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 116 Codec.Decoder decoder = codec.getDecoder(bais); 117 cellsDecoded = CodecPerformance.runDecoderTest(i, count, decoder); 118 } 119 verifyCells(cells, cellsDecoded); 120 } 121 122 public static void main(String[] args) throws IOException { 123 // How many Cells to encode/decode on each cycle. 124 final int count = 100000; 125 // How many times to do an operation; repeat gives hotspot chance to warm up. 126 final int cycles = 30; 127 128 Cell [] cells = getCells(count); 129 int size = getRoughSize(cells); 130 int initialBufferSize = 2 * size; // Multiply by 2 to ensure we don't have to grow buffer 131 132 // Test KeyValue codec. 133 doCodec(new KeyValueCodec(), cells, cycles, count, initialBufferSize); 134 doCodec(new CellCodec(), cells, cycles, count, initialBufferSize); 135 doCodec(new MessageCodec(), cells, cycles, count, initialBufferSize); 136 } 137}