Я работаю с Oracle, и меня просят ускорить работу над устаревшим приложением. Для этого ускорения мне нужен какой-то одномоментный сингл, содержащий временные данные; в настоящее время эти данные хранятся в постоянных таблицах базы данных и накладывают большую нагрузку на базу данных. Временные таблицы не могут использоваться из-за многосеансового доступа к данным.
Я попытался сделать этот синглтон использующим хранимую Java. Основная проблема, которую я нашел - Oracle делает что-то вроде отдельного JVM для каждого сеанса базы данных (https://docs.oracle.com/cd/B28359_01/java.111/b31225/chtwo.htm#BABBDCDI), поэтому Singleton не может быть доступен через общие Память.
Я делаю некоторые API, содержащие "сервер" (singleton) и "client" (методы доступа). Клиент связывается с сервером через локальные сокеты. Поскольку однопоточный характер сохраненного Java (https://docs.oracle.com/cd/B28359_01/java.111/b31225/chtwo.htm#BABHHHDG) сервера принимает и обрабатывает запросы в один поток, подобный этому (упрощенный):
ServerSocket socket = new ServerSocket(..., InetAddress.getByName(null));
while (!finished) {
Socket client = socket.accept();
..
output.println(process(input));
..
client.close();
}
Клиент отправляет запрос следующим образом:
Socket socket = new Socket(InetAddress.getByName(null), getPort(requestId));
..
for (int i = 0; i < data.length; i++) output.println(data[i]);
String result = in.readLine();
..
socket.close();
В то время как runnings тестирует как автономное приложение Java, без Oracle, он работает так на моей рабочей станции:
34001 звонков в 3.178 сек.
Avg. 10698.86721208307 звонков в секунду
Avg. время ожидания: 0.03199905885121026 мс.
Avg. время процесса: 0.0628510926149231 ms.
Это общеприемлемо. Но при загрузке в Oracle такой тест показывает совсем другую скорость:
117 звонков в 24.218 сек.
Avg. 4.831117350730861 звонков в секунду
Avg. время ожидания: 90.17094017094017 мс.
Avg. время процесса: 203.54700854700855 мс.
Почему это так медленно? Что я могу сделать, чтобы исправить эту бессмыслицу? Есть ли лучший способ общения между сеансами в Oracle/jvm?
В результате расследования.
Администраторы не сказали ничего интересного о длительности запросов квестов и/или запросов.
Внутренняя Java-система Oracle в несколько раз медленнее, чем автономная. Я написал простой пример, в котором конвертирует целое число в строку и помещает его в карту; он работает примерно в 4 раза медленнее в хранимой процедуре. Пенальти различается для различных операций.
Я профилировал класс. Используя различные методы (nodelay, повторное использование сокетов, потоков), я достиг примерно в 8 раз быстрее в автономном приложении и примерно в 100 раз быстрее в сохраненной Java, это было ограничение, которое я могу сделать.
В этот момент я отказался от сохраненного-java-only. Я начал автономное приложение с частью сервера рядом с базой данных и настроил клиентскую часть в базу данных для ее подключения. Это дает мне скорость, необходимую мне; в этом случае эффективная скорость составляет около 80% автономного приложения. Эта скорость для меня достаточно; он остановился, чтобы стать узким местом.