/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.fs.azure; import java.io.*; import java.util.*; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org.apache.hadoop.fs.azure.metrics.AzureFileSystemInstrumentation; import junit.framework.*; import org.junit.Test; /** * A simple benchmark to find out the difference in speed between block * and page blobs. */ public class TestBlobTypeSpeedDifference extends TestCase { /** * Writes data to the given stream of the given size, flushing every * x bytes. */ private static void writeTestFile(OutputStream writeStream, long size, long flushInterval) throws IOException { int bufferSize = (int) Math.min(1000, flushInterval); byte[] buffer = new byte[bufferSize]; Arrays.fill(buffer, (byte) 7); int bytesWritten = 0; int bytesUnflushed = 0; while (bytesWritten < size) { int numberToWrite = (int) Math.min(bufferSize, size - bytesWritten); writeStream.write(buffer, 0, numberToWrite); bytesWritten += numberToWrite; bytesUnflushed += numberToWrite; if (bytesUnflushed >= flushInterval) { writeStream.flush(); bytesUnflushed = 0; } } } private static class TestResult { final long timeTakenInMs; final long totalNumberOfRequests; TestResult(long timeTakenInMs, long totalNumberOfRequests) { this.timeTakenInMs = timeTakenInMs; this.totalNumberOfRequests = totalNumberOfRequests; } } /** * Writes data to the given file of the given size, flushing every * x bytes. Measure performance of that and return it. */ private static TestResult writeTestFile(NativeAzureFileSystem fs, Path path, long size, long flushInterval) throws IOException { AzureFileSystemInstrumentation instrumentation = fs.getInstrumentation(); long initialRequests = instrumentation.getCurrentWebResponses(); Date start = new Date(); OutputStream output = fs.create(path); writeTestFile(output, size, flushInterval); output.close(); long finalRequests = instrumentation.getCurrentWebResponses(); return new TestResult(new Date().getTime() - start.getTime(), finalRequests - initialRequests); } /** * Writes data to a block blob of the given size, flushing every * x bytes. Measure performance of that and return it. */ private static TestResult writeBlockBlobTestFile(NativeAzureFileSystem fs, long size, long flushInterval) throws IOException { return writeTestFile(fs, new Path("/blockBlob"), size, flushInterval); } /** * Writes data to a page blob of the given size, flushing every * x bytes. Measure performance of that and return it. */ private static TestResult writePageBlobTestFile(NativeAzureFileSystem fs, long size, long flushInterval) throws IOException { return writeTestFile(fs, AzureBlobStorageTestAccount.pageBlobPath("pageBlob"), size, flushInterval); } /** * Runs the benchmark over a small 10 KB file, flushing every 500 bytes. */ @Test public void testTenKbFileFrequentFlush() throws Exception { AzureBlobStorageTestAccount testAccount = AzureBlobStorageTestAccount.create(); if (testAccount == null) { return; } try { testForSizeAndFlushInterval(testAccount.getFileSystem(), 10 * 1000, 500); } finally { testAccount.cleanup(); } } /** * Runs the benchmark for the given file size and flush frequency. */ private static void testForSizeAndFlushInterval(NativeAzureFileSystem fs, final long size, final long flushInterval) throws IOException { for (int i = 0; i < 5; i++) { TestResult pageBlobResults = writePageBlobTestFile(fs, size, flushInterval); System.out.printf( "Page blob upload took %d ms. Total number of requests: %d.\n", pageBlobResults.timeTakenInMs, pageBlobResults.totalNumberOfRequests); TestResult blockBlobResults = writeBlockBlobTestFile(fs, size, flushInterval); System.out.printf( "Block blob upload took %d ms. Total number of requests: %d.\n", blockBlobResults.timeTakenInMs, blockBlobResults.totalNumberOfRequests); } } /** * Runs the benchmark for the given file size and flush frequency from the * command line. */ public static void main(String argv[]) throws Exception { Configuration conf = new Configuration(); long size = 10 * 1000 * 1000; long flushInterval = 2000; if (argv.length > 0) { size = Long.parseLong(argv[0]); } if (argv.length > 1) { flushInterval = Long.parseLong(argv[1]); } testForSizeAndFlushInterval((NativeAzureFileSystem)FileSystem.get(conf), size, flushInterval); } }