@@ -533,6 +533,53 @@ class Queue<T> {
533533 }
534534}
535535
536+ class LoadEstimator {
537+
538+ private static _HISTORY_LENGTH = 10 ;
539+ private static _INSTANCE : LoadEstimator | null = null ;
540+ public static getInstance ( ) : LoadEstimator {
541+ if ( ! LoadEstimator . _INSTANCE ) {
542+ LoadEstimator . _INSTANCE = new LoadEstimator ( ) ;
543+ }
544+ return LoadEstimator . _INSTANCE ;
545+ }
546+
547+ private lastRuns : number [ ] ;
548+
549+ constructor ( ) {
550+ this . lastRuns = [ ] ;
551+ const now = Date . now ( ) ;
552+ for ( let i = 0 ; i < LoadEstimator . _HISTORY_LENGTH ; i ++ ) {
553+ this . lastRuns [ i ] = now - 1000 * i ;
554+ }
555+ setInterval ( ( ) => {
556+ for ( let i = LoadEstimator . _HISTORY_LENGTH ; i >= 1 ; i -- ) {
557+ this . lastRuns [ i ] = this . lastRuns [ i - 1 ] ;
558+ }
559+ this . lastRuns [ 0 ] = Date . now ( ) ;
560+ } , 1000 ) ;
561+ }
562+
563+ /**
564+ * returns an estimative number, from 0 (low load) to 1 (high load)
565+ */
566+ public load ( ) : number {
567+ const now = Date . now ( ) ;
568+ const historyLimit = ( 1 + LoadEstimator . _HISTORY_LENGTH ) * 1000 ;
569+ let score = 0 ;
570+ for ( let i = 0 ; i < LoadEstimator . _HISTORY_LENGTH ; i ++ ) {
571+ if ( now - this . lastRuns [ i ] <= historyLimit ) {
572+ score ++ ;
573+ }
574+ }
575+ return 1 - score / LoadEstimator . _HISTORY_LENGTH ;
576+ }
577+
578+ public hasHighLoad ( ) : boolean {
579+ return this . load ( ) >= 0.5 ;
580+ }
581+ }
582+
536583/**
537584 * Same as Protocol, but will actually track messages and acks.
538585 * Moreover, it will ensure no messages are lost if there are no event listeners.
@@ -559,6 +606,8 @@ export class PersistentProtocol implements IMessagePassingProtocol {
559606 private _socketReader : ProtocolReader ;
560607 private _socketDisposables : IDisposable [ ] ;
561608
609+ private readonly _loadEstimator = LoadEstimator . getInstance ( ) ;
610+
562611 private readonly _onControlMessage = new BufferedEmitter < VSBuffer > ( ) ;
563612 readonly onControlMessage : Event < VSBuffer > = this . _onControlMessage . event ;
564613
@@ -670,15 +719,19 @@ export class PersistentProtocol implements IMessagePassingProtocol {
670719
671720 const timeSinceLastIncomingMsg = Date . now ( ) - this . _socketReader . lastReadTime ;
672721 if ( timeSinceLastIncomingMsg >= ProtocolConstants . KeepAliveTimeoutTime ) {
673- // Trash the socket
674- this . _onSocketTimeout . fire ( undefined ) ;
675- return ;
722+ // It's been a long time since we received a server message
723+ // But this might be caused by the event loop being busy and failing to read messages
724+ if ( ! this . _loadEstimator . hasHighLoad ( ) ) {
725+ // Trash the socket
726+ this . _onSocketTimeout . fire ( undefined ) ;
727+ return ;
728+ }
676729 }
677730
678731 this . _incomingKeepAliveTimeout = setTimeout ( ( ) => {
679732 this . _incomingKeepAliveTimeout = null ;
680733 this . _recvKeepAliveCheck ( ) ;
681- } , ProtocolConstants . KeepAliveTimeoutTime - timeSinceLastIncomingMsg + 5 ) ;
734+ } , Math . max ( ProtocolConstants . KeepAliveTimeoutTime - timeSinceLastIncomingMsg , 0 ) + 5 ) ;
682735 }
683736
684737 public getSocket ( ) : ISocket {
@@ -821,15 +874,19 @@ export class PersistentProtocol implements IMessagePassingProtocol {
821874 const oldestUnacknowledgedMsg = this . _outgoingUnackMsg . peek ( ) ! ;
822875 const timeSinceOldestUnacknowledgedMsg = Date . now ( ) - oldestUnacknowledgedMsg . writtenTime ;
823876 if ( timeSinceOldestUnacknowledgedMsg >= ProtocolConstants . AcknowledgeTimeoutTime ) {
824- // Trash the socket
825- this . _onSocketTimeout . fire ( undefined ) ;
826- return ;
877+ // It's been a long time since our sent message was acknowledged
878+ // But this might be caused by the event loop being busy and failing to read messages
879+ if ( ! this . _loadEstimator . hasHighLoad ( ) ) {
880+ // Trash the socket
881+ this . _onSocketTimeout . fire ( undefined ) ;
882+ return ;
883+ }
827884 }
828885
829886 this . _outgoingAckTimeout = setTimeout ( ( ) => {
830887 this . _outgoingAckTimeout = null ;
831888 this . _recvAckCheck ( ) ;
832- } , ProtocolConstants . AcknowledgeTimeoutTime - timeSinceOldestUnacknowledgedMsg + 5 ) ;
889+ } , Math . max ( ProtocolConstants . AcknowledgeTimeoutTime - timeSinceOldestUnacknowledgedMsg , 0 ) + 5 ) ;
833890 }
834891
835892 private _sendAck ( ) : void {
0 commit comments