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