some more micro bench support
This commit is contained in:
parent
dc0e493cce
commit
f90b4e6fee
|
@ -25,14 +25,14 @@ import org.elasticsearch.action.search.SearchResponse;
|
|||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.client.action.bulk.BulkRequestBuilder;
|
||||
import org.elasticsearch.common.RandomStringGenerator;
|
||||
import org.elasticsearch.common.StopWatch;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.SizeValue;
|
||||
import org.elasticsearch.common.util.concurrent.jsr166y.ThreadLocalRandom;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.node.Node;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.client.Requests.*;
|
||||
import static org.elasticsearch.cluster.metadata.IndexMetaData.*;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.*;
|
||||
|
@ -48,10 +48,10 @@ public class TermsFacetSearchBenchmark {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Settings settings = settingsBuilder()
|
||||
.put("index.engine.robin.refreshInterval", "-1")
|
||||
.put("index.refresh_interval", "-1")
|
||||
.put("gateway.type", "local")
|
||||
.put(SETTING_NUMBER_OF_SHARDS, 2)
|
||||
.put(SETTING_NUMBER_OF_REPLICAS, 1)
|
||||
.put(SETTING_NUMBER_OF_REPLICAS, 0)
|
||||
.build();
|
||||
|
||||
Node node1 = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "node1")).node();
|
||||
|
@ -61,11 +61,13 @@ public class TermsFacetSearchBenchmark {
|
|||
|
||||
Client client = clientNode.client();
|
||||
|
||||
long COUNT = SizeValue.parseSizeValue("1m").singles();
|
||||
long COUNT = SizeValue.parseSizeValue("5m").singles();
|
||||
int BATCH = 100;
|
||||
int QUERY_WARMUP = 20;
|
||||
int QUERY_COUNT = 200;
|
||||
int NUMBER_OF_TERMS = 10;
|
||||
int NUMBER_OF_TERMS = 200;
|
||||
int NUMBER_OF_MULTI_VALUE_TERMS = 5;
|
||||
int STRING_TERM_SIZE = 5;
|
||||
|
||||
long[] lValues = new long[NUMBER_OF_TERMS];
|
||||
for (int i = 0; i < NUMBER_OF_TERMS; i++) {
|
||||
|
@ -73,7 +75,7 @@ public class TermsFacetSearchBenchmark {
|
|||
}
|
||||
String[] sValues = new String[NUMBER_OF_TERMS];
|
||||
for (int i = 0; i < NUMBER_OF_TERMS; i++) {
|
||||
sValues[i] = Integer.toString(i);
|
||||
sValues[i] = RandomStringGenerator.randomAlphabetic(STRING_TERM_SIZE);
|
||||
}
|
||||
|
||||
Thread.sleep(10000);
|
||||
|
@ -90,8 +92,22 @@ public class TermsFacetSearchBenchmark {
|
|||
BulkRequestBuilder request = client.prepareBulk();
|
||||
for (int j = 0; j < BATCH; j++) {
|
||||
counter++;
|
||||
|
||||
XContentBuilder builder = jsonBuilder().startObject();
|
||||
builder.field("id", Integer.toString(counter));
|
||||
builder.field("s_value", sValues[counter % sValues.length]);
|
||||
builder.field("i_value", lValues[counter % lValues.length]);
|
||||
|
||||
builder.startArray("sm_value");
|
||||
for (int k = 0; k < NUMBER_OF_MULTI_VALUE_TERMS; k++) {
|
||||
builder.value(sValues[ThreadLocalRandom.current().nextInt(sValues.length)]);
|
||||
}
|
||||
builder.endArray();
|
||||
|
||||
builder.endObject();
|
||||
|
||||
request.add(Requests.indexRequest("test").type("type1").id(Integer.toString(counter))
|
||||
.source(source(Integer.toString(counter), sValues[counter % sValues.length], lValues[counter % lValues.length])));
|
||||
.source(builder));
|
||||
}
|
||||
BulkResponse response = request.execute().actionGet();
|
||||
if (response.hasFailures()) {
|
||||
|
@ -113,23 +129,28 @@ public class TermsFacetSearchBenchmark {
|
|||
client.admin().indices().prepareRefresh().execute().actionGet();
|
||||
System.out.println("--> Number of docs in index: " + client.prepareCount().setQuery(matchAllQuery()).execute().actionGet().count());
|
||||
|
||||
System.out.println("--> Warmup...");
|
||||
|
||||
long totalQueryTime = 0;
|
||||
|
||||
// S_VALUE
|
||||
|
||||
System.out.println("--> Warmup (s_value) ...");
|
||||
// run just the child query, warm up first
|
||||
for (int j = 0; j < QUERY_WARMUP; j++) {
|
||||
SearchResponse searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("s_value").field("s_value"))
|
||||
.addFacet(termsFacet("l_value").field("l_value"))
|
||||
.execute().actionGet();
|
||||
if (j == 0) {
|
||||
System.out.println("--> Warmup took: " + searchResponse.took());
|
||||
System.out.println("--> Loading (s_value) took: " + searchResponse.took());
|
||||
}
|
||||
if (searchResponse.hits().totalHits() != COUNT) {
|
||||
System.err.println("--> mismatch on hits");
|
||||
}
|
||||
}
|
||||
System.out.println("--> Warmup (s_value) DONE");
|
||||
|
||||
long totalQueryTime = 0;
|
||||
totalQueryTime = 0;
|
||||
for (int j = 0; j < QUERY_COUNT; j++) {
|
||||
SearchResponse searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
|
@ -142,6 +163,24 @@ public class TermsFacetSearchBenchmark {
|
|||
}
|
||||
System.out.println("--> Terms Facet (s_value) " + (totalQueryTime / QUERY_COUNT) + "ms");
|
||||
|
||||
client.admin().indices().prepareClearCache().setFieldDataCache(true).execute().actionGet();
|
||||
|
||||
System.out.println("--> Warmup (l_value) ...");
|
||||
// run just the child query, warm up first
|
||||
for (int j = 0; j < QUERY_WARMUP; j++) {
|
||||
SearchResponse searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("l_value").field("l_value"))
|
||||
.execute().actionGet();
|
||||
if (j == 0) {
|
||||
System.out.println("--> Loading (l_value) took: " + searchResponse.took());
|
||||
}
|
||||
if (searchResponse.hits().totalHits() != COUNT) {
|
||||
System.err.println("--> mismatch on hits");
|
||||
}
|
||||
}
|
||||
System.out.println("--> Warmup (l_value) DONE");
|
||||
|
||||
totalQueryTime = 0;
|
||||
for (int j = 0; j < QUERY_COUNT; j++) {
|
||||
SearchResponse searchResponse = client.prepareSearch()
|
||||
|
@ -155,14 +194,41 @@ public class TermsFacetSearchBenchmark {
|
|||
}
|
||||
System.out.println("--> Terms Facet (l_value) " + (totalQueryTime / QUERY_COUNT) + "ms");
|
||||
|
||||
client.admin().indices().prepareClearCache().setFieldDataCache(true).execute().actionGet();
|
||||
|
||||
System.out.println("--> Warmup (sm_value) ...");
|
||||
// run just the child query, warm up first
|
||||
for (int j = 0; j < QUERY_WARMUP; j++) {
|
||||
SearchResponse searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("sm_value").field("sm_value"))
|
||||
.execute().actionGet();
|
||||
if (j == 0) {
|
||||
System.out.println("--> Loading (sm_value) took: " + searchResponse.took());
|
||||
}
|
||||
if (searchResponse.hits().totalHits() != COUNT) {
|
||||
System.err.println("--> mismatch on hits");
|
||||
}
|
||||
}
|
||||
System.out.println("--> Warmup (sm_value) DONE");
|
||||
|
||||
|
||||
totalQueryTime = 0;
|
||||
for (int j = 0; j < QUERY_COUNT; j++) {
|
||||
SearchResponse searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("sm_value").field("sm_value"))
|
||||
.execute().actionGet();
|
||||
if (searchResponse.hits().totalHits() != COUNT) {
|
||||
System.err.println("--> mismatch on hits");
|
||||
}
|
||||
totalQueryTime += searchResponse.tookInMillis();
|
||||
}
|
||||
System.out.println("--> Terms Facet (sm_value) " + (totalQueryTime / QUERY_COUNT) + "ms");
|
||||
|
||||
clientNode.close();
|
||||
|
||||
node1.close();
|
||||
node2.close();
|
||||
}
|
||||
|
||||
private static XContentBuilder source(String id, String sValue, long lValue) throws IOException {
|
||||
return jsonBuilder().startObject().field("id", id).field("s_value", sValue).field("l_value", lValue).endObject();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search 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.elasticsearch.benchmark.trove;
|
||||
|
||||
import org.elasticsearch.common.RandomStringGenerator;
|
||||
import org.elasticsearch.common.StopWatch;
|
||||
import org.elasticsearch.common.trove.map.hash.THashMap;
|
||||
import org.elasticsearch.common.trove.map.hash.TObjectIntHashMap;
|
||||
import org.elasticsearch.common.unit.SizeValue;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class StringMapAdjustOrPutBenchmark {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
int NUMBER_OF_KEYS = (int) SizeValue.parseSizeValue("200k").singles();
|
||||
int STRING_SIZE = 5;
|
||||
long PUT_OPERATIONS = SizeValue.parseSizeValue("5m").singles();
|
||||
long ITERATIONS = 10;
|
||||
boolean REUSE = true;
|
||||
|
||||
|
||||
String[] values = new String[NUMBER_OF_KEYS];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = RandomStringGenerator.randomAlphabetic(STRING_SIZE);
|
||||
}
|
||||
|
||||
StopWatch stopWatch;
|
||||
|
||||
stopWatch = new StopWatch().start();
|
||||
TObjectIntHashMap<String> map = new TObjectIntHashMap<String>();
|
||||
for (long iter = 0; iter < ITERATIONS; iter++) {
|
||||
if (REUSE) {
|
||||
map.clear();
|
||||
} else {
|
||||
map = new TObjectIntHashMap<String>();
|
||||
}
|
||||
for (long i = 0; i < PUT_OPERATIONS; i++) {
|
||||
map.adjustOrPutValue(values[(int) (i % NUMBER_OF_KEYS)], 1, 1);
|
||||
}
|
||||
}
|
||||
map.clear();
|
||||
map = null;
|
||||
|
||||
System.out.println("TObjectIntHashMap: TP (seconds) " + ITERATIONS / stopWatch.stop().totalTime().secondsFrac());
|
||||
|
||||
// now test with THashMap
|
||||
stopWatch = new StopWatch().start();
|
||||
THashMap<String, StringEntry> tMap = new THashMap<String, StringEntry>();
|
||||
for (long iter = 0; iter < ITERATIONS; iter++) {
|
||||
if (REUSE) {
|
||||
tMap.clear();
|
||||
} else {
|
||||
tMap = new THashMap<String, StringEntry>();
|
||||
}
|
||||
for (long i = 0; i < PUT_OPERATIONS; i++) {
|
||||
String key = values[(int) (i % NUMBER_OF_KEYS)];
|
||||
StringEntry stringEntry = tMap.get(key);
|
||||
if (stringEntry == null) {
|
||||
stringEntry = new StringEntry(key, 1);
|
||||
tMap.put(key, stringEntry);
|
||||
} else {
|
||||
stringEntry.counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("THashMap: TP (seconds) " + ITERATIONS / stopWatch.stop().totalTime().secondsFrac());
|
||||
|
||||
tMap.clear();
|
||||
tMap = null;
|
||||
|
||||
stopWatch = new StopWatch().start();
|
||||
HashMap<String, StringEntry> hMap = new HashMap<String, StringEntry>();
|
||||
for (long iter = 0; iter < ITERATIONS; iter++) {
|
||||
if (REUSE) {
|
||||
hMap.clear();
|
||||
} else {
|
||||
hMap = new HashMap<String, StringEntry>();
|
||||
}
|
||||
for (long i = 0; i < PUT_OPERATIONS; i++) {
|
||||
String key = values[(int) (i % NUMBER_OF_KEYS)];
|
||||
StringEntry stringEntry = hMap.get(key);
|
||||
if (stringEntry == null) {
|
||||
stringEntry = new StringEntry(key, 1);
|
||||
hMap.put(key, stringEntry);
|
||||
} else {
|
||||
stringEntry.counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("HashMap: TP (seconds) " + ITERATIONS / stopWatch.stop().totalTime().secondsFrac());
|
||||
|
||||
}
|
||||
|
||||
|
||||
static class StringEntry {
|
||||
String key;
|
||||
int counter;
|
||||
|
||||
StringEntry(String key, int counter) {
|
||||
this.key = key;
|
||||
this.counter = counter;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search 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.elasticsearch.common;
|
||||
|
||||
import org.elasticsearch.common.util.concurrent.jsr166y.ThreadLocalRandom;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomStringGenerator {
|
||||
|
||||
/**
|
||||
* <p><code>RandomStringUtils</code> instances should NOT be constructed in
|
||||
* standard programming. Instead, the class should be used as
|
||||
* <code>RandomStringUtils.random(5);</code>.</p>
|
||||
*
|
||||
* <p>This constructor is public to permit tools that require a JavaBean instance
|
||||
* to operate.</p>
|
||||
*/
|
||||
public RandomStringGenerator() {
|
||||
super();
|
||||
}
|
||||
|
||||
// Random
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of all characters.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @return the random string
|
||||
*/
|
||||
public static String random(int count) {
|
||||
return random(count, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of characters whose
|
||||
* ASCII value is between <code>32</code> and <code>126</code> (inclusive).</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @return the random string
|
||||
*/
|
||||
public static String randomAscii(int count) {
|
||||
return random(count, 32, 127, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of alphabetic
|
||||
* characters.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @return the random string
|
||||
*/
|
||||
public static String randomAlphabetic(int count) {
|
||||
return random(count, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of alpha-numeric
|
||||
* characters.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @return the random string
|
||||
*/
|
||||
public static String randomAlphanumeric(int count) {
|
||||
return random(count, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of numeric
|
||||
* characters.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @return the random string
|
||||
*/
|
||||
public static String randomNumeric(int count) {
|
||||
return random(count, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of alpha-numeric
|
||||
* characters as indicated by the arguments.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @param letters if <code>true</code>, generated string will include
|
||||
* alphabetic characters
|
||||
* @param numbers if <code>true</code>, generated string will include
|
||||
* numeric characters
|
||||
* @return the random string
|
||||
*/
|
||||
public static String random(int count, boolean letters, boolean numbers) {
|
||||
return random(count, 0, 0, letters, numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of alpha-numeric
|
||||
* characters as indicated by the arguments.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @param start the position in set of chars to start at
|
||||
* @param end the position in set of chars to end before
|
||||
* @param letters if <code>true</code>, generated string will include
|
||||
* alphabetic characters
|
||||
* @param numbers if <code>true</code>, generated string will include
|
||||
* numeric characters
|
||||
* @return the random string
|
||||
*/
|
||||
public static String random(int count, int start, int end, boolean letters, boolean numbers) {
|
||||
return random(count, start, end, letters, numbers, null, ThreadLocalRandom.current());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string based on a variety of options, using
|
||||
* default source of randomness.</p>
|
||||
*
|
||||
* <p>This method has exactly the same semantics as
|
||||
* {@link #random(int, int, int, boolean, boolean, char[], Random)}, but
|
||||
* instead of using an externally supplied source of randomness, it uses
|
||||
* the internal static {@link Random} instance.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @param start the position in set of chars to start at
|
||||
* @param end the position in set of chars to end before
|
||||
* @param letters only allow letters?
|
||||
* @param numbers only allow numbers?
|
||||
* @param chars the set of chars to choose randoms from.
|
||||
* If <code>null</code>, then it will use the set of all chars.
|
||||
* @return the random string
|
||||
* @throws ArrayIndexOutOfBoundsException if there are not
|
||||
* <code>(end - start) + 1</code> characters in the set array.
|
||||
*/
|
||||
public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) {
|
||||
return random(count, start, end, letters, numbers, chars, ThreadLocalRandom.current());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string based on a variety of options, using
|
||||
* supplied source of randomness.</p>
|
||||
*
|
||||
* <p>If start and end are both <code>0</code>, start and end are set
|
||||
* to <code>' '</code> and <code>'z'</code>, the ASCII printable
|
||||
* characters, will be used, unless letters and numbers are both
|
||||
* <code>false</code>, in which case, start and end are set to
|
||||
* <code>0</code> and <code>Integer.MAX_VALUE</code>.
|
||||
*
|
||||
* <p>If set is not <code>null</code>, characters between start and
|
||||
* end are chosen.</p>
|
||||
*
|
||||
* <p>This method accepts a user-supplied {@link Random}
|
||||
* instance to use as a source of randomness. By seeding a single
|
||||
* {@link Random} instance with a fixed seed and using it for each call,
|
||||
* the same random sequence of strings can be generated repeatedly
|
||||
* and predictably.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @param start the position in set of chars to start at
|
||||
* @param end the position in set of chars to end before
|
||||
* @param letters only allow letters?
|
||||
* @param numbers only allow numbers?
|
||||
* @param chars the set of chars to choose randoms from.
|
||||
* If <code>null</code>, then it will use the set of all chars.
|
||||
* @param random a source of randomness.
|
||||
* @return the random string
|
||||
* @throws ArrayIndexOutOfBoundsException if there are not
|
||||
* <code>(end - start) + 1</code> characters in the set array.
|
||||
* @throws IllegalArgumentException if <code>count</code> < 0.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static String random(int count, int start, int end, boolean letters, boolean numbers,
|
||||
char[] chars, Random random) {
|
||||
if (count == 0) {
|
||||
return "";
|
||||
} else if (count < 0) {
|
||||
throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
|
||||
}
|
||||
if ((start == 0) && (end == 0)) {
|
||||
end = 'z' + 1;
|
||||
start = ' ';
|
||||
if (!letters && !numbers) {
|
||||
start = 0;
|
||||
end = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
char[] buffer = new char[count];
|
||||
int gap = end - start;
|
||||
|
||||
while (count-- != 0) {
|
||||
char ch;
|
||||
if (chars == null) {
|
||||
ch = (char) (random.nextInt(gap) + start);
|
||||
} else {
|
||||
ch = chars[random.nextInt(gap) + start];
|
||||
}
|
||||
if ((letters && Character.isLetter(ch))
|
||||
|| (numbers && Character.isDigit(ch))
|
||||
|| (!letters && !numbers)) {
|
||||
if (ch >= 56320 && ch <= 57343) {
|
||||
if (count == 0) {
|
||||
count++;
|
||||
} else {
|
||||
// low surrogate, insert high surrogate after putting it in
|
||||
buffer[count] = ch;
|
||||
count--;
|
||||
buffer[count] = (char) (55296 + random.nextInt(128));
|
||||
}
|
||||
} else if (ch >= 55296 && ch <= 56191) {
|
||||
if (count == 0) {
|
||||
count++;
|
||||
} else {
|
||||
// high surrogate, insert low surrogate before putting it in
|
||||
buffer[count] = (char) (56320 + random.nextInt(128));
|
||||
count--;
|
||||
buffer[count] = ch;
|
||||
}
|
||||
} else if (ch >= 56192 && ch <= 56319) {
|
||||
// private high surrogate, no effing clue, so skip it
|
||||
count++;
|
||||
} else {
|
||||
buffer[count] = ch;
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return new String(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @param chars the String containing the set of characters to use,
|
||||
* may be null
|
||||
* @return the random string
|
||||
* @throws IllegalArgumentException if <code>count</code> < 0.
|
||||
*/
|
||||
public static String random(int count, String chars) {
|
||||
if (chars == null) {
|
||||
return random(count, 0, 0, false, false, null, ThreadLocalRandom.current());
|
||||
}
|
||||
return random(count, chars.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a random string whose length is the number of characters
|
||||
* specified.</p>
|
||||
*
|
||||
* <p>Characters will be chosen from the set of characters specified.</p>
|
||||
*
|
||||
* @param count the length of random string to create
|
||||
* @param chars the character array containing the set of characters to use,
|
||||
* may be null
|
||||
* @return the random string
|
||||
* @throws IllegalArgumentException if <code>count</code> < 0.
|
||||
*/
|
||||
public static String random(int count, char[] chars) {
|
||||
if (chars == null) {
|
||||
return random(count, 0, 0, false, false, null, ThreadLocalRandom.current());
|
||||
}
|
||||
return random(count, 0, chars.length, false, false, chars, ThreadLocalRandom.current());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue