Uploaded image for project: 'Kylin'
  1. Kylin
  2. KYLIN-5216 Upgrade metadata and engine : Kylin 5.0
  3. KYLIN-5229

PropertiesDelegate introduce lock to KylinConfig

    XMLWordPrintableJSON

Details

    • Sub-task
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • None
    • 5.0-alpha
    • Metadata
    • None

    Description

      Background

      Kyligence team plans to add new feature which supports reading config entry from external Config Server(such as Nacos) other than local kylin.properties. So we add PropertiesDelegate and IExternalConfigLoader to support this request.

      Issue

      PropertiesDelegate introduces performance downgrade because it add lock to KylinConfigBase#getOptional, impact query concurrency badly, from Yanghong Team's load testing result, query concurrency change from 60 to 3.

      Root Cause

       

      //// KylinConfigBase
      
      protected String getOptional(String prop, String dft) {
          final String property = System.getProperty(prop);
          return property != null ? getSubstitutor().replace(property)
                  : getSubstitutor().replace(properties.getProperty(prop, dft)); // Step 1
      }
       
      protected StrSubstitutor getSubstitutor() {
          // overrides > env > properties
          final Map<String, Object> all = Maps.newHashMap();
          all.putAll((Map) properties); // Step 2
          all.putAll(STATIC_SYSTEM_ENV);
          all.putAll(overrides);
          return new StrSubstitutor(all);
      }
      
      
      //// PropertiesDelegate
      
      @Override
      public Set<Map.Entry<Object, Object>> entrySet() {
          return getAllProperties().entrySet(); // Step 3
      }
      
      
      
      private synchronized Properties getAllProperties() { // Step 4, synchronized     
          Properties propertiesView = new Properties();
          if (this.configLoader != null) {
              propertiesView.putAll(this.configLoader.getProperties()); // Step 5
          }
          propertiesView.putAll(this.properties);
          return propertiesView;
      } 
      
      
      //// Hashtable
      
      public synchronized void putAll(Map<? extends K, ? extends V> t) {
          for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
              put(e.getKey(), e.getValue()); // Step 7
      }
      
      
      public synchronized V put(K key, V value) { // Step 8
          // Make sure the value is not null
          if (value == null) {
              throw new NullPointerException();
          }
      
          // Makes sure the key is not already in the hashtable.
          Entry<?,?> tab[] = table;
          int hash = key.hashCode();
          int index = (hash & 0x7FFFFFFF) % tab.length;
          @SuppressWarnings("unchecked")
          Entry<K,V> entry = (Entry<K,V>)tab[index];
          for(; entry != null ; entry = entry.next) {
              if ((entry.hash == hash) && entry.key.equals(key)) {
                  V old = entry.value;
                  entry.value = value;
                  return old;
              }
          }
      
          addEntry(hash, key, value, index);
          return null;
      }
      
      

       

      Screenshots

      Java Stack of Query Thread:

       

      Attachments

        1. image-2022-08-17-13-17-40-751.png
          154 kB
          Xiaoxiang Yu

        Activity

          People

            mukvin mukvin
            xxyu Xiaoxiang Yu
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: