We help IT Professionals succeed at work.

improve performance and should be scalable

Javatechno
Javatechno asked
on
I have written a code snippet, this code will be access from thousands of object and get method look up also will be done from these objects. I need help in improving performance of this code and should be scalable so that if more then 10000 objects are accessing it it should not effect performance
import java.util.Set;
import java.util.HashSet;

/**
 * Implementation of the WidgetCatalog interface.  Please see the interface
 * for the specification.
 */
public class WidgetCatalogImpl implements WidgetCatalog
{

    // using JDK 1.5
    Set<Widget> set = new HashSet<Widget>();


    public void add(Widget widget) {
        set.add(widget);
    }

   /**
    * Return the widget for the specified version of the named widget.  If
    * the exact flag is true then this will only return a widget for an
    * exact name/version match.  If the exact flag is false then this will
    * return the version with a matching major version but the highest
    * available minor number.
    *
    * @param name    the name of the widget
    * @param major   the major version
    * @param minor   the minor version
    * @param exact   whether we need an exact match
    */    
    public Widget get(String name,int major,int minor,boolean exact) {
       Widget widgetToReturn = null;
       if(exact) {
           Widget w = new Widget(name, major, minor);

           // for loop using JDK 1.5 version
           for(Widget wid : set) {
                if((w.getName().equals(wid.getName())) && (wid.getVersion()).equals(w.getVersion())) {
                    widgetToReturn = w;
                    break;
                } 
           }
       } else {
           Widget w = new Widget(name, major, minor);
           WidgetVersion widgetVersion = new WidgetVersion(major, minor);

           // for loop using JDK 1.5 version
           for(Widget wid : set) {
               WidgetVersion wv = wid.getVersion();
               if((w.getName().equals(wid.getName())) && major == wv.getMajor() && WidgetVersion.isCompatibleAndNewer(wv, widgetVersion)) {
                    widgetToReturn = wid;
               } else if((w.getName().equals(wid.getName())) && wv.equals(widgetVersion.getMajor(), widgetVersion.getMinor())) {
                    widgetToReturn = w;
               }
           }
       }
       return widgetToReturn;
   }

   /**
    * Return the widget for the specified version of the named widget.
    * This will return the newest version of the widget that is compatible,
    * meaning the major version is the same but the minor version is equal to
    * or higher than the desired version.
    *
    * @param name    the name of the widget
    * @param major   the major version
    * @param minor   the minor version
    */
    public Widget getBest(String name,int major,int minor) {

       // THIS METHOD IS NOT GETTING USED ANY WHERE
        return null;
    }
    
}

Open in new window

Comment
Watch Question

Author

Commented:
Can we make performance better by using cache system, if yes, How?
Assuming you have more than ten widgets, instead of using a HashSet to store your widgets consider using a different data structure, such as a HashMap. Currently you are searching for widgets by brute-force, i.e. iterating over the set with average search times of n/2 (where the set contains n items).  With a HashMap, search times are of the order of 1. A huge improvement.

Also, have you considered the effects of concurrent access?  Would it be a problem if two or more clients added and requested the same widget type simultaneously? If so, then you must use a thread-safe data structure and synchronise method access.

Hope this helps.

Author

Commented:
there is no key, so hashmap can not be used :(
What about a joint key? Name and version, for instance?

Author

Commented:
i did not get you, can you give more details please?
Well, several ways of combining keys...

1. (Crude.) Use a concatenation  (name and version?) as your key.

2. (Better.) Create a map of sets. I.e. A map that maps a widget name to a set, where a set retrieved from the first map contains widgets with the same name  E.g.

    HashMap<String, Set<Widget>> map;

  This reduces the size of your brute-force search.

3. (Sophisticated.) Create a map of maps, or a map of lists. Where the inner maps use version number as a key or are sorted by version number!

 
Correction for point 3. above:

3. (Sophisticated.) Create a map of maps, or a map of lists. Where the inner maps use version number as a key or are the inner list is sorted by version number!

Author

Commented:
is it possible for you to give me implementation as well?
Okay, here are some suggestions for a Map of Lists...

Modify the internal set and add method as code below. Then, in your get method, each for loop can be rewritten from

  for(Widget wid : set) {
    // ...
  }

to

  for(Widget wid : map.get(name)) {
    // ...
  }

Now, the time-consuming brute-force search has been restricted to widgets with the correct name.
Map<String, List<Widget>> map = new HashMap<String, List<Widget>>();


  public void add(Widget widget) {
    if(map.containsKey(widget.getName())
      map.get(widget.getName()).add(widget);
    else {
      List<Widget> newList = new Vector<Widget>(widget);
      map.add(newList);
    }
  }

Open in new window

Author

Commented:
thanks for help