создание идентификаторов на основе номера строки

#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);

}