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.assertArrayEquals; 021import static org.junit.Assert.assertTrue; 022 023import java.io.ByteArrayInputStream; 024import java.io.ByteArrayOutputStream; 025import java.io.IOException; 026import org.apache.hadoop.hbase.Cell; 027import org.apache.hadoop.hbase.ExtendedCell; 028import org.apache.hadoop.hbase.ExtendedCellScanner; 029import org.apache.hadoop.hbase.KeyValue; 030import org.apache.hadoop.hbase.io.CellOutputStream; 031import org.apache.hadoop.hbase.util.Bytes; 032import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 033import org.apache.yetus.audience.InterfaceAudience; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * Do basic codec performance eval. 039 */ 040@InterfaceAudience.Public 041public class CodecPerformance { 042 /** @deprecated LOG variable would be made private. since 1.2, remove in 3.0 */ 043 @Deprecated 044 public static final Logger LOG = LoggerFactory.getLogger(CodecPerformance.class); 045 046 static ExtendedCell[] getCells(final int howMany) { 047 ExtendedCell[] cells = new ExtendedCell[howMany]; 048 for (int i = 0; i < howMany; i++) { 049 byte[] index = Bytes.toBytes(i); 050 KeyValue kv = new KeyValue(index, Bytes.toBytes("f"), index, index); 051 cells[i] = kv; 052 } 053 return cells; 054 } 055 056 static int getRoughSize(final Cell[] cells) { 057 int size = 0; 058 for (Cell c : cells) { 059 size += c.getRowLength() + c.getFamilyLength() + c.getQualifierLength() + c.getValueLength(); 060 size += Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE; 061 } 062 return size; 063 } 064 065 static byte[] runEncoderTest(final int index, final int initialBufferSize, 066 final ByteArrayOutputStream baos, final CellOutputStream encoder, final ExtendedCell[] cells) 067 throws IOException { 068 long startTime = EnvironmentEdgeManager.currentTime(); 069 for (int i = 0; i < cells.length; i++) { 070 encoder.write(cells[i]); 071 } 072 encoder.flush(); 073 LOG.info("" + index + " encoded count=" + cells.length + " in " 074 + (EnvironmentEdgeManager.currentTime() - startTime) + "ms for encoder " + encoder); 075 // Ensure we did not have to grow the backing buffer. 076 assertTrue(baos.size() < initialBufferSize); 077 return baos.toByteArray(); 078 } 079 080 static ExtendedCell[] runDecoderTest(final int index, final int count, 081 final ExtendedCellScanner decoder) throws IOException { 082 ExtendedCell[] cells = new ExtendedCell[count]; 083 long startTime = EnvironmentEdgeManager.currentTime(); 084 for (int i = 0; decoder.advance(); i++) { 085 cells[i] = decoder.current(); 086 } 087 LOG.info("" + index + " decoded count=" + cells.length + " in " 088 + (EnvironmentEdgeManager.currentTime() - startTime) + "ms for decoder " + decoder); 089 // Ensure we did not have to grow the backing buffer. 090 assertTrue(cells.length == count); 091 return cells; 092 } 093 094 static void verifyCells(final Cell[] input, final Cell[] output) { 095 assertArrayEquals(input, output); 096 } 097 098 static void doCodec(final Codec codec, final ExtendedCell[] cells, final int cycles, 099 final int count, final int initialBufferSize) throws IOException { 100 byte[] bytes = null; 101 ExtendedCell[] cellsDecoded = null; 102 for (int i = 0; i < cycles; i++) { 103 ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); 104 Codec.Encoder encoder = codec.getEncoder(baos); 105 bytes = runEncoderTest(i, initialBufferSize, baos, encoder, cells); 106 } 107 for (int i = 0; i < cycles; i++) { 108 ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 109 Codec.Decoder decoder = codec.getDecoder(bais); 110 cellsDecoded = CodecPerformance.runDecoderTest(i, count, decoder); 111 } 112 verifyCells(cells, cellsDecoded); 113 } 114 115 public static void main(String[] args) throws IOException { 116 // How many Cells to encode/decode on each cycle. 117 final int count = 100000; 118 // How many times to do an operation; repeat gives hotspot chance to warm up. 119 final int cycles = 30; 120 121 ExtendedCell[] cells = getCells(count); 122 int size = getRoughSize(cells); 123 int initialBufferSize = 2 * size; // Multiply by 2 to ensure we don't have to grow buffer 124 125 // Test KeyValue codec. 126 doCodec(new KeyValueCodec(), cells, cycles, count, initialBufferSize); 127 doCodec(new CellCodec(), cells, cycles, count, initialBufferSize); 128 doCodec(new MessageCodec(), cells, cycles, count, initialBufferSize); 129 } 130}