Domino Calendar REST API性能调优 之 代码篇

来源:互联网 发布:编程猫的网址 编辑:程序博客网 时间:2024/06/05 01:41

    去年发布Domino Calendar Service之前碰到一个读Invitations的性能瓶颈,经过一段时间的代码分析发现这是Domino底层实现的性能问题,于是将此BUG抛给了Domino底层同事,我们寻找了一个Workaround从而发布了Domino Calendar Service,今天看了一下这个BUG的记录,仍然是没有解决,可能底层的修改比较谨慎吧。

    性能问题描述

在30 s内读取500个用户的5000个Invitations(平均每个用户10个Invitations),平均每个请求的响应时间是875 ms;

在30 s内读取1000个用户的10000个Invitations(平均每个用户10个Invitations),平均每个请求的响应时间是5 s;

在30 s内读取2000个用户的20000个Invitations(平均每个用户10个Invitations),平均每个请求的响应时间是21 s;

    这响应时间是尼玛指数级的增长,这尼玛是妥妥的无法接受。

    性能问题分析

我们在REST API Service这一层面的代码时这样实现的:

            List<String> iCalendarList = null;            Vector<Object> list = calendar.getNewInvitations(dtStart, dtSince);            // Convert Vector<NotesCalendarNotice> to an array of iCalendar notices.                        if ( list != null && list.size() > 0 ) {                                // Convert the list of NotesCalendarNotice objects to a list of strings                                iCalendarList = new ArrayList<String>();                Iterator<Object> noticeIterator = list.iterator();                boolean matched = false;                StringBuffer noticeValue = new StringBuffer();                while (noticeIterator.hasNext()) {                    Object obj = noticeIterator.next();                    if ( obj instanceof NotesCalendarNotice) {                        matched = false;                        noticeValue.setLength(0);                        NotesCalendarNotice notice = (NotesCalendarNotice)obj;                        try {                            // The read is wrapped in it's own try block so one failure                            // doesn't sink the whole list                            <strong>noticeValue.append(notice.read());</strong>                            if(id == null){                                matched = true;                            }                            else{                                Pattern patternUID = Pattern.compile("(\n|\r)"+"UID:"+id+"(\n|\r)"); // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$                                Matcher matcher = patternUID.matcher(noticeValue);                                matched = matcher.find();                                                            }                            if( matched ){                                   iCalendarList.add(noticeValue.toString());                            }                        }                        catch (NotesException e) {                            // TODO:  Log a warning                        }                    }                }            }

代码的调用栈如下:

REST API GetNewInvitationsJava APIC&S API/api/calendar/invitations1. get a list of noticeNotesCalendar.getNewInvitations() CalGetNewInvitations()/api/calendar/invitations2 read content of each noticeNotesCalendarNotice.read()CalReadNotice()

读取Invitations需要两步,第一步是获得一个Invitations List (Vector<Object> list = calendar.getNewInvitations(dtStart, dtSince);),第二部是循环对List中的Entry进行read。 瞧瞧代码中黑体字中的大循环,循环不可怕,可怕的每个循环中的长时间操作(见第二个黑体 notice.read()),以指数级读取时间增长看起来应该是notice.read()的底层代码时间太长,我们进行了时间Log输出证实了我们的判断。

    性能问题解决

1,将BUG抛到底层开发同事,这个是根本解决办法,或者解决notice.read()读取时间问题,或者提供另外一种读取方法来提高效率(如缓存等)

2, 我们为Rest API用户提供两个workaround来提高读取多个Invitations的性能,具体见性能报告:http://blog.csdn.net/buptdavid/article/details/40315367

     2.1 使用REST API参数 receivedsince 和 since 进行分页读取

     2.2 实现客户端的缓存策略





0 0
原创粉丝点击