#java
#java
Вопрос:
Я работаю над приложением на основе фреймов, и мне нужно сгенерировать идентификаторы на основе вызывающего сайта, но очень, очень быстро.
Приведу простой пример, демонстрирующий основы;
public void test() {
if (Math.random() < 0.5) {
System.out.println(id());
} else {
System.out.println(id());
}
}
Теперь id()
должен быть присвоен уникальный идентификатор, и при повторном запуске теста идентификаторы должны быть одинаковыми. Таким образом, подсчет невозможен.
Простой способ сделать это — использовать номер строки, поэтому id
метод может выглядеть примерно так (индекс может потребоваться изменить в зависимости от того, как вы его вызываете):
int id() {
return (new Throwable()).getStackTrace()[1].getLineNumber();
}
Для надежности в моем текущем приложении я генерирую идентификатор на основе всего стека. Это делает возможным вложение функций и по-прежнему генерирует уникальный согласованный идентификатор. Проблема в том, что это происходит медленно, где-то около 0.007ms
для одного идентификатора. А для программы просмотра файлов, например, количество идентификаторов, которые необходимо создать, может исчисляться тысячами.
Вот пример того, что я с этим делаю: переключатель, ползунок, метка и кнопка имеют уникальный идентификатор, который воссоздается в каждом кадре.
Я также использую StackWalker, но увеличение, которое это дает, немного разочаровывает. У кого-нибудь есть представление о том, как решить эту проблему?
Комментарии:
1. вы могли бы ранее сгенерировать (большой) набор случайных UUID и просто выполнить итерацию по нему? Или какая-то логика, которая генерирует их отдельно (другой поток), «на лету», создавая какой-то пул случайных идентификаторов (управление дубликатами и т.д. На основе вашей логики)
2. @AsierAranbarri Я не хочу избегать отслеживания логической причины, которая действительно может усложнить ситуацию и сделать ее более подверженной ошибкам.
Ответ №1:
Throwable.getStackTrace()
вычисляет элементы трассировки всего стека. Попробуйте вызвать напрямую Throwable.getStackTraceElement
с помощью самоанализа. Мой тест показывает, что это почти в 2 раза быстрее. Разница должна быть больше, если трассировка стека больше.
public static void main(String[] args) throws Exception {
Long time = System.currentTimeMillis();
for (int i = 0; i < 1000000; i ) {
StackTraceElement e = new Throwable().getStackTrace()[0];
}
// 2862
System.out.println(System.currentTimeMillis() - time);
Method m = Throwable.class.getDeclaredMethod("getStackTraceElement", int.class);
m.setAccessible(true);
time = System.currentTimeMillis();
for (int i = 0; i < 1000000; i ) {
m.invoke(new Throwable(), 0);
}
// 1648
System.out.println(System.currentTimeMillis() - time);
}