U E D R , A S I H C RSS

Java/Mode Selection Performance Test

Servlet —„œ, ๋˜๋Š” Switch - Case ๋“ ๋งŽ€ ๋ถ„๊ธฐ๋ฅผ •˜๋Š” ๋ฐฉ๋ฒ•— ๋Œ€•œ ๋””žธ & ผฌ๋จผŠค ๊ด€ —„œ˜ ๊ตฌ๊ฒฝ.

1. if-else

๋Œ€๊ฐ• ๋‹คŒ˜ ฝ”๋“œ Šคƒ€ผผ๊ฒƒด๋‹ค.
~cpp 
public class IfElse {
    public void printPerformance(String[] modeExecute) {
        long start;
        long end;
        start = System.currentTimeMillis();
        for (int i = 0; i < ModeChoicePerformanceTest.LOOPING_COUNT; i++) {
            executeIfElse(modeExecute);
        }
        end = System.currentTimeMillis();
        System.out.println("if - else elapsed time :" + (end - start) + "ms ");
    }

    private void executeIfElse(String[] modeExecute) {
        for (int i = 0; i < modeExecute.length; i++) {
            executeWithIfElse(modeExecute[i]);
        }
    }

    public void executeWithIfElse(String mode) {
        if (mode.equals("One")) {
            doOne(1);
        } else if (mode.equals("Two")) {
            doTwo(1);
        } else if (mode.equals("Three")) {
            doThree(1);
        } else if (mode.equals("Four")) {
            doFour(1);
        } else if (mode.equals("Five")) {
            doFive(1);
        } else {
            doDefault(1);
        }
    }


    public void doOne(int i) {
        i = 10;
    }

    public void doTwo(int i) {
        i = 10;
    }

    public void doThree(int i) {
        i = 10;
    }

    public void doFour(int i) {
        i = 10;
    }

    public void doFive(int i) {
        i = 10;
    }

    public void doDefault(int i) {
        i = 100;
    }
}
ด ๋ฐฉ๋ฒ•€ ผ๋‹จ †๋„ƒœผ๋ก  ๊ฐ€žฅ ๋น ๋ฅด๋‹ค. •˜ง€๋งŒ, •œŽธœผ๋กœ
Seminar:WhySwitchStatementsAreBadSmell— ๊ธ๋ฆฌง€ •Š„๊นŒ? ๊ทผ๋ฐ.. ๊ทธ— ๋Œ€•œ ๋ฐ˜๋ก œผ๋กœ ๋“ค–ด˜ค๋Š”๊ฒƒด 'ด๊ด mode ๋ถ„๊ธฐด๋ฏ€๋กœ •ž—„œ˜ Switch-Statement —„œ˜ ˜ˆ™€๋Š” ๋‹ค๋ฅธ ƒ™ฉ •„๋‹ˆ๋ƒ. –ดฐจ”ผ ๋ถ„๊ธฐ ด›„—” ๊ทธ๋ƒฅ •ด๋‹น ๋ถ€๋ถ„ด ‹ค–‰๋˜๊ณ  ๋ด๋‹ค.' ๋ผ๊ณ  ๋ง• ๊ฒƒด๋‹ค. ๊ธ€Œ”. ๋ชจ๋ฅด๊ฒ ๋‹ค.
•œŽธœผ๋กœ ๋А๊ปดง€๋Š” ๊ฒƒœผ๋กœ๋Š”, switch ๋กœ ๋ถ„๊ธฐ๋ฅผ ๋‚˜๋ˆŒ mode string ๊ณผ ›น parameter ™€˜ ค‘๋ณตด žˆ„ ๊ฒƒด๋ผ๋Š”  ด ๋ณดธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  •˜๋‚˜˜ mode ๊ฐ€ ๋Š˜–ด๋‚ ๋•Œ๋งˆ๋‹ค •ด๋‹น method ๊ฐ€ ๋Š˜–ด๋‚˜๊ณ , mode string ด ๋Š˜–ด๋‚˜๊ณ , if-else ๊ตฌ๋ฌธด ฃผš ๊ธธ–ด„๋‹ค๋Š”  ด žˆ๋‹ค. ง€๊ธˆ€ ๋ฉ”†Œ๋“œ๋กœ ถ”ถœ„ •ด๋†“€ ƒ™ฉดง€๋งŒ, ๋งŒผ  € ๋ถ€๋ถ„ด ๋ฉ”†Œ๋“œ๋กœ ถ”ถœด •ˆ๋˜–ดžˆ๋‹ค๋ฉด? ๊ทธ๊ด ๋‹จ •œ๋งˆ๋”” ๋ฐ–— • ๋งด —†๋‹ค. (๋‹จ,  € ๋…ผ๋ฌธ„ •„๋Š” ‚ฌ๋žŒ— •œ•ด„œ) GotoStatementConsideredHarmful.

