|
Java example source code file (LotsOfCancels.java)
The LotsOfCancels.java Java example source code/* * Copyright 2009 Google Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Reproduces O(N^2) behavior of JDK6/7 select() call. This happens when * a selector has many unprocessed updates to its interest set (e.g. adding * OP_READ on a bunch of newly accepted sockets). The O(N^2) is triggered * by cancelling a number of selection keys (or just closing a few sockets). * In this case, select() will first go through the list of cancelled keys * and try to deregister them. That deregistration is O(N^2) over the list * of unprocessed updates to the interest set. * * <p> This O(N^2) behavior is a BUG in JVM and should be fixed. * * <p> The test first creates initCount connections, and adds them * to the server epoll set. It then creates massCount connections, * registers interest (causing updateList to be populated with massCount*2 * elements), but does not add them to epoll set (that would've cleared * updateList). The test then closes initCount connections, thus populating * deregistration queue. The subsequent call to selectNow() will first process * deregistration queue, performing O(N^2) over updateList size, * equal to massCount * 2. * * <p> Note that connect rate is artificially slowed down to compensate * for what I believe is a Linux bug, where too high of a connection rate * ends up in SYN's being dropped and then slow retransmits. * * @author Igor Chernyshev */ public class LotsOfCancels { static long testStartTime; public static void main(String[] args) throws Exception { // the final select should run in less than 1000ms. runTest(500, 2700, 1000); } static void log(String msg) { System.out.println(getLogPrefix() + msg); } static String getLogPrefix() { return durationMillis(testStartTime) + ": "; } /** * Returns the elapsed time since startNanos, in milliseconds. * @param startNanos the start time; this must be a value returned * by {@link System.nanoTime} */ static long durationMillis(long startNanos) { return (System.nanoTime() - startNanos) / (1000L * 1000L); } static void runTest(int initCount, int massCount, int maxSelectTime) throws Exception { testStartTime = System.nanoTime(); InetSocketAddress address = new InetSocketAddress("127.0.0.1", 7359); // Create server channel, add it to selector and run epoll_ctl. log("Setting up server"); Selector serverSelector = Selector.open(); ServerSocketChannel server = ServerSocketChannel.open(); server.configureBlocking(false); server.socket().bind(address, 5000); server.register(serverSelector, SelectionKey.OP_ACCEPT); serverSelector.selectNow(); log("Setting up client"); ClientThread client = new ClientThread(address); client.start(); Thread.sleep(100); // Set up initial set of client sockets. log("Starting initial client connections"); client.connectClients(initCount); Thread.sleep(500); // Wait for client connections to arrive // Accept all initial client sockets, add to selector and run // epoll_ctl. log("Accepting initial connections"); List<SocketChannel> serverChannels1 = acceptAndAddAll(serverSelector, server, initCount); if (serverChannels1.size() != initCount) { throw new Exception("Accepted " + serverChannels1.size() + " instead of " + initCount); } serverSelector.selectNow(); // Set up mass set of client sockets. log("Requesting mass client connections"); client.connectClients(massCount); Thread.sleep(500); // Wait for client connections to arrive // Accept all mass client sockets, add to selector and do NOT // run epoll_ctl. log("Accepting mass connections"); List<SocketChannel> serverChannels2 = acceptAndAddAll(serverSelector, server, massCount); if (serverChannels2.size() != massCount) { throw new Exception("Accepted " + serverChannels2.size() + " instead of " + massCount); } // Close initial set of sockets. log("Closing initial connections"); closeAll(serverChannels1); // Now get the timing of select() call. log("Running the final select call"); long startTime = System.nanoTime(); serverSelector.selectNow(); long duration = durationMillis(startTime); log("Init count = " + initCount + ", mass count = " + massCount + ", duration = " + duration + "ms"); if (duration > maxSelectTime) { System.out.println ("\n\n\n\n\nFAILURE: The final selectNow() took " + duration + "ms " + "- seems like O(N^2) bug is still here\n\n"); System.exit(1); } } static List<SocketChannel> acceptAndAddAll(Selector selector, ServerSocketChannel server, int expected) throws Exception { int retryCount = 0; int acceptCount = 0; List<SocketChannel> channels = new ArrayList Other Java examples (source code examples)Here is a short list of links related to this Java LotsOfCancels.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.