简体   繁体   English

Java Collection以获得最佳性能

[英]Java Collection for Optimal performance

I have below snippet of code which gets all the available menu items for a zone(top or left)and adds the widgets for which user has access to an ArrayList collection. 我有下面的代码片段,它获取区域(顶部或左侧)的所有可用菜单项,并添加用户可以访问ArrayList集合的小部件。 For now the getWidgetsByZone(zone) returns 64 items and iterates over them. 现在,getWidgetsByZone(zone)返回64个项目并对它们进行迭代。 Am seeing some performance lag in this method(in a tool called GlowRoot which logs the time trace for each user action) I dont know why. 我看到这种方法有一些性能滞后(在一个名为GlowRoot的工具中记录每个用户操作的时间轨迹)我不知道为什么。 Am trying to improve the performance by switching to other optimal collection. 我试图通过切换到其他最佳收集来提高性能。 Can someone help me to choose the optimal collection for my scenario? 有人可以帮助我为我的场景选择最佳集合吗?

AM using JDK 7, Hibernate 3.6 and Spring 3.1 AM使用JDK 7,Hibernate 3.6和Spring 3.1

Here is DashboardService.getMenuItems() implementation 这是DashboardService.getMenuItems()实现

public List<IContentWidget> getMenuItems(String zone) {
        List<IContentWidget> widgets = new ArrayList<IContentWidget>();
        if (zone != null) {

            List<IPersistentEntityInstance> instances = getWidgetsByZone(zone);

            for (IPersistentEntityInstance instance : instances) {
                IContentWidget contentWidget = (IContentWidget) instance;
                if (contentWidget.getZones() == null) continue;

                // block widgets that should only show up in mobile / responsive ui
                if (contentWidget.getZones().contains(RESPONSIVE_VISIBLE)) continue;

                // Add widget only if the current user has read permission on the entity.
                if (contentWidget.getTargetItemScreen() != null || contentWidget.getTargetListScreen() != null) {
                    if (isAccessible(contentWidget)) {
                        widgets.add(contentWidget);
                    }
                }
                else {
                    widgets.add(contentWidget);
                }
            }
        }
        Collections.sort(widgets, new Comparator<IContentWidget>() {

            public int compare(IContentWidget o1, IContentWidget o2) {
                int i = o1.getOrderNum() - o2.getOrderNum();
                return i == 0 ? 0 : i < 0 ? -1 : 1;
            }

        });
        return widgets;
    }

Implementation of DashboardService.isAccesible() DashboardService.isAccesible()的实现

private boolean isAccessible(IContentWidget contentWidget) {
    boolean isWidgetAccessible = false;
    String permission = contentWidget.getDisplayPermission();
    if (permission != null) {
        isWidgetAccessible = authorizationService.userHasPermission(SecurityHelper.getAuthenticatedUser(),
                permission);
    }
    else {
        IBaseScreen screen = contentWidget.getTargetItemScreen() == null ? contentWidget.getTargetListScreen()
                : contentWidget.getTargetItemScreen();
        // return true when target screen is 'null', this means that target link cannot be secured because it is not
        // associated with any entity
        if (screen == null) {
            isWidgetAccessible = true;
        }
        else {
            IAccessEntry access = authorizationService.getAccessForEntityMetadata(screen.getEntityMetadata());

            // fetching metadata from entityMetadataService again to trigger population of facade
            if (screen instanceof IListScreen && access.getIsReadable()) {
                isWidgetAccessible = true;
            }
            else if (screen instanceof IItemScreen && access.getIsCreatable()) {
                isWidgetAccessible = true;
            }
        }
    }
    return isWidgetAccessible;
}

Implementation of getWidgetsByZone method 实现getWidgetsByZone方法

public List<IPersistentEntityInstance> getWidgetsByZone(String zone) {
    IEntityMetadata entity =  entityService.findEntityMetadataByName(ContentWidget.class.getSimpleName());
return entityService.runNamedQuery(entity, NamedQueryList.WIDGETS_BY_ZONE, new Object[] { zone });
    }

Here is my ContentWidget Entity 这是我的ContentWidget实体