๋‘๋ฒˆงธ - Method reflection

~cpp 

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class MethodFullReflection {
    public void printPerformance(String[] modeExecute) throws InvocationTargetException, IllegalAccessException {
        long start;
        long end;
        start = System.currentTimeMillis();
        for (int i = 0; i < ModeChoicePerformanceTest.LOOPING_COUNT; i++) {
            executeReflection(modeExecute);
        }
        end = System.currentTimeMillis();
        System.out.println("elapsed time :" + (end - start) + "ms ");

    }

    private void executeReflection(String[] modeExecute) throws InvocationTargetException, IllegalAccessException {
        for (int i = 0; i < modeExecute.length; i++) {
            Method method = null;
            try {
                method = this.getClass().getMethod("do" + modeExecute[i], new Class[]{int.class});
                method.invoke(this, new Object[]{new Integer(1)});
            } catch (NoSuchMethodException e) {
                this.doDefault(1);
            } catch (SecurityException e) {
                e.printStackTrace();  //To change body of catch statement use Options | File Templates.
            }
        }
    }

    private void doDefault(int i) {
        i = 100;
    }

    public void doOne(int i) {
        i = 10;
    }

    public void doTwo(int i) {
        i = 10;
    }

    public void doThree(int i) {
        i = 10;
    }

    public void doFour(int i) {
        i = 10;
    }

    public void doFive(int i) {
        i = 10;
    }

}
žฅ  : MODE ๊ฐ€ ถ”๊ฐ€๋ ๋•Œ๋งˆ๋‹ค doXXX ‹œผ๋กœ ด๋ฆ„„  ••ดฃผ๊ณ  ด๋ฅผ ‹ค–‰•˜๋ฉด ๋œ๋‹ค. กฐ๊ด ๋ถ„๊ธฐ ๋ถ€๋ถ„˜ ฝ”๋“œ๊ฐ€ ฆ๊ฐ€๋˜ง€ •Š๊ณ , •ด๋‹น Mode ๊ฐ€ ถ”๊ฐ€๋ ๋•Œ๋งˆ๋‹ค ๋ฉ”†Œ๋“œ •˜๋‚˜๋งŒ ถ”๊ฐ€•ดฃผ๋ฉด ๋œ๋‹ค.
๋‹จ  : ž๋ฐ”—„œ๋Š” Method Reflection & Invoke ๊ฐ€ —„ฒญ ๋А๋ฆฌ๋‹ค.; †๋„๋Š” ๋ฐ‘˜๊บผ ฐธกฐ.

„ธ๋ฒˆงธ. œ„˜ ๋ฐฉ๋ฒ•„ ๋ณด™„•œ ๋ฐฉ๋ฒ•ด๋‹ค. ๋ฐ”๋กœ ผข…˜ Table Lookup.

~cpp 

import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

/**
 * User: Administrator Date: 2003. 7. 12. Time: ˜ค „ 12:48:38
 */
public class MethodTableLookupReflection {
    public void printPerformance(String[] modeExecute) throws InvocationTargetException, IllegalAccessException {
        long start;
        long end;
        start = System.currentTimeMillis();
        initReflectionMap(modeExecute);
        end = System.currentTimeMillis();
        System.out.println("reflection with method initialize table elapsed time :" + (end - start) + "ms ");

        start = System.currentTimeMillis();
        for (int i = 0; i < ModeChoicePerformanceTest.LOOPING_COUNT; i++) {
            executeReflectionWithMapping(modeExecute);
        }
        end = System.currentTimeMillis();
        System.out.println("reflection with method elapsed time :" + (end - start) + "ms ");

    }

    private static Map methodMap;


    private void executeReflectionWithMapping(String[] modeExecute) throws InvocationTargetException, IllegalAccessException {
        for (int i = 0; i < modeExecute.length; i++) {
            Method method = (Method) methodMap.get(modeExecute[i]);
            if (method != null)
                method.invoke(this, new Object[]{new Integer(1)});
            else
                doDefault(1);
        }
    }

