Performance optimization
Reuse the same arrays Clear only the range that needs to be cleared Reduce the MAX_EVENTS constant to 100
This commit is contained in:
parent
887d95f2c2
commit
6558bd9ba9
@ -6,5 +6,5 @@ public interface ClientEventsHandler {
|
||||
|
||||
int getClientId();
|
||||
|
||||
void handleEvents(boolean isClosed, long[] eventIds, Object[] events);
|
||||
void handleEvents(boolean isClosed, long[] eventIds, Object[] events, int arrayOffset, int arrayLength);
|
||||
}
|
||||
|
@ -4,5 +4,10 @@ import it.tdlight.jni.TdApi.Object;
|
||||
|
||||
public interface EventsHandler {
|
||||
|
||||
void handleClientEvents(int clientId, boolean isClosed, long[] clientEventIds, Object[] clientEvents);
|
||||
void handleClientEvents(int clientId,
|
||||
boolean isClosed,
|
||||
long[] clientEventIds,
|
||||
Object[] clientEvents,
|
||||
int arrayOffset,
|
||||
int arrayLength);
|
||||
}
|
||||
|
@ -46,12 +46,13 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events) {
|
||||
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events,
|
||||
int arrayOffset, int arrayLength) {
|
||||
if (updatesHandler != null) {
|
||||
LongArrayList idsToFilter = new LongArrayList(eventIds);
|
||||
ObjectArrayList<TdApi.Object> eventsToFilter = new ObjectArrayList<>(events);
|
||||
|
||||
for (int i = eventIds.length - 1; i >= 0; i--) {
|
||||
for (int i = (arrayOffset + arrayLength) - 1; i >= arrayOffset; i--) {
|
||||
if (eventIds[i] != 0) {
|
||||
idsToFilter.removeLong(i);
|
||||
eventsToFilter.remove(i);
|
||||
|
@ -73,13 +73,15 @@ public final class InternalClientManager implements AutoCloseable {
|
||||
return clientManager;
|
||||
}
|
||||
|
||||
private void handleClientEvents(int clientId, boolean isClosed, long[] clientEventIds, TdApi.Object[] clientEvents) {
|
||||
private void handleClientEvents(int clientId, boolean isClosed, long[] clientEventIds, TdApi.Object[] clientEvents,
|
||||
int arrayOffset, int arrayLength) {
|
||||
ClientEventsHandler handler = registeredClientEventHandlers.get(clientId);
|
||||
|
||||
if (handler != null) {
|
||||
handler.handleEvents(isClosed, clientEventIds, clientEvents);
|
||||
handler.handleEvents(isClosed, clientEventIds, clientEvents, arrayOffset, arrayLength);
|
||||
} else {
|
||||
java.util.List<DroppedEvent> droppedEvents = getEffectivelyDroppedEvents(clientEventIds, clientEvents);
|
||||
java.util.List<DroppedEvent> droppedEvents
|
||||
= getEffectivelyDroppedEvents(clientEventIds, clientEvents, arrayOffset, arrayLength);
|
||||
|
||||
if (!droppedEvents.isEmpty()) {
|
||||
logger.error("Unknown client id \"{}\"! {} events have been dropped!", clientId, droppedEvents.size());
|
||||
@ -101,9 +103,10 @@ public final class InternalClientManager implements AutoCloseable {
|
||||
/**
|
||||
* Get only events that have been dropped, ignoring synthetic errors related to the closure of a client
|
||||
*/
|
||||
private List<DroppedEvent> getEffectivelyDroppedEvents(long[] clientEventIds, TdApi.Object[] clientEvents) {
|
||||
java.util.List<DroppedEvent> droppedEvents = new ArrayList<>(clientEvents.length);
|
||||
for (int i = 0; i < clientEvents.length; i++) {
|
||||
private List<DroppedEvent> getEffectivelyDroppedEvents(long[] clientEventIds, TdApi.Object[] clientEvents,
|
||||
int arrayOffset, int arrayLength) {
|
||||
java.util.List<DroppedEvent> droppedEvents = new ArrayList<>(arrayLength);
|
||||
for (int i = arrayOffset; i < arrayOffset + arrayLength; i++) {
|
||||
long id = clientEventIds[i];
|
||||
TdApi.Object event = clientEvents[i];
|
||||
boolean mustPrintError = true;
|
||||
|
@ -60,8 +60,9 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events) {
|
||||
for (int i = 0; i < eventIds.length; i++) {
|
||||
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events,
|
||||
int arrayOffset, int arrayLength) {
|
||||
for (int i = arrayOffset; i < arrayOffset + arrayLength; i++) {
|
||||
handleEvent(eventIds[i], events[i]);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
"tdlight.dispatcher.use_optimized_dispatcher",
|
||||
"true"
|
||||
));
|
||||
private static final int MAX_EVENTS = 1000;
|
||||
private static final int MAX_EVENTS = 100;
|
||||
private static final int[] originalSortingSource = new int[MAX_EVENTS];
|
||||
static {
|
||||
for (int i = 0; i < originalSortingSource.length; i++) {
|
||||
@ -37,9 +37,15 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
private final int[] clientIds = new int[MAX_EVENTS];
|
||||
private final long[] eventIds = new long[MAX_EVENTS];
|
||||
private final TdApi.Object[] events = new TdApi.Object[MAX_EVENTS];
|
||||
private int eventsLastUsedLength = 0;
|
||||
|
||||
private final long[] clientEventIds = new long[MAX_EVENTS];
|
||||
private final TdApi.Object[] clientEvents = new TdApi.Object[MAX_EVENTS];
|
||||
private int clientEventsLastUsedLength = 0;
|
||||
|
||||
private final CountDownLatch closeWait = new CountDownLatch(1);
|
||||
private final Set<Integer> registeredClients = new ConcurrentHashMap<Integer, java.lang.Object>().keySet(new java.lang.Object());
|
||||
private final Set<Integer> registeredClients
|
||||
= new ConcurrentHashMap<Integer, java.lang.Object>().keySet(new java.lang.Object());
|
||||
|
||||
|
||||
public ResponseReceiver(EventsHandler eventsHandler) {
|
||||
@ -89,22 +95,24 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
if (i == resultsCount || (i != 0 && clientIds[sortIndex[i]] != lastClientId)) {
|
||||
if (lastClientIdEventsCount > 0) {
|
||||
int clientId = lastClientId;
|
||||
long[] clientEventIds = new long[lastClientIdEventsCount];
|
||||
TdApi.Object[] clientEvents = new TdApi.Object[lastClientIdEventsCount];
|
||||
for (int j = 0; j < lastClientIdEventsCount; j++) {
|
||||
clientEventIds[j] = eventIds[sortIndex[i - lastClientIdEventsCount + j]];
|
||||
clientEvents[j] = events[sortIndex[i - lastClientIdEventsCount + j]];
|
||||
|
||||
if (clientEventIds[j] == 0 && clientEvents[j] instanceof TdApi.UpdateAuthorizationState) {
|
||||
TdApi.AuthorizationState authorizationState = ((TdApi.UpdateAuthorizationState) clientEvents[j]).authorizationState;
|
||||
if (authorizationState instanceof TdApi.AuthorizationStateClosed) {
|
||||
if (clientEventIds[j] == 0
|
||||
&& clientEvents[j].getConstructor() == TdApi.UpdateAuthorizationState.CONSTRUCTOR) {
|
||||
TdApi.AuthorizationState authorizationState
|
||||
= ((TdApi.UpdateAuthorizationState) clientEvents[j]).authorizationState;
|
||||
if (authorizationState.getConstructor() == TdApi.AuthorizationStateClosed.CONSTRUCTOR) {
|
||||
lastClientClosed = true;
|
||||
closedClients.add(clientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanClientEventsArray(lastClientIdEventsCount);
|
||||
|
||||
eventsHandler.handleClientEvents(clientId, lastClientClosed, clientEventIds, clientEvents);
|
||||
eventsHandler.handleClientEvents(clientId, lastClientClosed, clientEventIds, clientEvents,
|
||||
0, lastClientIdEventsCount);
|
||||
}
|
||||
|
||||
if (i < resultsCount) {
|
||||
@ -138,30 +146,31 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
}
|
||||
Set<Integer> clientIds = eventsList.stream().map(e -> e.clientId).collect(Collectors.toSet());
|
||||
for (int clientId : clientIds) {
|
||||
List<Event> clientEventsList = eventsList.stream().filter(e -> e.clientId == clientId).collect(Collectors.toList());
|
||||
long[] clientEventIds = new long[clientEventsList.size()];
|
||||
Object[] clientEvents = new Object[clientEventsList.size()];
|
||||
List<Event> clientEventsList = eventsList.stream()
|
||||
.filter(e -> e.clientId == clientId)
|
||||
.collect(Collectors.toList());
|
||||
boolean closed = false;
|
||||
for (int i = 0; i < clientEventsList.size(); i++) {
|
||||
Event e = clientEventsList.get(i);
|
||||
clientEventIds[i] = e.eventId;
|
||||
clientEvents[i] = e.event;
|
||||
|
||||
if (e.eventId == 0 && e.event instanceof TdApi.UpdateAuthorizationState) {
|
||||
TdApi.AuthorizationState authorizationState = ((TdApi.UpdateAuthorizationState) e.event).authorizationState;
|
||||
if (authorizationState instanceof TdApi.AuthorizationStateClosed) {
|
||||
if (e.eventId == 0 && e.event.getConstructor() == TdApi.UpdateAuthorizationState.CONSTRUCTOR) {
|
||||
TdApi.AuthorizationState authorizationState
|
||||
= ((TdApi.UpdateAuthorizationState) e.event).authorizationState;
|
||||
if (authorizationState.getConstructor() == TdApi.AuthorizationStateClosed.CONSTRUCTOR) {
|
||||
closed = true;
|
||||
closedClients.add(clientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
eventsHandler.handleClientEvents(clientId, closed, clientEventIds, clientEvents);
|
||||
cleanClientEventsArray(clientEventsList.size());
|
||||
eventsHandler.handleClientEvents(clientId, closed, clientEventIds, clientEvents,
|
||||
0, clientEventsList.size());
|
||||
}
|
||||
}
|
||||
|
||||
Arrays.fill(clientIds, 0);
|
||||
Arrays.fill(eventIds, 0);
|
||||
Arrays.fill(events, null);
|
||||
cleanEventsArray(resultsCount);
|
||||
|
||||
if (!closedClients.isEmpty()) {
|
||||
this.registeredClients.removeAll(closedClients);
|
||||
@ -171,9 +180,7 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
if (interrupted) {
|
||||
if (!jvmShutdown.get()) {
|
||||
for (Integer clientId : this.registeredClients) {
|
||||
long[] clientEventIds = new long[0];
|
||||
TdApi.Object[] clientEvents = new TdApi.Object[0];
|
||||
eventsHandler.handleClientEvents(clientId, true, clientEventIds, clientEvents);
|
||||
eventsHandler.handleClientEvents(clientId, true, clientEventIds, clientEvents, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,6 +189,20 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanEventsArray(int eventsCount) {
|
||||
if (eventsLastUsedLength > eventsCount) {
|
||||
Arrays.fill(events, eventsCount, eventsLastUsedLength, null);
|
||||
}
|
||||
eventsLastUsedLength = eventsCount;
|
||||
}
|
||||
|
||||
private void cleanClientEventsArray(int clientEventsCount) {
|
||||
if (clientEventsLastUsedLength > clientEventsCount) {
|
||||
Arrays.fill(clientEvents, clientEventsCount, clientEventsLastUsedLength, null);
|
||||
}
|
||||
clientEventsLastUsedLength = clientEventsCount;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private int[] generateSortIndex(int from, int to, int[] data) {
|
||||
int[] sortedIndices = Arrays.copyOfRange(originalSortingSource, from, to);
|
||||
|
Loading…
Reference in New Issue
Block a user