@LocalOnly
@Entity
@EntityMetadataDefaults(editable = false)
@Audited
@NamedQueries({
    @NamedQuery(name = NamedQueryList.DASHBOARD_WIDGETS, query = "from ContentWidget where zones like '%dashboard%' and dashboardContexts.size = 0 order by orderNum", hints = {
            @QueryHint(name = "org.hibernate.cacheable", value = "true"),
            @QueryHint(name = "org.hibernate.cacheRegion", value = "Metadata") }),
    @NamedQuery(name = NamedQueryList.WIDGETS_BY_ZONE, query = "from ContentWidget where zones like '%' || ? || '%' order by orderNum", hints = {
            @QueryHint(name = "org.hibernate.cacheable", value = "true"),
            @QueryHint(name = "org.hibernate.cacheRegion", value = "Metadata") }),
    @NamedQuery(name = NamedQueryList.WIDGETS_BY_ZONE_ORDER_BY_NAME, query = "from ContentWidget where zones like '%' || ? || '%' order by displayName", hints = {
            @QueryHint(name = "org.hibernate.cacheable", value = "true"),
            @QueryHint(name = "org.hibernate.cacheRegion", value = "Metadata") }),
    @NamedQuery(name = NamedQueryList.WIDGETS_BY_DASHBOARD_URL, query = "from ContentWidget where dashboardUrl like ? || '%'", hints = {
            @QueryHint(name = "org.hibernate.cacheable", value = "true"),
            @QueryHint(name = "org.hibernate.cacheRegion", value = "Metadata") }),
    @NamedQuery(name = NamedQueryList.WIDGETS_BY_NAME, query = "from ContentWidget where name = ?", hints = {
            @QueryHint(name = "org.hibernate.cacheable", value = "true"),
            @QueryHint(name = "org.hibernate.cacheRegion", value = "Metadata") }),
    @NamedQuery(name = NamedQueryList.WIDGETS_BY_CONTEXT, query = "from ContentWidget where zones like '%dashboard%' and ? in elements(dashboardContexts) order by orderNum", hints = {
            @QueryHint(name = "org.hibernate.cacheable", value = "true"),
            @QueryHint(name = "org.hibernate.cacheRegion", value = "Metadata") }) })
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "Metadata")
@EventDefaults({
        @EventHandlerDefaults(beanName = "contentWidgetPermissionCommand", eventType = EventTypeEnum.OnBeforeCreate),
        @EventHandlerDefaults(beanName = "contentWidgetPermissionCommand", eventType = EventTypeEnum.OnBeforeUpdate) })
@ReadPermission(name = AuthorizationService.ANONYMOUS_PERMISSION)
public class ContentWidget implements IContentWidget {
    private static final long       serialVersionUID = 1680304771254400928L;
    private String                  packageGuid;
    private Long                    id;

    private String                  name;                                   // unique name to reconcile imported data
    private String                  displayName;                            // used by UI
    private String                  description;                            // anchor title attribute
    private int                     orderNum;                               // universal ordering
    private String                  zones;                                  // csv: "top,left,dashboard,context,..."
    private String                  iconClass;
    private String                  displayPermission;

    // menu settings
    private IContentWidget          parent;

    private String                  targetUrl;

    private IListScreen             targetListScreen;
    private IItemScreen             targetItemScreen;
    private boolean                 isCacheable;
    private boolean                 isDivider;

    private boolean                 isPopup;

    private List<IEntityMetadata>   contextEntities;                        // for contextual menus
    protected IFilterDefinition     entityFilterDefinition;
    // dashboard settings
    private int                     dashboardWidth   = 1;
    private String                  dashboardUrl;
    private String                  dashboardWidgetType;
    private IListScreen             dashboardListScreen;
    private IItemScreen             dashboardItemScreen;
    private List<IEntityMetadata>   dashboardContexts;                      // for item screen dashboards

    private ISessionService         sessionService;
    @Autowired
    private IPassportContextService passportContextService;
    @Autowired
    private IReportingConfiguration reportingConfiguration;
    private Timestamp               createdAt;
    private Timestamp               updatedAt;
    private ICustomNamedQuery       menuCountQuery;
    private Set<IPassportContext>   passportContexts;
    }

Performance trace Update: 性能跟踪更新:

The method performance trace in GlowRoot is as below GlowRoot中的方法性能跟踪如下