    private void initReflectionMap(String[] methodNames) {
        methodMap = new HashMap();
        for (int i = 0; i < methodNames.length; i++) {
            try {
                methodMap.put(methodNames[i], this.getClass().getMethod("do" + methodNames[i], new Class[]{int.class}));
            } catch (NoSuchMethodException e) {
            } catch (SecurityException e) {
            }
        }

    }

    private void doDefault(int i) {
        i = 100;
    }

    public void doOne(int i) {
        i = 10;
    }

    public void doTwo(int i) {
        i = 10;
    }

    public void doThree(int i) {
        i = 10;
    }

    public void doFour(int i) {
        i = 10;
    }

    public void doFive(int i) {
        i = 10;
    }
}
ด ๋ฐฉ๋ฒ•€ œ„˜ ๋ฐฉ๋ฒ•๊ณผ ๊ฐ™€ žฅ „ ง€๋‹ˆ๋ฉด„œ ผฌ๋จผŠค๋ฅผ ๊˜ 10๋ฐฐ๊ฐ€๋Ÿ‰ –ฅƒ‹œ‚จ๋‹ค.

„ค๋ฒˆงธ. Inner Class — ๋Œ€•ด Command Pattern ˜ ‚ฌšฉ.

~cpp 

import java.util.Map;
import java.util.HashMap;

/**
 * User: Administrator Date: 2003. 7. 12. Time: ˜ค „ 12:57:7
 */
public class InterfaceTableLookup {
    protected Map modeMap = new HashMap();

    public void printPerformance(String[] modeExecute) {
        long start;
        long end;
        start = System.currentTimeMillis();
        initModeMap();
        end = System.currentTimeMillis();
        System.out.println("interface table lookup init table elapsed time :" + (end - start) + "ms ");

        start = System.currentTimeMillis();
        for (int i = 0; i < ModeChoicePerformanceTest.LOOPING_COUNT; i++) {
            executeInnerclassMapping(modeExecute);
        }
        end = System.currentTimeMillis();
        System.out.println("interface table lookup elapsed time :" + (end - start) + "ms ");


    }

    private void executeInnerclassMapping(String[] modeExecute) {
        for (int i = 0; i < modeExecute.length; i++) {
            executeMode(modeExecute[i]);
         }
    }

    private void executeMode(String s) {
        IMode mode = (IMode) modeMap.get(s);
        if (mode == null) doDefault(1);
        else mode.execute(1);
    }

    public class ExOne implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public  class ExTwo implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public class ExThree implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public class ExFour implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public class ExFive implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    private void initModeMap() {
        modeMap.put("One", new ExOne());
        modeMap.put("Two", new ExTwo());
        modeMap.put("Three", new ExThree());
        modeMap.put("Four", new ExFour());
        modeMap.put("Five", new ExFive());
    }
}
ด ๋ฐฉ๋ฒ•€ initModeMap —„œ ๋งค๋ฒˆ Mode— ๋Œ€•œ ๋“๋ก„ •ดค˜•ผ •œ๋‹ค. ผฌ๋จผŠค๋Š” Method Reflection ๋ณด๋‹ค ›”ฌ ๋น ๋ฅด๋‹ค.

๋งˆง€๋ง‰ ๋ฐฉ๋ฒ• - interface & reflection

œ„˜ ๋ฐฉ๋ฒ•— initModeMap „ reflection œผ๋กœ ฒ˜๋ฆฌ•œ ๊ฒƒด๋‹ค.
~cpp 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * User: Administrator Date: 2003. 7. 12. Time: ˜ค „ 1:2:16
 */
public class InterfaceTableLookupReflection {
    public void printPerformance(String[] modeExecute) throws NoSuchMethodException, InstantiationException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
        long start;
        long end;
        start = System.currentTimeMillis();
        initModeMapWithReflection(modeExecute);
        end = System.currentTimeMillis();
        System.out.println("interface reflection & table lookup init able elapsed time :" + (end - start) + "ms ");

