/*
* 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.brooklyn.core.test.qa.performance;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.core.mgmt.persist.FileBasedStoreObjectAccessor;
import org.apache.brooklyn.test.performance.PerformanceTestDescriptor;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.internal.ssh.process.ProcessTool;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.io.FileUtil;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
public class FilePersistencePerformanceTest extends AbstractPerformanceTest {
File file;
FileBasedStoreObjectAccessor fileAccessor;
@BeforeMethod(alwaysRun=true)
@Override
public void setUp() throws Exception {
super.setUp();
file = File.createTempFile("fileBasedStoreObject", ".txt");
Files.write("initial", file, Charsets.UTF_8);
fileAccessor = new FileBasedStoreObjectAccessor(file, "mytmpextension");
app.start(ImmutableList.of(loc));
}
@AfterMethod(alwaysRun=true)
@Override
public void tearDown() throws Exception {
super.tearDown();
if (file != null) file.delete();
}
protected int numIterations() {
return 100;
}
@Test(groups={"Integration", "Acceptance"})
public void testFileBasedStoreObjectPuts() throws Exception {
int numIterations = numIterations();
double minRatePerSec = 100 * PERFORMANCE_EXPECTATION;
final AtomicInteger i = new AtomicInteger();
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testFileBasedStoreObjectPuts")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
fileAccessor.put(""+i.incrementAndGet());
}}));
}
@Test(groups={"Integration", "Acceptance"})
public void testFileBasedStoreObjectGet() throws Exception {
// The file system will have done a lot of caching here - we are unlikely to touch the disk more than once.
int numIterations = numIterations();
double minRatePerSec = 100 * PERFORMANCE_EXPECTATION;
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testFileBasedStoreObjectGet")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
fileAccessor.get();
}}));
}
@Test(groups={"Integration", "Acceptance"})
public void testFileBasedStoreObjectDelete() throws Exception {
int numIterations = numIterations();
double minRatePerSec = 100 * PERFORMANCE_EXPECTATION;
// Will do 10% warm up runs first
final List<File> files = Lists.newArrayList();
for (int i = 0; i < (numIterations * 1.1 + 1); i++) {
file = File.createTempFile("fileBasedStoreObjectDelete-"+i, ".txt");
Files.write(""+i, file, Charsets.UTF_8);
files.add(file);
}
final AtomicInteger i = new AtomicInteger();
try {
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testFileBasedStoreObjectDelete")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
File file = files.get(i.getAndIncrement());
FileBasedStoreObjectAccessor fileAccessor = new FileBasedStoreObjectAccessor(file, "mytmpextension");
fileAccessor.delete();
}}));
} finally {
for (File file : files) {
if (file != null) file.delete();
}
}
}
@Test(groups={"Integration", "Acceptance"})
public void testFileUtilSetFilePermissions() throws IOException {
int numIterations = numIterations();
double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
final File file = File.createTempFile("filePermissions", ".txt");
try {
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testFileUtilSetFilePermissions")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
int i = 0;
public void run() {
try {
if (i % 2 == 0) {
FileUtil.setFilePermissionsTo600(file);
} else {
FileUtil.setFilePermissionsTo700(file);
}
} catch (Exception e) {
throw Exceptions.propagate(e);
}
}}));
} finally {
file.delete();
}
}
// fileAccessor.put() is implemented with an execCommands("mv") so look at performance of just that piece
@Test(groups={"Integration", "Acceptance"})
public void testProcessToolExecCommand() {
int numIterations = numIterations();
double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testProcessToolExecCommand")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
String cmd = "true";
new ProcessTool().execCommands(MutableMap.<String,String>of(), MutableList.of(cmd), null);
}}));
}
@Test(groups={"Integration", "Acceptance"})
public void testJavaUtilFileRenames() {
int numIterations = numIterations();
double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
final File parentDir = file.getParentFile();
final AtomicInteger i = new AtomicInteger();
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testJavaUtilFileRenames")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
File newFile = new File(parentDir, "fileRename-"+i.incrementAndGet()+".txt");
file.renameTo(newFile);
file = newFile;
}}));
}
@Test(groups={"Integration", "Acceptance"})
public void testGuavaFileWrites() {
int numIterations = numIterations();
double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
final AtomicInteger i = new AtomicInteger();
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testGuavaFileWrites")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
try {
Files.write(""+i.incrementAndGet(), file, Charsets.UTF_8);
} catch (IOException e) {
throw Exceptions.propagate(e);
}
}}));
}
@Test(groups={"Integration", "Acceptance"})
public void testGuavaFileMoves() {
int numIterations = numIterations();
double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
final File parentDir = file.getParentFile();
final AtomicInteger i = new AtomicInteger();
measure(PerformanceTestDescriptor.create()
.summary("FilePersistencePerformanceTest.testGuavaFileMoves")
.iterations(numIterations)
.minAcceptablePerSecond(minRatePerSec)
.job(new Runnable() {
public void run() {
File newFile = new File(parentDir, "fileRename-"+i.incrementAndGet()+".txt");
try {
Files.move(file, newFile);
} catch (IOException e) {
throw Exceptions.propagate(e);
}
file = newFile;
}}));
}
}