60.0% com.dc.core.presentation.presenter.impl.WebContentPresenter.getMenuHTML(WebContentPresenter.java:435)
50.0% com.dc.core.presentation.service.impl.DashboardService.getMenuItems(DashboardService.java:258)
30.0% com.dc.core.presentation.service.impl.DashboardService.isAccessible(DashboardService.java:382)

Here is my WebContentPresenter.getMenuHTML() implementation 这是我的WebContentPresenter.getMenuHTML()实现

public String getMenuHTML(String baseUrl, String zone, String cssClass, IPersistentEntityInstance entityInstance) {
    (line 435) List<IContentWidget> instances = dashboardService.getMenuItems(zone);
    StringBuffer html = new StringBuffer();

    if (instances == null || instances.isEmpty()) {
        html.append("&nbsp;");
    }
    else {
        Map<Long, List<IContentWidget>> treeData = new HashMap<Long, List<IContentWidget>>();
        for (IContentWidget instance : instances) {
            BeanWrapperImpl bean = new BeanWrapperImpl(instance);
            Object parent = bean.getPropertyValue("parent");
            Long parentId = -1L;
            if (passportContextService.getIsInContext(instance)) {
                if (parent != null) {
                    parentId = ((IContentWidget) parent).getId();
                }
                List<IContentWidget> children = treeData.get(parentId);
                if (children == null) {
                    children = new ArrayList<IContentWidget>();
                }
                children.add(instance);
                treeData.put(parentId, children);
            }
        }

        generateTreeHtml(html, treeData, -1L, baseUrl, "parent", entityInstance,
                authorizationService.userHasAdminPermission(SecurityHelper.getAuthenticatedUser()));
    }
    return String.format("<ul class=\"%s\">%s</ul>", cssClass, html.toString());
}

For 64 items difference between collections is not significant. 对于64个项目,集合之间的差异并不重要。 I would rather investigate IContentWidget methods calls. 我宁愿调查IContentWidget方法调用。 How do you get those instances? 你如何得到这些实例? Maybe each time you call getter, there is performed query to database? 也许每次调用getter时,都会对数据库执行查询? Could you provide some more details about persistence layer? 你能提供一些关于持久层的更多细节吗?

For code readability I prefer : 为了代码可读性,我更喜欢:

public List<IContentWidget> getMenuItems(String zone) {
    if(zone == null){
        return Collections. < IContentWidget > emptyList();
    }
    List<IContentWidget> widgets = new ArrayList<IContentWidget>();
    List<IPersistentEntityInstance> instances = getWidgetsByZone(zone);
    for (IPersistentEntityInstance instance : instances) {
        IContentWidget contentWidget = (IContentWidget) instance;
        if (contentWidget.getZones() == null || contentWidget.getZones().contains(RESPONSIVE_VISIBLE)) {
           continue;
        }
        // Add widget only if the current user has read permission on the entity.
        if (contentWidget.getTargetItemScreen() == null ||
            contentWidget.getTargetListScreen()== null) {
            widgets.add(contentWidget);continue;
        }
        if (isAccessible(contentWidget)) {
             widgets.add(contentWidget);
        }


    }
}
Collections.sort(widgets, new Comparator<IContentWidget>() {

    public int compare(IContentWidget o1, IContentWidget o2) {
        return o1.getOrderNum() - o2.getOrderNum();
    }

});
return widgets;
}

Also change 也改变

private boolean isAccessible(IContentWidget contentWidget) {
    boolean isWidgetAccessible = false;
    String permission = contentWidget.getDisplayPermission();
    if (permission != null) {
        return authorizationService.userHasPermission(SecurityHelper.getAuthenticatedUser(),
                permission);
    }
    else {
        IBaseScreen screen = contentWidget.getTargetItemScreen() == null ? contentWidget.getTargetListScreen()
                : contentWidget.getTargetItemScreen();
        // return true when target screen is 'null', this means that target link cannot be secured because it is not
        // associated with any entity
        if (screen == null) {
            return true;
        }
        else {
            IAccessEntry access = authorizationService.getAccessForEntityMetadata(screen.getEntityMetadata());

            // fetching metadata from entityMetadataService again to trigger population of facade
            if (screen instanceof IListScreen && access.getIsReadable()) {
                isWidgetAccessible = true;
            }
            else if (screen instanceof IItemScreen && access.getIsCreatable()) {
                isWidgetAccessible = true;
            }
        }
    }
    return isWidgetAccessible;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM