diff --git a/src/main/java/org/fisco/bcos/sdk/demo/perf/PerformanceBFS.java b/src/main/java/org/fisco/bcos/sdk/demo/perf/PerformanceBFS.java new file mode 100644 index 0000000..96db317 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/demo/perf/PerformanceBFS.java @@ -0,0 +1,194 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *

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 org.fisco.bcos.sdk.demo.perf; + +import com.google.common.util.concurrent.RateLimiter; + +import java.net.URL; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + +import me.tongfei.progressbar.ProgressBar; +import me.tongfei.progressbar.ProgressBarBuilder; +import me.tongfei.progressbar.ProgressBarStyle; +import org.fisco.bcos.sdk.demo.contract.HelloWorld; +import org.fisco.bcos.sdk.v3.BcosSDK; +import org.fisco.bcos.sdk.v3.client.Client; +import org.fisco.bcos.sdk.v3.contract.precompiled.bfs.BFSPrecompiled; +import org.fisco.bcos.sdk.v3.contract.precompiled.model.PrecompiledAddress; +import org.fisco.bcos.sdk.v3.model.ConstantConfig; +import org.fisco.bcos.sdk.v3.model.EnumNodeVersion; +import org.fisco.bcos.sdk.v3.model.TransactionReceipt; +import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback; +import org.fisco.bcos.sdk.v3.utils.ThreadPoolService; + +public class PerformanceBFS { + private static final Set supportCommands = + new HashSet<>(Arrays.asList("mkdir", "link")); + private static String contractAddress; + private static EnumNodeVersion version; + + private static void Usage() { + System.out.println(" Usage:"); + System.out.println("===== PerformanceBFS test==========="); + System.out.println( + " \t java -cp 'conf/:lib/*:apps/*' org.fisco.bcos.sdk.demo.perf.PerformanceBFS [mkdir] [count] [tps] [groupId]."); + System.out.println( + " \t java -cp 'conf/:lib/*:apps/*' org.fisco.bcos.sdk.demo.perf.PerformanceBFS [link] [count] [tps] [groupId]."); + } + + public static void main(String[] args) { + try { + String configFileName = ConstantConfig.CONFIG_FILE_NAME; + URL configUrl = PerformanceBFS.class.getClassLoader().getResource(configFileName); + if (configUrl == null) { + System.out.println("The configFile " + configFileName + " doesn't exist!"); + return; + } + if (args.length < 4) { + Usage(); + return; + } + String command = args[0]; + int sendCount = Integer.parseInt(args[1]); + int qps = Integer.parseInt(args[2]); + String groupId = args[3]; + System.out.println( + "====== PerformanceBFS " + + command + + ", count: " + + sendCount + + ", qps:" + + qps + + ", groupId: " + + groupId); + + if (!supportCommands.contains(command)) { + System.out.println("Command " + command + " not supported!"); + Usage(); + return; + } + + String configFile = configUrl.getPath(); + BcosSDK sdk = BcosSDK.build(configFile); + + // build the client + Client client = sdk.getClient(groupId); + if (client == null) { + System.out.println("client is null"); + return; + } + version = client.getChainVersion(); + + HelloWorld helloWorld = + HelloWorld.deploy(client, client.getCryptoSuite().getCryptoKeyPair()); + contractAddress = helloWorld.getContractAddress(); + + BFSPrecompiled bfsPrecompiled = + BFSPrecompiled.load( + PrecompiledAddress.BFS_PRECOMPILED_ADDRESS, + client, + client.getCryptoSuite().getCryptoKeyPair()); + + int totalCount = sendCount; + CountDownLatch countDownLatch = new CountDownLatch(totalCount); + RateLimiter limiter = RateLimiter.create(qps); + ProgressBar sentBar = + new ProgressBarBuilder() + .setTaskName("Send :") + .setInitialMax(sendCount) + .setStyle(ProgressBarStyle.UNICODE_BLOCK) + .build(); + ProgressBar receivedBar = + new ProgressBarBuilder() + .setTaskName("Receive:") + .setInitialMax(totalCount) + .setStyle(ProgressBarStyle.UNICODE_BLOCK) + .build(); + + System.out.println("====== PerformanceBFS " + command + " start ======"); + ThreadPoolService threadPoolService = + new ThreadPoolService( + "PerformanceBFS", Runtime.getRuntime().availableProcessors()); + + Collector collector = new Collector(); + collector.setTotal(totalCount); + for (int i = 0; i < sendCount; ++i) { + limiter.acquire(); + threadPoolService + .getThreadPool() + .execute( + () -> { + long now = System.currentTimeMillis(); + callBFSOperation( + command, + bfsPrecompiled, + new TransactionCallback() { + @Override + public void onResponse(TransactionReceipt receipt) { + long cost = System.currentTimeMillis() - now; + collector.onMessage(receipt, cost); + receivedBar.step(); + countDownLatch.countDown(); + } + }); + sentBar.step(); + }); + } + // wait to collect all the receipts + countDownLatch.await(); + receivedBar.close(); + sentBar.close(); + collector.report(); + threadPoolService.stop(); + System.exit(0); + } catch (Exception e) { + System.out.println( + "====== PerformanceBFS test failed, error message: " + e.getMessage()); + e.printStackTrace(); + System.exit(0); + } + } + + private static void callBFSOperation( + String command, BFSPrecompiled bfsPrecompiled, TransactionCallback callback) { + if (command.compareToIgnoreCase("mkdir") == 0) { + mkdir(bfsPrecompiled, callback); + } + if (command.compareToIgnoreCase("link") == 0) { + link(bfsPrecompiled, callback); + } + } + + public static String getNextID() { + return String.valueOf(Math.abs(new Random().nextInt())) + System.currentTimeMillis(); + } + + private static void mkdir(BFSPrecompiled bfsPrecompiled, TransactionCallback callback) { + String nextID = getNextID(); + bfsPrecompiled.mkdir("/apps/fruit" + nextID, callback); + } + + private static void link(BFSPrecompiled bfsPrecompiled, TransactionCallback callback) { + String nextID = getNextID(); + if (version.compareToVersion(EnumNodeVersion.BCOS_3_1_0) >= 0) { + bfsPrecompiled.link("/apps/link" + nextID, contractAddress, "", callback); + } else { + bfsPrecompiled.link("link", nextID, contractAddress, "", callback); + } + } +}