optimizer code
diff --git a/include/dubbo.hrl b/include/dubbo.hrl
index f975fee..611eb69 100644
--- a/include/dubbo.hrl
+++ b/include/dubbo.hrl
@@ -39,8 +39,8 @@
     is_twoway = false       ::boolean(),
     data                    ::null|dubbo_rpc_invocation,
     mid                     ::integer(),
-    mversion                ::string(),
-    error_msg               ::string(),
+    mversion                ::binary(),
+    error_msg               ::binary(),
     state                   ::byte(),
     decode_state
 }).
@@ -74,7 +74,7 @@
     category = <<"consumers">> ::binary(),
     check=false                ::boolean(),
     default_timeout=500        ::integer(),
-    dubbo_version= <<"2.5.3">>         ::binary(),
+    dubbo_version= <<"2.5.3">> ::binary(),
     methods=[]                 ::list(),
     revision= <<"">>           ::binary(),
     side= <<"consumers">>      ::binary()
@@ -97,4 +97,7 @@
 
 -record(interface_list,{interface,pid,connection_info}).
 -record(provider_node_list,{host_flag,connection_info}).
--record(connection_info,{connection_id,pid,weight,host_flag}).
\ No newline at end of file
+-record(connection_info,{connection_id,pid,weight,host_flag}).
+
+-type dubbo_request() ::#dubbo_request{}.
+-type dubbo_response()::#dubbo_response{}.
\ No newline at end of file
diff --git a/include/dubbo_type.hrl b/include/dubbo_type.hrl
index f01d969..cd9972a 100644
--- a/include/dubbo_type.hrl
+++ b/include/dubbo_type.hrl
@@ -9,4 +9,5 @@
 -author("dlive").
 
 
--type response_content() :: binary().
\ No newline at end of file
+-type response_content() :: binary().
+
diff --git a/src/cotton_hessian.erl b/src/cotton_hessian.erl
index eeb756f..395389b 100644
--- a/src/cotton_hessian.erl
+++ b/src/cotton_hessian.erl
@@ -53,14 +53,13 @@
     {ref, Index} ->
       IndexBin = encode(int, Index, State),
       <<$Q, IndexBin/binary>>;
-    _Object ->
-      logger:debug("[encode] object ~p",[Input]),
-      encode(class_object, Input, State);
-%%			{<<>>,State};
     {K, V} ->
       {BK,SK} = encode(K, State),
       {BV,SV} = encode(V, SK),
-      {<<BK/binary, BV/binary>>, SV}
+      {<<BK/binary, BV/binary>>, SV};
+    _Object ->
+      logger:debug("[encode] object ~p",[Input]),
+      encode(class_object, Input, State)
   end;
 encode(int, Int, _State) when Int >= -16, Int =< 47 ->
   _Int = Int + 16#90,
@@ -240,10 +239,9 @@
   Size = size(CamMethod),
   <<$m,Size:16/unsigned,CamMethod/binary>>;
 encode(method, String, _State) when is_list(String) ->
-  CamString = erlang_to_camel_case(String),
-  Length = string:len(CamString),
-  Bin = list_to_binary(CamString),
-  <<$m,Length:16/unsigned,Bin/binary>>;
+  CamMethod = erlang_to_camel_case(String),
+  Size = size(CamMethod),
+  <<$m,Size:16/unsigned,CamMethod/binary>>;
 encode(reply, ok, _State) ->
   <<$H,16#02,16#00,$R,16#01,$N>>;
 encode(reply, {ok, Object}, State) ->
@@ -378,11 +376,12 @@
 %---------------------------------------------------------------------------
 erlang_to_camel_case(String) when is_binary(String) ->
   AsList = binary_to_list(String),
-  AsCamel = lists:foldl(fun camelize/2,[],AsList),
-  list_to_binary(AsCamel);
+  erlang_to_camel_case(AsList);
 erlang_to_camel_case(String) when is_atom(String) ->
   AsList = atom_to_list(String),
-  AsCamel = lists:foldl(fun camelize/2,[],AsList),
+  erlang_to_camel_case(AsList);
+erlang_to_camel_case(String) ->
+  AsCamel = lists:foldl(fun camelize/2,[],String),
   list_to_binary(AsCamel).
 
 camelize(Element,Acc) when Element == $_ -> [$_|Acc];