        start = System.currentTimeMillis();
        for (int i = 0; i < ModeChoicePerformanceTest.LOOPING_COUNT; i++) {
            executeInnerclassMapping(modeExecute);
        }
        end = System.currentTimeMillis();
        System.out.println("interface reflection & table lookup elapsed time :" + (end - start) + "ms ");

    }

    private void executeInnerclassMapping(String[] modeExecute) {
        for (int i = 0; i < modeExecute.length; i++) {
            executeMode(modeExecute[i]);
         }
    }

    private void executeMode(String s) {
        IMode mode = (IMode) modeMap.get(s);
        if (mode == null) doDefault(1);
        else mode.execute(1);
    }

    protected Map modeMap = new HashMap();
    public final static String modeClassHeader = "Ex";
    String expectedClassNameHeader = this.getClass().getName() + "$" + modeClassHeader;

    private void initModeMapWithReflection(String[] modeExecute) throws InstantiationException, InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Class[] consParamClasses = new Class[]{this.getClass()};
        Object[] consParams = new Object[]{this};


        Class[] inners = this.getClass().getClasses();
        for (int i=0;i<inners.length;i++) {
            if (inners[i].getName().startsWith(expectedClassNameHeader)) {
                Constructor innerCons = inners[i].getDeclaredConstructor(consParamClasses);
                modeMap.put(modeExecute[i], innerCons.newInstance(consParams));
            }
        }
    }

    public void doDefault(int i) {
        i = 100;
    }

    public class ExOne implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public  class ExTwo implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public class ExThree implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public class ExFour implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }

    public class ExFive implements IMode {
        public void execute(int i) {
            i = 10;
        }
    }
}
ด ๋ฐฉ๋ฒ•€ Mode ถ”๊ฐ€‹œ ๊ทธ๋ƒฅ ExModeName ‹œผ๋กœ ถ”๊ฐ€•ดฃผ๋ฉด ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด„œ Mode กฐ๊ด ๋ถ„๊ธฐ ๋ถ€๋ถ„ด ๋ณ€•˜ง€ •Š๋Š”๋‹ค. Reflectionœผ๋กœ table lookup „šฐ๋Š” ๋ถ€๋ถ„ด๋‚˜ Mode กฐ๊ด ๋ถ„๊ธฐ ๋ถ€๋ถ„„ •„— ƒœ„ ด๋ž˜Šค๋กœ ถ”ถœ•  ˆ˜ žˆ๋‹ค. ผฌ๋จผŠค๋ฉด—„œ๋Š” ˜™ธ๋กœ •ž—„œ ˆ˜๋™œผ๋กœ map „ „šฐ๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ™๋‹ค. œ —ฐ„๊ณผ ผฌ๋จผŠค ๋‘๊ฐ€ง€๊ฐ€   ˆžˆ –ดšธ–ดง€๋Š” ๋ฐฉ๋ฒ•ด๋‹ค.


ด๊œ„˜ …ŒŠคŠธ๋“ค„ •œ๋ฒˆ— ‹ค–‰‹œ‚ค๊ธฐ œ„•œ runner class.
~cpp 
import java.lang.reflect.InvocationTargetException;

/*
  ‰๊ฐ€•˜๋ ค๋Š” กฐ๊ด๋“ค :
  1. •ด๋‹น method ˜ naming œผ๋กœ reflection call.
  2. switch - case ๋กœ mode ๊ตฌ๋ถ„.
  3. interface & class - command pattern ˜ ๊ตฌ˜„.

  ‰๊ฐ€š”†Œ๋“ค
  1. •ด๋‹น ฝ”๋“œ ž‘„๋Œ€๋น„ ๋Š˜–ด๋‚˜๋Š” ๋ฐ˜๋ณต ž‘—…๋“ค
  2. performance
  3. maintance
*/
public class ModeChoicePerformanceTest {
    public static final int LOOPING_COUNT = 1000000;

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, InstantiationException {
        String[] modeExecute = new String[]{"One", "Two", "Three", "Four", "Five", "hugu"};

        new IfElse().printPerformance(modeExecute);
        new MethodFullReflection().printPerformance(modeExecute);
        new MethodTableLookupReflection().printPerformance(modeExecute);
        new InterfaceTableLookup().printPerformance(modeExecute);
        new InterfaceTableLookupReflection().printPerformance(modeExecute);
    }
}

๊ฒฐ๊ณผ

~cpp 
if - else elapsed time :611ms 
elapsed time :61889ms 
reflection with method initialize table elapsed time :0ms 
reflection with method elapsed time :6459ms 
interface table lookup init table elapsed time :10ms 
interface table lookup elapsed time :741ms 
interface reflection & table lookup init able elapsed time :10ms 
interface reflection & table lookup elapsed time :731ms 
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:33
Processing time 0.0168 sec