def get_factors(self, target_latency, pixel_count): factors = [] if len(self.client_latency)>0: #client latency: (we want to keep client latency as low as can be) metric = "client-latency" l = 0.005 + self.min_client_latency wm = logp(l / 0.020) factors.append(calculate_for_target(metric, l, self.avg_client_latency, self.recent_client_latency, aim=0.8, slope=0.005, smoothing=sqrt, weight_multiplier=wm)) if len(self.client_ping_latency)>0: metric = "client-ping-latency" l = 0.005 + self.min_client_ping_latency wm = logp(l / 0.050) factors.append(calculate_for_target(metric, l, self.avg_client_ping_latency, self.recent_client_ping_latency, aim=0.95, slope=0.005, smoothing=sqrt, weight_multiplier=wm)) if len(self.server_ping_latency)>0: metric = "server-ping-latency" l = 0.005 + self.min_server_ping_latency wm = logp(l / 0.050) factors.append(calculate_for_target(metric, l, self.avg_server_ping_latency, self.recent_server_ping_latency, aim=0.95, slope=0.005, smoothing=sqrt, weight_multiplier=wm)) #packet queue size: (includes packets from all windows) factors.append(queue_inspect("packet-queue-size", self.packet_qsizes, smoothing=sqrt)) #packet queue pixels (global): qpix_time_values = [(event_time, value) for event_time, _, value in list(self.damage_packet_qpixels)] factors.append(queue_inspect("packet-queue-pixels", qpix_time_values, div=pixel_count, smoothing=sqrt)) #compression data queue: (This is an important metric since each item will consume a fair amount of memory and each will later on go through the other queues.) factors.append(queue_inspect("compression-work-queue", self.compression_work_qsizes)) if self.mmap_size>0: #full: effective range is 0.0 to ~1.2 full = 1.0-float(self.mmap_free_size)/self.mmap_size #aim for ~33% factors.append(("mmap-area", "%s%% full" % int(100*full), logp(3*full), (3*full)**2)) return factors
def calculate_batch_delay(wid, window_dimensions, has_focus, other_is_fullscreen, other_is_maximized, is_OR, soft_expired, batch, global_statistics, statistics): """ Calculates a new batch delay. We first gather some statistics, then use them to calculate a number of factors. which are then used to adjust the batch delay in 'update_batch_delay'. """ low_limit = get_low_limit(global_statistics.mmap_size>0, window_dimensions) #for each indicator: (description, factor, weight) factors = statistics.get_factors(low_limit, batch.delay) statistics.target_latency = statistics.get_target_client_latency(global_statistics.min_client_latency, global_statistics.avg_client_latency) factors += global_statistics.get_factors(statistics.target_latency, low_limit) #damage pixels waiting in the packet queue: (extract data for our window id only) time_values = global_statistics.get_damage_pixels(wid) factors.append(queue_inspect("damage-packet-queue-pixels", time_values, div=low_limit, smoothing=sqrt)) #boost window that has focus and OR windows: factors.append(("focus", {"has_focus" : has_focus}, int(not has_focus), int(has_focus))) factors.append(("override-redirect", {"is_OR" : is_OR}, int(not is_OR), int(is_OR))) #if another window is fullscreen or maximized, slow us down: factors.append(("fullscreen", {"other_is_fullscreen" : other_is_fullscreen}, 4*int(other_is_fullscreen), int(other_is_fullscreen))) factors.append(("maximized", {"other_is_maximized" : other_is_maximized}, 4*int(other_is_maximized), int(other_is_maximized))) #soft expired regions is a strong indicator of problems: #(0 for none, up to max_soft_expired which is 5) factors.append(("soft-expired", {"count" : soft_expired}, soft_expired, int(bool(soft_expired)))) #now use those factors to drive the delay change: update_batch_delay(batch, factors)
def calculate_batch_delay(wid, window_dimensions, has_focus, other_is_fullscreen, other_is_maximized, is_OR, soft_expired, batch, global_statistics, statistics, bandwidth_limit): """ Calculates a new batch delay. We first gather some statistics, then use them to calculate a number of factors. which are then used to adjust the batch delay in 'update_batch_delay'. """ low_limit = get_low_limit(global_statistics.mmap_size>0, window_dimensions) #for each indicator: (description, factor, weight) factors = statistics.get_factors(bandwidth_limit) statistics.target_latency = statistics.get_target_client_latency(global_statistics.min_client_latency, global_statistics.avg_client_latency) factors += global_statistics.get_factors(low_limit) #damage pixels waiting in the packet queue: (extract data for our window id only) time_values = global_statistics.get_damage_pixels(wid) def mayaddfac(metric, info, factor, weight): if factor>=0.01 and weight>0.01: factors.append((metric, info, factor, weight)) mayaddfac(*queue_inspect("damage-packet-queue-pixels", time_values, div=low_limit, smoothing=sqrt)) #boost window that has focus and OR windows: mayaddfac("focus", {"has_focus" : has_focus}, int(not has_focus), int(has_focus)) mayaddfac("override-redirect", {"is_OR" : is_OR}, int(not is_OR), int(is_OR)) #soft expired regions is a strong indicator of problems: #(0 for none, up to max_soft_expired which is 5) mayaddfac("soft-expired", {"count" : soft_expired}, soft_expired, int(bool(soft_expired))) #now use those factors to drive the delay change: min_delay = 0 if batch.always: min_delay = batch.min_delay #if another window is fullscreen or maximized, #make sure we don't use a very low delay (cap at 25fps) if other_is_fullscreen or other_is_maximized: min_delay = max(40, min_delay) update_batch_delay(batch, factors, min_delay)
def get_factors(self, pixel_count): factors = [] def mayaddfac(metric, info, factor, weight): if weight>0.01: factors.append((metric, info, factor, weight)) if self.client_latency: #client latency: (we want to keep client latency as low as can be) metric = "client-latency" l = 0.005 + self.min_client_latency wm = logp(l / 0.020) mayaddfac(*calculate_for_target(metric, l, self.avg_client_latency, self.recent_client_latency, aim=0.8, slope=0.005, smoothing=sqrt, weight_multiplier=wm)) if self.client_ping_latency: metric = "client-ping-latency" l = 0.005 + self.min_client_ping_latency wm = logp(l / 0.050) mayaddfac(*calculate_for_target(metric, l, self.avg_client_ping_latency, self.recent_client_ping_latency, aim=0.95, slope=0.005, smoothing=sqrt, weight_multiplier=wm)) if self.server_ping_latency: metric = "server-ping-latency" l = 0.005 + self.min_server_ping_latency wm = logp(l / 0.050) mayaddfac(*calculate_for_target(metric, l, self.avg_server_ping_latency, self.recent_server_ping_latency, aim=0.95, slope=0.005, smoothing=sqrt, weight_multiplier=wm)) #packet queue size: (includes packets from all windows) mayaddfac(*queue_inspect("packet-queue-size", self.packet_qsizes, smoothing=sqrt)) #packet queue pixels (global): qpix_time_values = tuple((event_time, value) for event_time, _, value in tuple(self.damage_packet_qpixels)) mayaddfac(*queue_inspect("packet-queue-pixels", qpix_time_values, div=pixel_count, smoothing=sqrt)) #compression data queue: (This is an important metric #since each item will consume a fair amount of memory #and each will later on go through the other queues.) mayaddfac(*queue_inspect("compression-work-queue", self.compression_work_qsizes)) if self.mmap_size>0: #full: effective range is 0.0 to ~1.2 full = 1.0-self.mmap_free_size/self.mmap_size #aim for ~33% mayaddfac("mmap-area", "%s%% full" % int(100*full), logp(3*full), (3*full)**2) if self.congestion_value>0: mayaddfac("congestion", {}, 1+self.congestion_value, self.congestion_value*10) return factors