diff --git a/src/dubbo_adapter.erl b/src/dubbo_adapter.erl
index 5cccb8b..e3e6be4 100644
--- a/src/dubbo_adapter.erl
+++ b/src/dubbo_adapter.erl
@@ -13,7 +13,7 @@
 %% API
 -export([reference/1]).
 
--spec reference(Data::#dubbo_rpc_invocation{}) -> #dubbo_request{}.
+-spec(reference(Data::#dubbo_rpc_invocation{}) -> dubbo_request()).
 reference(Data)->
   #dubbo_request{
     is_event = false,
diff --git a/src/dubbo_codec.erl b/src/dubbo_codec.erl
index 1868ddf..ace771c 100644
--- a/src/dubbo_codec.erl
+++ b/src/dubbo_codec.erl
@@ -83,7 +83,7 @@
     Header.
 
 
--spec decode_header(binary())-> {State::ok|error,Type::request|response,Data::#dubbo_response{}|#dubbo_request{}}.
+-spec(decode_header(Header::binary())-> {State::ok|error,Type::request|response,Data::dubbo_response()|dubbo_request()}).
 decode_header(Header)->
     <<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,Flag:8,State:8,Mid:64,DataLen:32>> = Header,
     if
@@ -94,7 +94,7 @@
             {DecodeState,Req} = decode_header(request,Flag,State,Mid,DataLen),
             {DecodeState,request,Req}
     end.
-decode_header(request,Flag,State,Mid,DataLen)->
+decode_header(request,Flag,_State,Mid,_DataLen)->
     SerializeType = Flag band 16#1f,
     IsTwoWay = if
                    (Flag band 16#40) /=0 -> true;
@@ -112,7 +112,7 @@
         serialize_type = SerializeType
     },
     {ok,Req};
-decode_header(response,Flag,State,Mid,DataLen)->
+decode_header(response,Flag,State,Mid,_DataLen)->
     SerializeType = Flag band 16#1f,
     IsEvent = if
         (Flag band 16#20) /= 0 -> true;
diff --git a/src/dubbo_consumer_pool.erl b/src/dubbo_consumer_pool.erl
index c88c5eb..a0ff016 100644
--- a/src/dubbo_consumer_pool.erl
+++ b/src/dubbo_consumer_pool.erl
@@ -255,10 +255,6 @@
         List->
             Len = length(List),
             RemNum = (RandNum rem Len)+1,
-%%            RandNum2 = if
-%%                           RandNum==Len -> RandNum-1;
-%%                           true->RandNum
-%%                       end,
             InterfaceListItem = lists:nth(RemNum,List),
             {ok,InterfaceListItem#interface_list.connection_info}
     end.
diff --git a/src/dubbo_heartbeat.erl b/src/dubbo_heartbeat.erl
index 529ce39..97edbd2 100644
--- a/src/dubbo_heartbeat.erl
+++ b/src/dubbo_heartbeat.erl
@@ -12,6 +12,8 @@
 -include("dubbo.hrl").
 %% API
 -export([generate_request/2]).
+
+-spec(generate_request(RequestId::undefined|integer(),NeedResponse::boolean())->{ok,binary()}).
 generate_request(undefined,NeedResponse)->
     RequestId = dubbo_id_generator:gen_id(),
     generate_request(RequestId,NeedResponse);
diff --git a/src/dubbo_invoker.erl b/src/dubbo_invoker.erl
index 0116278..f7c9685 100644
--- a/src/dubbo_invoker.erl
+++ b/src/dubbo_invoker.erl
@@ -52,28 +52,14 @@
             end;
         {error,none}->
             logger:error("[INVOKE] ~p error Reason no_provider",[Interface]),
-            {error,no_provider};
-        {error,R1}->
-            logger:error("[INVOKE] ~p error Reason ~p",[Interface,R1]),
-            {error,R1}
+            {error,no_provider}
     end.
 
 
 is_sync(Option)->
     maps:is_key(sync,Option).
-%%    lists:member(sync,Option).
 get_ref(Option)->
     maps:get(ref,Option,make_ref()).
-%%    case maps:is_key(ref,Option) of
-%%        true->
-%%
-%%    end,
-%%    case proplists:get_value(ref,Option) of
-%%        undefined->
-%%            make_ref();
-%%        Ref->
-%%            Ref
-%%    end.
 
 get_timeout(Option)->
     maps:get(timeout,Option,?REQUEST_TIME_OUT).
@@ -87,7 +73,8 @@
         TimeOut ->
             {error,timeout}
     end.
-
+merge_attachments(#dubbo_request{data = null}=Request,_Option) ->
+    Request;
 merge_attachments(Request,Option)->
     Attachements= Request#dubbo_request.data#dubbo_rpc_invocation.attachments,
     case lists:keyfind(attachments,1,Option) of
diff --git a/src/dubbo_netty_client.erl b/src/dubbo_netty_client.erl
index f2b716a..d837b0f 100644
--- a/src/dubbo_netty_client.erl
+++ b/src/dubbo_netty_client.erl
@@ -73,7 +73,7 @@
     State = case open(Host,Port) of
                 {ok,Socket} ->
                     #state{socket = Socket};
-                {error}->
+                {error,_Reason}->
                     #state{}
     end,
     NowStamp = time_util:timestamp_ms(),
@@ -236,17 +236,14 @@
         {nodelay, true},
         {high_watermark, 512 * 1024},
         {low_watermark, 256 * 1024},
-%%        {high_msgq_watermark,128 * 1024},
-%%        {low_msgq_watermark,64 * 1024},
         {sndbuf, 512 * 1024},
         {recbuf, 512 * 1024}
         ]) of
         {ok,Sockets} ->
-%%            inet:setopts(Sockets, [{active, once}]),
             inet:setopts(Sockets, [{active, true}]),
             {ok,Sockets};
         Info ->
-            logger:error("start netty client ~p~n",[Info]),
+            logger:error("start client connection error ~p",[Info]),
             {error,Info}
     end.
 
diff --git a/src/dubbo_serializa_json.erl b/src/dubbo_serializa_json.erl
index fd8a211..c7126b8 100644
--- a/src/dubbo_serializa_json.erl
+++ b/src/dubbo_serializa_json.erl
@@ -18,12 +18,7 @@
 encode_request_data(Request)->
     DataType =case Request#dubbo_request.is_event of
                   false->
-                      case Request#dubbo_request.data of
-                          #dubbo_rpc_invocation{} ->
-                              dubbo_rpc_invocation;
-                          _ ->
-                              unknow
-                      end;
+                      dubbo_rpc_invocation;
                   true->
                       dubbo_event
               end,
@@ -31,21 +26,16 @@
     {ok,Bin}.
 
 
-encode_request_data(dubbo_rpc_invocation,Request,Data,State) ->
+encode_request_data(dubbo_rpc_invocation,_Request,Data,State) ->
     RequestList = [
-%%        jiffy:encode(?DUBBO_VERSION,[]),
         string_encode(?DUBBO_VERSION),
         ?LINE_SEPERATOR,
-%%        jiffy:encode(Data#dubbo_rpc_invocation.className,[]),
         string_encode(Data#dubbo_rpc_invocation.className),
         ?LINE_SEPERATOR,
-%%        jiffy:encode(Data#dubbo_rpc_invocation.classVersion,[]),
         string_encode(Data#dubbo_rpc_invocation.classVersion),
         ?LINE_SEPERATOR,
-%%        jiffy:encode(Data#dubbo_rpc_invocation.methodName,[]),
         string_encode(Data#dubbo_rpc_invocation.methodName),
         ?LINE_SEPERATOR,
-%%        jiffy:encode(Data#dubbo_rpc_invocation.parameterDesc,[]),
         string_encode(Data#dubbo_rpc_invocation.parameterDesc),
         ?LINE_SEPERATOR
     ],
@@ -53,10 +43,9 @@
     AttachBinay = jiffy:encode({Data#dubbo_rpc_invocation.attachments},[]),
     RequestData = erlang:iolist_to_binary(RequestList ++ [ArgsBin,AttachBinay,?LINE_SEPERATOR]),
     {ok,RequestData};
-encode_request_data(dubbo_event,Request,Data,State) ->
+encode_request_data(dubbo_event,_Request,Data,_State) ->
     %% @todo 确认该数据类型
     Bin =  jiffy:encode(Data),
-%%    Bin = cotton_hessian:encode(Data,State),
     {ok,Bin}.
 
 
diff --git a/src/dubbo_traffic_control.erl b/src/dubbo_traffic_control.erl
index e437ffb..a8bd010 100644
--- a/src/dubbo_traffic_control.erl
+++ b/src/dubbo_traffic_control.erl
@@ -31,9 +31,7 @@
             ets:update_counter(?TRAFFIC_CONTROL,Key,-1),
             full;
         _V ->
-%%            logger:debug("check traffic incr value ~p",[V]),
             ok
-
     catch
         _T:_R->
             ets:insert(?TRAFFIC_CONTROL,{Key,1}),
diff --git a/src/time_util.erl b/src/time_util.erl
index b6bda7a..31e09ee 100644
--- a/src/time_util.erl
+++ b/src/time_util.erl
@@ -1,154 +1,49 @@
-
-
-
 -module(time_util).
 
 -include_lib("kernel/include/file.hrl").
 
 
 -export([
-	get_cur_time/0,get_cur_time/1,
-	format_time_to_str/1,
-	timestamp/0,timestamp_ms/0,
-	timestamp_to_datetime/1,
-	timestamp_to_local_datetime/1,
-	get_cur_date/0,
-	datetime_to_timestamp/1,
-	datetime_string_to_timestamp/1,get_curdate_timestamp/0]).
+    get_cur_time/0,get_cur_time/1,
+    format_time_to_str/1,
+    timestamp/0,timestamp_ms/0,
+    timestamp_to_datetime/1,
+    timestamp_to_local_datetime/1,
+    get_cur_date/0,
+    datetime_to_timestamp/1]).
 
 
 get_cur_time()->
-	{{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time(os:timestamp()),
-	io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
+	  {{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time(os:timestamp()),
+	  io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
 
 get_cur_date()->
-	{{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time(os:timestamp()),
-	io_lib:format("~4..0w-~2..0w-~2..0w",[Year, Month, Day]).
+	  {{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time(os:timestamp()),
+    io_lib:format("~4..0w-~2..0w-~2..0w",[Year, Month, Day]).
 
 get_cur_time({{Year,Month,Day},{Hour,Min,Second}})->
-	io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
+	  io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
 
 format_time_to_str({{Year,Month,Day},{Hour,Min,Second}})->
-	io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
+	  io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
 
-timestamp() ->  
-    {M, S, _} = os:timestamp(),  
+timestamp() ->
+    {M, S, _} = os:timestamp(),
     M * 1000000 + S.
 timestamp_ms()->
     {M,S,W} = os:timestamp(),
     M*1000000000+S*1000+(W div 1000).
 
 timestamp_to_datetime(Timestamp) ->
-    calendar:gregorian_seconds_to_datetime(Timestamp +  
+    calendar:gregorian_seconds_to_datetime(Timestamp +
       calendar:datetime_to_gregorian_seconds({{1970,1,1}, {0,0,0}})).
 timestamp_to_local_datetime(Timestamp) ->
-    Date=calendar:gregorian_seconds_to_datetime(Timestamp +  
+    Date=calendar:gregorian_seconds_to_datetime(Timestamp +
       calendar:datetime_to_gregorian_seconds({{1970,1,1}, {0,0,0}})),
     calendar:universal_time_to_local_time(Date).
 
-%% @doc 时间转时间戳
 datetime_to_timestamp(Date)->
-	[{D,T}]=calendar:local_time_to_universal_time_dst(Date),
-	S = calendar:datetime_to_gregorian_seconds({D, T}),
+	  [{D,T}]=calendar:local_time_to_universal_time_dst(Date),
+	  S = calendar:datetime_to_gregorian_seconds({D, T}),
     S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}),
-    Seconds = (S - S1).
-    % {Seconds div 1000000, Seconds rem 1000000, MS}.
-
-%% @doc 时间字符串转 时间戳
-datetime_string_to_timestamp(TimeStr) ->
-    case catch parse_datetime(TimeStr) of
-    {'EXIT', _Err} ->
-        undefined;
-    TimeStamp ->
-        TimeStamp
-    end.
-
-parse_datetime(TimeStr) ->
-    [Date, Time] = string:tokens(TimeStr, "T"),
-    D = parse_date(Date),
-    {T, MS, TZH, TZM} = parse_time(Time),
-    S = calendar:datetime_to_gregorian_seconds({D, T}),
-    S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}),
-    Seconds = (S - S1) - TZH * 60 * 60 - TZM * 60,
-    {Seconds div 1000000, Seconds rem 1000000, MS}.
-
-% yyyy-mm-dd
-parse_date(Date) ->
-    [Y, M, D] = string:tokens(Date, "-"),
-    Date1 = {list_to_integer(Y), list_to_integer(M), list_to_integer(D)},
-    case calendar:valid_date(Date1) of
-    true ->
-        Date1;
-    _ ->
-        false
-    end.
-
-% hh:mm:ss[.sss]TZD
-parse_time(Time) ->
-    case string:str(Time, "Z") of
-    0 ->
-        parse_time_with_timezone(Time);
-    _ ->
-        [T | _] = string:tokens(Time, "Z"),
-        {TT, MS} = parse_time1(T),
-        {TT, MS, 0, 0}
-    end.
-
-parse_time_with_timezone(Time) ->
-    case string:str(Time, "+") of
-    0 ->
-        case string:str(Time, "-") of
-        0 ->
-            false;
-        _ ->
-            parse_time_with_timezone(Time, "-")
-        end;
-    _ ->
-        parse_time_with_timezone(Time, "+")
-    end.
-
-parse_time_with_timezone(Time, Delim) ->
-    [T, TZ] = string:tokens(Time, Delim),
-    {TZH, TZM} = parse_timezone(TZ),
-    {TT, MS} = parse_time1(T),
-    case Delim of
-    "-" ->
-        {TT, MS, -TZH, -TZM};
-    "+" ->
-        {TT, MS, TZH, TZM}
-    end.
-
-parse_timezone(TZ) ->
-    [H, M] = string:tokens(TZ, ":"),
-    {[H1, M1], true} = check_list([{H, 12}, {M, 60}]),
-    {H1, M1}.
-
-parse_time1(Time) ->
-    [HMS | T] =  string:tokens(Time, "."),
-    MS = case T of
-         [] ->
-         0;
-         [Val] ->
-         list_to_integer(string:left(Val, 6, $0))
-     end,
-    [H, M, S] = string:tokens(HMS, ":"),
-    {[H1, M1, S1], true} = check_list([{H, 24}, {M, 60}, {S, 60}]),
-    {{H1, M1, S1}, MS}.
-
-check_list(List) ->
-    lists:mapfoldl(
-      fun({L, N}, B)->
-      V = list_to_integer(L),
-      if
-          (V >= 0) and (V =< N) ->
-          {V, B};
-          true ->
-          {false, false}
-      end
-      end, true, List).
-%% @doc 获取当天零点时间戳
-get_curdate_timestamp()->
-    {M, S, T} = os:timestamp(),
-    TimestampTmp = M * 1000000 + S,
-    {{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time({M, S, T}),
-    TimestampTmp - Second -(Hour*60+Min)*60.
\ No newline at end of file
+    (S - S1).
diff --git a/test/dubbo_heartbeat_tests.erl b/test/dubbo_heartbeat_tests.erl
new file mode 100644
index 0000000..bdc2d49
--- /dev/null
+++ b/test/dubbo_heartbeat_tests.erl
@@ -0,0 +1,20 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2019, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 15. May 2019 23:57
+%%%-------------------------------------------------------------------
+-module(dubbo_heartbeat_tests).
+-author("dlive").
+
+-include_lib("eunit/include/eunit.hrl").
+
+heartbeat1_test()->
+  dubbo_id_generator:start_link(),
+  {ok,Data} = dubbo_heartbeat:generate_request(undefined,false),
+  ?assert(is_binary(Data)).
+
+simple_test() ->
+  ?assert(true).