private void frequencyTable(ServletOutputStream out, TimerInfoStats stats, String sort, String baseurl)
            throws IOException {
        Set<TimerInfoItem> treeSet;
        if ("perf".equalsIgnoreCase(sort)) {
            treeSet = new TreeSet<TimerInfoItem>(new AverageComparator());
        } else if ("uri".equalsIgnoreCase(sort)) {
            treeSet = new TreeSet<TimerInfoItem>(new UriComparator());
        } else {
            treeSet = new TreeSet<TimerInfoItem>(new TotalTimeComparator());
        }
        treeSet.addAll(stats.getStatData().values());
        float totaltime = tistat.getElapsedTime() / 1000f; // secs
        //threadload
        //long totalcall = tistat.getTotalNofCalls();
        //float callssecs = totalcall / totaltime;
        //double threadload = (tistat.getTotalAverage() * callssecs) / 1000f;
        //
        out.println("<br/>");
        out.println("<table style='border:1px solid black' cellspacing='0' cellpadding='1'>");
        out.println("<tr bgcolor='#eeeeff'>");
        out.println("<th>No</th>");
        out.println("<th># Calls</th>");
        out.println("<th>Total (s)</th>");
        out.println("<th>Min (s)</th>");
        out.println("<th>1/Frequency (s)</th>");
        out.println("<th>Max (s)</th>");
        out.println("<th>Std (s)</th>");
        out.println("<th><a href='" + baseurl + "&sort=perf'>Perf (#/s)</a></th>");
        out.println("<th><a href='" + baseurl + "&sort=time'>Total (%)</a></th>");
        out.println("<th>Rate (#/s)</th>");
        out.println("<th>Td99 [s]</th>");
        out.println("<th>Payload [KB]</th>");
        out.println("<th>Bitrate [KB/s]</th>");
        out.println("<th>Cacheability TTL5 [%]</th>");
        out.println("<th>Cacheability TTL15 [%]</th>");
        out.println("<th><a href='" + baseurl + "&sort=uri'>URI</a></th></tr>");
        NumberFormat nf0 = NumberFormat.getInstance();
        nf0.setMaximumFractionDigits(0);
        nf0.setMinimumFractionDigits(0);
        NumberFormat nf1 = NumberFormat.getInstance();
        nf1.setMaximumFractionDigits(1);
        nf1.setMinimumFractionDigits(1);
        NumberFormat nf2 = NumberFormat.getInstance();
        nf2.setMaximumFractionDigits(2);
        nf2.setMinimumFractionDigits(2);
        NumberFormat nf3 = NumberFormat.getInstance();
        nf3.setMaximumFractionDigits(3);
        nf3.setMinimumFractionDigits(3);
        long loop = 1;
        //frequencyTable
        Map<String, CacheInfoItem> clone = stats.getCacheData();
        for (TimerInfoItem item : treeSet) {
            String key = item.getKey();
            double[] freqDataArray = item.getFreqDataArray(stats.getTotalTotalTime(), 1d, totaltime);
            CacheInfoItem cacheInfoItem = clone.get(key);
            if (freqDataArray[0] != 0) {
                out.println("<tr align='right'>");
                out.println("<td>" + nf0.format(loop++) + "</td>");
                out.println("<td>" + nf0.format(freqDataArray[0]) + "</td>");
                out.println("<td>" + nf0.format(freqDataArray[1]) + "</td>");
                out.println("<td bgcolor='#eeeeff'>" + nf1.format(freqDataArray[2]) + "</td>");
                out.println("<td bgcolor='#dddddd'>" + nf1.format(freqDataArray[3]) + "</td>");
                out.println("<td bgcolor='#eeeeff'>" + nf1.format(freqDataArray[4]) + "</td>");
                out.println("<td>" + nf1.format(freqDataArray[5]) + "</td>");
                out.println("<td>" + nf2.format(freqDataArray[6]) + "</td>");
                out.println("<td>" + nf3.format(freqDataArray[7]) + "</td>");
                out.println("<td>" + nf3.format(freqDataArray[8]) + "</td>");
                if (key.contains("|200|") || key.equals("TOTAL")) {
                    out.println("<td>" + nf2.format(freqDataArray[9]) + "</td>");
                    out.println("<td bgcolor='#eee'>" + nf1.format(freqDataArray[10] / 1024) + "</td>");
                    out.println("<td bgcolor='#eee'>" + nf1.format(freqDataArray[12] / 1024) + "</td>");
                    out.println("<td>" + nf1.format(cacheInfoItem.getCacheability5()) + "</td>");
                    out.println("<td>" + nf1.format(cacheInfoItem.getCacheability15()) + "</td>");
                } else {
                    out.println("<td>-</td>");
                    out.println("<td bgcolor='#eee'>-</td>");
                    out.println("<td bgcolor='#eee'>-</td>");
                    out.println("<td>-</td>");
                    out.println("<td>-</td>");
                }
                out.println("<td style='border-right:none' align='left'>" + key + "</td>");
            }
            out.println("</tr>");
            if (loop > 10000) {
                break;
            }
        }
        out.println("\r\n<tr bgcolor='#eeeeff'><td colspan='16' style='border:none'>&nbsp;</td></tr></table>");
    }