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();
|
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 {
|
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
|
@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) {
|
if (updatesHandler != null) {
|
||||||
LongArrayList idsToFilter = new LongArrayList(eventIds);
|
LongArrayList idsToFilter = new LongArrayList(eventIds);
|
||||||
ObjectArrayList<TdApi.Object> eventsToFilter = new ObjectArrayList<>(events);
|
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) {
|
if (eventIds[i] != 0) {
|
||||||
idsToFilter.removeLong(i);
|
idsToFilter.removeLong(i);
|
||||||
eventsToFilter.remove(i);
|
eventsToFilter.remove(i);
|
||||||
|
@ -73,13 +73,15 @@ public final class InternalClientManager implements AutoCloseable {
|
|||||||
return clientManager;
|
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);
|
ClientEventsHandler handler = registeredClientEventHandlers.get(clientId);
|
||||||
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.handleEvents(isClosed, clientEventIds, clientEvents);
|
handler.handleEvents(isClosed, clientEventIds, clientEvents, arrayOffset, arrayLength);
|
||||||
} else {
|
} else {
|
||||||
java.util.List<DroppedEvent> droppedEvents = getEffectivelyDroppedEvents(clientEventIds, clientEvents);
|
java.util.List<DroppedEvent> droppedEvents
|
||||||
|
= getEffectivelyDroppedEvents(clientEventIds, clientEvents, arrayOffset, arrayLength);
|
||||||
|
|
||||||
if (!droppedEvents.isEmpty()) {
|
if (!droppedEvents.isEmpty()) {
|
||||||
logger.error("Unknown client id \"{}\"! {} events have been dropped!", clientId, droppedEvents.size());
|
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
|
* 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) {
|
private List<DroppedEvent> getEffectivelyDroppedEvents(long[] clientEventIds, TdApi.Object[] clientEvents,
|
||||||
java.util.List<DroppedEvent> droppedEvents = new ArrayList<>(clientEvents.length);
|
int arrayOffset, int arrayLength) {
|
||||||
for (int i = 0; i < clientEvents.length; i++) {
|
java.util.List<DroppedEvent> droppedEvents = new ArrayList<>(arrayLength);
|
||||||
|
for (int i = arrayOffset; i < arrayOffset + arrayLength; i++) {
|
||||||
long id = clientEventIds[i];
|
long id = clientEventIds[i];
|
||||||
TdApi.Object event = clientEvents[i];
|
TdApi.Object event = clientEvents[i];
|
||||||
boolean mustPrintError = true;
|
boolean mustPrintError = true;
|
||||||
|
@ -60,8 +60,9 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events) {
|
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events,
|
||||||
for (int i = 0; i < eventIds.length; i++) {
|
int arrayOffset, int arrayLength) {
|
||||||
|
for (int i = arrayOffset; i < arrayOffset + arrayLength; i++) {
|
||||||
handleEvent(eventIds[i], events[i]);
|
handleEvent(eventIds[i], events[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
|||||||
"tdlight.dispatcher.use_optimized_dispatcher",
|
"tdlight.dispatcher.use_optimized_dispatcher",
|
||||||
"true"
|
"true"
|
||||||
));
|
));
|
||||||
private static final int MAX_EVENTS = 1000;
|
private static final int MAX_EVENTS = 100;
|
||||||
private static final int[] originalSortingSource = new int[MAX_EVENTS];
|
private static final int[] originalSortingSource = new int[MAX_EVENTS];
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < originalSortingSource.length; i++) {
|
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 int[] clientIds = new int[MAX_EVENTS];
|
||||||
private final long[] eventIds = new long[MAX_EVENTS];
|
private final long[] eventIds = new long[MAX_EVENTS];
|
||||||
private final TdApi.Object[] events = new TdApi.Object[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 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) {
|
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 (i == resultsCount || (i != 0 && clientIds[sortIndex[i]] != lastClientId)) {
|
||||||
if (lastClientIdEventsCount > 0) {
|
if (lastClientIdEventsCount > 0) {
|
||||||
int clientId = lastClientId;
|
int clientId = lastClientId;
|
||||||
long[] clientEventIds = new long[lastClientIdEventsCount];
|
|
||||||
TdApi.Object[] clientEvents = new TdApi.Object[lastClientIdEventsCount];
|
|
||||||
for (int j = 0; j < lastClientIdEventsCount; j++) {
|
for (int j = 0; j < lastClientIdEventsCount; j++) {
|
||||||
clientEventIds[j] = eventIds[sortIndex[i - lastClientIdEventsCount + j]];
|
clientEventIds[j] = eventIds[sortIndex[i - lastClientIdEventsCount + j]];
|
||||||
clientEvents[j] = events[sortIndex[i - lastClientIdEventsCount + j]];
|
clientEvents[j] = events[sortIndex[i - lastClientIdEventsCount + j]];
|
||||||
|
|
||||||
if (clientEventIds[j] == 0 && clientEvents[j] instanceof TdApi.UpdateAuthorizationState) {
|
if (clientEventIds[j] == 0
|
||||||
TdApi.AuthorizationState authorizationState = ((TdApi.UpdateAuthorizationState) clientEvents[j]).authorizationState;
|
&& clientEvents[j].getConstructor() == TdApi.UpdateAuthorizationState.CONSTRUCTOR) {
|
||||||
if (authorizationState instanceof TdApi.AuthorizationStateClosed) {
|
TdApi.AuthorizationState authorizationState
|
||||||
|
= ((TdApi.UpdateAuthorizationState) clientEvents[j]).authorizationState;
|
||||||
|
if (authorizationState.getConstructor() == TdApi.AuthorizationStateClosed.CONSTRUCTOR) {
|
||||||
lastClientClosed = true;
|
lastClientClosed = true;
|
||||||
closedClients.add(clientId);
|
closedClients.add(clientId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cleanClientEventsArray(lastClientIdEventsCount);
|
||||||
|
|
||||||
eventsHandler.handleClientEvents(clientId, lastClientClosed, clientEventIds, clientEvents);
|
eventsHandler.handleClientEvents(clientId, lastClientClosed, clientEventIds, clientEvents,
|
||||||
|
0, lastClientIdEventsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < resultsCount) {
|
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());
|
Set<Integer> clientIds = eventsList.stream().map(e -> e.clientId).collect(Collectors.toSet());
|
||||||
for (int clientId : clientIds) {
|
for (int clientId : clientIds) {
|
||||||
List<Event> clientEventsList = eventsList.stream().filter(e -> e.clientId == clientId).collect(Collectors.toList());
|
List<Event> clientEventsList = eventsList.stream()
|
||||||
long[] clientEventIds = new long[clientEventsList.size()];
|
.filter(e -> e.clientId == clientId)
|
||||||
Object[] clientEvents = new Object[clientEventsList.size()];
|
.collect(Collectors.toList());
|
||||||
boolean closed = false;
|
boolean closed = false;
|
||||||
for (int i = 0; i < clientEventsList.size(); i++) {
|
for (int i = 0; i < clientEventsList.size(); i++) {
|
||||||
Event e = clientEventsList.get(i);
|
Event e = clientEventsList.get(i);
|
||||||
clientEventIds[i] = e.eventId;
|
clientEventIds[i] = e.eventId;
|
||||||
clientEvents[i] = e.event;
|
clientEvents[i] = e.event;
|
||||||
|
|
||||||
if (e.eventId == 0 && e.event instanceof TdApi.UpdateAuthorizationState) {
|
if (e.eventId == 0 && e.event.getConstructor() == TdApi.UpdateAuthorizationState.CONSTRUCTOR) {
|
||||||
TdApi.AuthorizationState authorizationState = ((TdApi.UpdateAuthorizationState) e.event).authorizationState;
|
TdApi.AuthorizationState authorizationState
|
||||||
if (authorizationState instanceof TdApi.AuthorizationStateClosed) {
|
= ((TdApi.UpdateAuthorizationState) e.event).authorizationState;
|
||||||
|
if (authorizationState.getConstructor() == TdApi.AuthorizationStateClosed.CONSTRUCTOR) {
|
||||||
closed = true;
|
closed = true;
|
||||||
closedClients.add(clientId);
|
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);
|
cleanEventsArray(resultsCount);
|
||||||
Arrays.fill(eventIds, 0);
|
|
||||||
Arrays.fill(events, null);
|
|
||||||
|
|
||||||
if (!closedClients.isEmpty()) {
|
if (!closedClients.isEmpty()) {
|
||||||
this.registeredClients.removeAll(closedClients);
|
this.registeredClients.removeAll(closedClients);
|
||||||
@ -171,9 +180,7 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
|||||||
if (interrupted) {
|
if (interrupted) {
|
||||||
if (!jvmShutdown.get()) {
|
if (!jvmShutdown.get()) {
|
||||||
for (Integer clientId : this.registeredClients) {
|
for (Integer clientId : this.registeredClients) {
|
||||||
long[] clientEventIds = new long[0];
|
eventsHandler.handleClientEvents(clientId, true, clientEventIds, clientEvents, 0, 0);
|
||||||
TdApi.Object[] clientEvents = new TdApi.Object[0];
|
|
||||||
eventsHandler.handleClientEvents(clientId, true, clientEventIds, clientEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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")
|
@SuppressWarnings("SameParameterValue")
|
||||||
private int[] generateSortIndex(int from, int to, int[] data) {
|
private int[] generateSortIndex(int from, int to, int[] data) {
|
||||||
int[] sortedIndices = Arrays.copyOfRange(originalSortingSource, from, to);
|
int[] sortedIndices = Arrays.copyOfRange(originalSortingSource, from, to);
|
||||||
|
Loading…
Reference in New Issue
Block a user