/*
* Copyright 2015-present Facebook, Inc.
*
* Licensed 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 com.facebook.buck.util.cache;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.util.WatchmanPathEvent;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.common.collect.Lists;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.Random;
import org.junit.Before;
import org.junit.Test;
public class CacheBenchmark {
@Param({"10000", "100000", "250000"})
private int leavesCount = 100;
private static final Random random = new Random(123);
private List<String> folders = Lists.newArrayList("");
private List<String> leaves = Lists.newArrayList();
private WatchedFileHashCache cache;
@Before
public void setUpTest() throws Exception {
setUpBenchmark();
cache = new WatchedFileHashCache(new FakeProjectFilesystem());
}
private static String generateRandomString() {
StringBuilder sb = new StringBuilder();
int length = random.nextInt(10) + 3; // min 3, max 12
for (int i = 0; i < length; i++) {
sb.append((char) (random.nextInt(26) + 97)); // min 'a', max 'z'
}
return sb.toString();
}
@BeforeExperiment
public void setUpBenchmark() throws Exception {
while (leaves.size() < leavesCount) {
String path = folders.get(random.nextInt(folders.size()));
// create a folder? 25% chance of doing so.
if (random.nextInt(4) == 0) {
path += generateRandomString() + "/";
// is it a leaf?
if (random.nextBoolean()) {
leaves.add(path);
}
folders.add(path);
} else {
// it's a file.
path += generateRandomString() + ".txt";
leaves.add(path);
}
}
}
@Test
public void addMultipleEntriesPerformance() throws Exception {
addMultipleEntries();
}
@Benchmark
public void addMultipleEntries() throws Exception {
addEntries();
}
private void addEntries() throws Exception {
leaves.forEach(
leaf -> {
try {
HashCode hashCode = Hashing.sha1().newHasher().putBytes(leaf.getBytes()).hash();
cache.set(Paths.get(leaf), hashCode);
} catch (IOException e) {
throw new RuntimeException(e.getCause());
}
});
}
@Test
public void invalidateMultipleEntries() throws Exception {
addEntries();
invalidateEntries();
}
@Benchmark
public void invalidateEntries() throws Exception {
leaves.forEach(
leaf ->
cache.onFileSystemChange(
WatchmanPathEvent.of(
Paths.get(leaf), WatchmanPathEvent.Kind.CREATE, Paths.get(leaf))));
}
}