Do you have some profiler metrics or benchmarks to support the concern? Even completely unoptimized, I'd be surprised if this presented any sort of performance challenge on a modern VM.
While the MapperMethod may look slow when you read the code, realize that most of the for loops will execute either 0 or 1 times. Or maybe a couple of times for methods that have multiple parameters or the odd one that has multiple annotations. Even then, it's 1 - 4 times against fairly quick code. The biggest performance impact is probably some of the string conversion and concatenation, which could probably be optimized. More important than the micro-optimizations though, is that MapperMethod is only ever called on the outermost call from the consumer of a Mapper interface. So it's a very high level call... just enough to marshal it down to a sqlSession.[select,insert,update,delete] call. Even at 40 TPS (a good benchmark for 1,000,000 concurrent requests in an 8 hour period) you're looking at literally 40 * 4 operations per second at most. I wouldn't be overly concerned with those calls. Even the potential creation and destruction of maybe a few hundred string objects under that amount of load, is nothing more than light exercise for the garbage collector. I think there may be room for improvement, but not enough to warrant introducing state into a stateless design. If you have some interesting profiler metrics that show a potential bottleneck, I'd be very interested in seeing it. Cheers, Clinton On Fri, Jan 1, 2010 at 9:17 AM, Eduardo Macarron <eduardo.macar...@gmail.com > wrote: > Yes Clinton, is just for performance. > > > 2010/1/1 Clinton Begin <clinton.be...@gmail.com> > > What problem are you trying to solve, or goal you're trying to achieve by >> doing this? Is it strictly a performance consideration? >> >> Clinton >> >> >> >> On Fri, Jan 1, 2010 at 7:31 AM, Eduardo Macarron < >> eduardo.macar...@gmail.com> wrote: >> >>> Fist of all happy new year! >>> >>> Some work has been doing on Spring 3 and Ibatis 3 integration. >>> >>> Having a look at mappers internals we saw that a new MapperMethod is >>> created (with some introspection work) on each call to a mapper method. I >>> wonder if it would be better to build them all during startup or maybe cache >>> them somehow. >>> >>> this is the Jira issue (http://jira.springframework.org/browse/SPR-5991) >>> Grabriel Axel posted it here some months ago (he opened the issue) >>> >>> The main problem with this task is that MapperMethods are not thread safe >>> and that they hold an SqlSession. Enabling cache would require to make some >>> changes to MapperMethods. SqlSession should be passed as an argument to >>> execute instead to its constructor. >>> >>> public MapperMethod(Method method, Configuration configuration) { >>> paramNames = new ArrayList<String>(); >>> paramPositions = new ArrayList<Integer>(); >>> ... >>> >>> public Object execute(Object[] args, SqlSession sqlSession) { >>> Object result; >>> if (SqlCommandType.INSERT == type) { >>> ... >>> >>> And MapperProxy >>> >>> public Object invoke(Object proxy, Method method, Object[] args) throws >>> Throwable { >>> return new MapperMethod(method, >>> sqlSession.getConfiguration()).execute(args, sqlSession); >>> } >>> >>> >>> So for example Spring could have this code to use directly injected >>> Mappers where SqlSession is got from spring's transaction context. >>> >>> private Map<Method, MapperMethod> mapperMethods = new >>> ConcurrentHashMap<Method, MapperMethod>(); >>> >>> public <T> T getMapper(final Class<T> type) { >>> // mimic iBATIS MapperProxy >>> return (T) >>> java.lang.reflect.Proxy.newProxyInstance(type.getClassLoader(), new Class[] >>> { type }, >>> new InvocationHandler() { >>> @Override >>> public Object invoke(final Object proxy, final Method >>> method, final Object[] args) throws Throwable { >>> return execute(new SqlSessionCallback<T>() { >>> @Override >>> public T doInSqlSession(SqlSession sqlSession) >>> throws SQLException { >>> // mimic iBATIS MapperProxy >>> Class<?> type = method.getDeclaringClass(); >>> if >>> (!sqlSession.getConfiguration().hasMapper(type)) { >>> throw new BindingException("Type " + type >>> + " is not known to the MapperRegistry."); >>> } >>> >>> MapperMethod mm = mapperMethods.get(method); >>> if (mm == null) { >>> mm = new MapperMethod(method, >>> sqlSession.getConfiguration()); >>> mapperMethods.put(method, mm); >>> } else { >>> logger.debug("Returning a cached >>> mapper method"); >>> } >>> >>> return (T) mm.execute(args, sqlSession); >>> } >>> }); >>> } >>> }); >>> } >>> >>> Or maybe avoid using directly MapperMethods and access to them thought >>> the "standard" api SqlSession.getConfiguration().getMapper(impl, sesion) but >>> in that case caching should be done inside. >>> >>> what do you think about this? >>> >>> >>> >> >