package httl.test;

import httl.test.model.Book;
import httl.test.model.User;
import httl.test.performance.BeetlCase;
import httl.test.performance.Case;
import httl.test.performance.Counter;
import httl.test.performance.FreemarkerCase;
import httl.test.performance.HttlCase;
import httl.test.performance.JavaCase;
import httl.test.performance.Smarty4jCase;
import httl.test.performance.VelocityCase;
import httl.test.util.DiscardWriter;

import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

import org.junit.Test;

public class PerformanceTest {

    @Test
    public void testPerformance() throws Exception {
    	int count = getProperty("count", 10000);
        int list = getProperty("list", 100);
        Random random = new Random();
        Book[] books = new Book[list];
        for (int i = 0; i < list; i ++) {
            books[i] = new Book(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString(), new Date(), random.nextInt(100) + 10, random.nextInt(60) + 30);
        }
        Map<String, Object> context = new HashMap<String, Object>();
        context.put("user", new User("liangfei", "admin", "Y"));
        context.put("books", books);
        Case[] cases = new Case[] { new BeetlCase(), new Smarty4jCase(), new FreemarkerCase(), new VelocityCase(), new HttlCase(), new JavaCase() };
        System.out.println("=======test environment========");
        System.out.println("os: " + System.getProperty("os.name") + " " + System.getProperty("os.version")  + ", cpu: " + Runtime.getRuntime().availableProcessors() 
        		+ ", jvm: " + System.getProperty("java.version") + ", memory: " + Runtime.getRuntime().totalMemory()
        		+ ", count: " + count + ", size: " + list);
        for (int i = 0; i < cases.length; i ++) {
        	Case c = cases[i];
        	String name = c.getClass().getSimpleName().replace("Case", "");
            System.out.println("========" + name.toLowerCase() + "========");
            Counter counter = new Counter();
            StringWriter writer = new StringWriter();
            // 当开启stream模式后，假设你的原生输出为byte[]流输出，比如HTTP的响应流。
            // 这样Writer实际是包装流的，所有输出String都需要编码成byte[]流，下面使用StreamWriter模拟。
            // 否则将不公平，因为httl会将静态文本编译byte[]，并为动态插值增加getBytes()。
            // 这个getBytes()实际是将Writer的转码提前了，是会增加开销的，但会减少Writer的开销。
            c.count(counter, count, "books", new HashMap<String, Object>(context), writer, new DiscardWriter());
            System.out.println("init: " + counter.getInitialized() + "ms, " +
            		"compile: " + counter.getCompiled() + "ms, " +
            		"first: " + counter.getExecuted() + "ms/" + writer.getBuffer().length() + "byte, " +
            		"total: " + counter.getFinished() + "ms/" + count + ", " +
            		"tps: " + (counter.getFinished() == 0 ? 0L : (1000L * count / counter.getFinished())) + "/s.");
        }
    }
    
    private static int getProperty(String key, int defaultValue) {
    	String value = System.getProperty(key);
    	if (value != null && value.length() > 0 && value.matches("\\d+")) {
    		return Integer.parseInt(value);
    	}
    	return defaultValue;
    }
    
    public static void main(String[] args) throws Exception {
        new PerformanceTest().testPerformance();
    }
    
}

@@ -758,19 +758,19 @@
    int l
-ist
+oop
  = getPr
@@ -778,19 +778,19 @@
 perty(%22l
-ist
+oop
 %22, 100);
@@ -861,19 +861,19 @@
 w Book%5Bl
-ist
+oop
 %5D;%0A     
@@ -896,19 +896,19 @@
 0; i %3C l
-ist
+oop
 ; i ++) 
@@ -1595,17 +1595,63 @@
 rsion%22) 
- 
++ %22 %22+ System.getProperty(%22os.arch%22)%0A        %09%09
 + %22, cpu
@@ -1703,28 +1703,66 @@
 s() 
-%0A        %09%09+ %22, jvm:
++ %22 cores, jvm: %22 + System.getProperty(%22java.vm.name%22) + %22
  %22 +
@@ -1806,16 +1806,18 @@
  %22, 
+%5Cn
 memory: 
 %22 + 
@@ -1816,62 +1816,351 @@
 ry: 
-%22 + Runtime.getRuntime().totalMemory()%0A        %09%09+ %22, 
+max: %22 + Runtime.getRuntime().maxMemory() %0A        %09%09+ %22, total: %22 + Runtime.getRuntime().totalMemory() + %22, free: %22 + Runtime.getRuntime().freeMemory() %0A        %09%09+ %22, use: %22 + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));%0A        System.out.println(%22=======test parameters========%22);%0A        System.out.println(%22
 coun
@@ -2181,22 +2181,22 @@
  %22, 
-size
+loop
 : %22 + l
-ist
+oop
 );%0A 

modify performance test