فهرست منبع

AMBARI-3748 [perf] Optimize processing of response in hosts mapper. (atkach)

atkach 11 سال پیش
والد
کامیت
45f1a86dec
3فایلهای تغییر یافته به همراه87 افزوده شده و 22 حذف شده
  1. 80 21
      ambari-web/app/mappers/hosts_mapper.js
  2. 4 1
      ambari-web/app/mappers/server_data_mapper.js
  3. 3 0
      ambari-web/app/mappers/status_mapper.js

+ 80 - 21
ambari-web/app/mappers/hosts_mapper.js

@@ -17,6 +17,13 @@
 
 var App = require('app');
 
+var stringUtils = require('utils/string_utils');
+/**
+ * previousResponse contains only mutable properties of host
+ * unlike App.cache.Hosts, which contains immutable properties
+ */
+var previousResponse = {};
+
 App.hostsMapper = App.QuickDataMapper.create({
 
   model: App.Host,
@@ -52,13 +59,16 @@ App.hostsMapper = App.QuickDataMapper.create({
   map: function (json) {
     console.time('App.hostsMapper execution time');
     if (json.items) {
-      var result = [];
+      var hostsWithFullInfo = [];
+      var modifiedHosts = [];
       var hostIds = {};
       var cacheData = App.cache['Hosts'];
       var currentHostStatuses = {};
+      var hostsData = {};
+      var isModelLoaded = false;
 
       json.items.forEach(function (item) {
-        //receive host_components when added hosts
+        //receive host_components when hosts were added
         item.host_components = item.host_components || [];
         item.host_components.forEach(function (host_component) {
           host_component.id = host_component.HostRoles.component_name + "_" + host_component.HostRoles.host_name;
@@ -66,18 +76,31 @@ App.hostsMapper = App.QuickDataMapper.create({
 
         hostIds[item.Hosts.host_name] = true;
         currentHostStatuses[item.Hosts.host_name] = item.Hosts.host_status;
-        result.push(this.parseIt(item, this.config));
+
+        var parsedItem = this.parseIt(item, this.config);
+        var hostCache = cacheData[item.Hosts.host_name];
+
+        hostsWithFullInfo.push(parsedItem);
+        if (hostCache) {
+          if (hostCache.is_modified) {
+            modifiedHosts.push(parsedItem);
+            delete hostCache.is_modified;
+          } else {
+            hostsData[item.Hosts.host_name] = this.getDiscrepancies(parsedItem, previousResponse[item.Hosts.host_name]);
+          }
+        }
+        previousResponse[item.Hosts.host_name] = parsedItem;
       }, this);
 
       App.cache['previousHostStatuses'] = currentHostStatuses;
-      result = this.sortByPublicHostName(result);
+      hostsWithFullInfo = this.sortByPublicHostName(hostsWithFullInfo);
 
       var clientHosts = App.Host.find();
 
       if (clientHosts) {
         // hosts were added
-        if (clientHosts.get('length') < result.length) {
-          result.forEach(function (host) {
+        if (clientHosts.get('length') < hostsWithFullInfo.length) {
+          hostsWithFullInfo.forEach(function (host) {
             cacheData[host.id] = {
               ip: host.ip,
               os_arch: host.os_arch,
@@ -88,37 +111,73 @@ App.hostsMapper = App.QuickDataMapper.create({
               host_components: host.host_components
             };
           });
+          App.store.loadMany(this.get('model'), hostsWithFullInfo);
+          isModelLoaded = true;
+        } else {
+          //restore properties from cache instead of asking them from server
+          modifiedHosts.forEach(function (host) {
+            var cacheHost = cacheData[host.id];
+            if (cacheHost) {
+              host.ip = cacheHost.ip;
+              host.os_arch = cacheHost.os_arch;
+              host.os_type = cacheHost.os_type;
+              host.public_host_name = cacheHost.public_host_name;
+              host.memory = cacheHost.memory;
+              host.cpu = cacheHost.cpu;
+              host.host_components = cacheHost.host_components;
+            }
+          });
+          App.store.loadMany(this.get('model'), modifiedHosts);
         }
         // hosts were deleted
-        if (clientHosts.get('length') > result.length) {
+        if (clientHosts.get('length') > hostsWithFullInfo.length) {
           clientHosts.forEach(function (host) {
             if (host && !hostIds[host.get('hostName')]) {
               // Delete old ones as new ones will be
               // loaded by loadMany().
               host.deleteRecord();
+              App.store.commit();
               host.get('stateManager').transitionTo('loading');
               delete cacheData[host.get('id')];
             }
           });
         }
       }
-      //restore properties from cache instead request them from server
-      result.forEach(function (host) {
-        var cacheHost = cacheData[host.id];
-        if (cacheHost) {
-          host.ip = cacheHost.ip;
-          host.os_arch = cacheHost.os_arch;
-          host.os_type = cacheHost.os_type;
-          host.public_host_name = cacheHost.public_host_name;
-          host.memory = cacheHost.memory;
-          host.cpu = cacheHost.cpu;
-          host.host_components = cacheHost.host_components;
-        }
-      });
-      App.store.loadMany(this.get('model'), result);
+      if (!isModelLoaded) {
+        App.Host.find().forEach(function (_host) {
+          var hostData = hostsData[_host.get('id')];
+          if (hostData) {
+            for (var i in hostData) {
+              _host.set(stringUtils.underScoreToCamelCase(i), hostData[i]);
+            }
+          }
+        });
+      }
     }
     console.timeEnd('App.hostsMapper execution time');
   },
+  /**
+   * check mutable fields whether they have been changed and if positive
+   * return host object only with properties, that contains new value
+   * @param current
+   * @param previous
+   * @return {*}
+   */
+  getDiscrepancies: function (current, previous) {
+    var result = {};
+    var fields = ['disk_total', 'disk_free', 'health_status', 'load_one', 'cpu_system', 'cpu_user', 'mem_total', 'mem_free'];
+    if (previous) {
+      fields.forEach(function (field) {
+        if (current[field] != previous[field]) result[field] = current[field];
+      });
+      if (JSON.stringify(current.disk_info) !== JSON.stringify(previous.disk_info)) {
+        result.disk_info = current.disk_info;
+      }
+      result.last_heart_beat_time = current.last_heart_beat_time;
+      return result;
+    }
+    return current;
+  },
 
   /**
    * Default data sorting by public_host_name field

+ 4 - 1
ambari-web/app/mappers/server_data_mapper.js

@@ -18,7 +18,10 @@
 
 var App = require('app');
 
-//initialize common cache container for mappers
+/**
+ * initialize common cache container for mappers
+ * App.cache contains shared data, used for syncronizing incoming server data among mappers
+ */
 App.cache = {
   'Hosts': {},
   'previousHostStatuses': {},

+ 3 - 0
ambari-web/app/mappers/status_mapper.js

@@ -97,6 +97,8 @@ App.statusMapper = App.QuickDataMapper.create({
               host_id: host.Hosts.host_name,
               service_id: service
             });
+            //update host-components only on adding due to Ember Data features
+            if (hostsCache[host.Hosts.host_name]) hostsCache[host.Hosts.host_name].is_modified = true;
           }
           currentComponentStatuses[host_component.id] = host_component.HostRoles.state;
 
@@ -142,6 +144,7 @@ App.statusMapper = App.QuickDataMapper.create({
             }
           } else {
             hostComponent.deleteRecord();
+            App.store.commit();
             hostComponent.get('stateManager').transitionTo('loading');
           }
         }