为什么在Erlang中使用`binary:match`搜索一个二进制文件比搜索多个二进制文件更快?

时间:2016-09-30 09:03:15

标签: erlang

当我发现奇怪的事情时,我试图使用binary:match而不是模式匹配来优化Elixir中的解析器:binary:match(Binary, [<<"z">>, <<"y">>])binary:match(Binary, <<"z">>)快几倍,即使二进制没有&# 39; t包含任何y。这是重现这一点的最小程序:

-module(a).
-compile(export_all).

one(Binary) ->
  binary:match(Binary, <<"z">>).

two(Binary) ->
  binary:match(Binary, [<<"z">>, <<"y">>]).

three(Binary) ->
  binary:match(Binary, [<<"z">>, <<"y">>, <<"x">>]).

main() ->
  As = binary:copy(<<"a">>, 10485760),
  Zs = binary:copy(<<"z">>, 10485760),
  Binary = <<As/binary, Zs/binary>>,
  io:format("~p~n", [timer:tc(?MODULE, one, [Binary])]),
  io:format("~p~n", [timer:tc(?MODULE, two, [Binary])]),
  io:format("~p~n", [timer:tc(?MODULE, three, [Binary])]).

这是一个相当快的OSX系统上的输出:

{62556,{10485760,1}}
{18272,{10485760,1}}
{18558,{10485760,1}}

并且不是那么快的Linux VPS:

{130249,{10485760,1}}
{39296,{10485760,1}}
{40805,{10485760,1}}

因此,对于包含10MB a后跟10MB z的二进制文件,搜索["z", "y"]["z", "y", "x"]大约需要30%的时间而不是搜索"z",即使结果相同,因为二进制文件不包含任何yx。即使我重新拨打电话,我也可以重现这一点。

所以我的问题是为什么会发生这种情况,如何让单个二进制搜索更快?

(我正在运行Erlang/OTP 19 [erts-8.0.2]。)

1 个答案:

答案 0 :(得分:1)

加快搜索单个二进制文件的明显解决方法是搜索else if(rec_data_string.contains(cs2)) { //System.out.println("1SecData"); //if one second data /*===================extracting data from input string======================================*/ try{ String Split =null,simsplit=null,latlon=null,slat=null; String[] Splitlat=null;String[] sptime=null;String[] spdate=null;String[] svel=null; String[] sdist=null;String[] salt=null;String[] sbat=null;String[] Signitn=null;String[] strSSTR=null; String[] sacc=null;String[] fsacc=null; String EventTyp="E"; System.out.println("INPUT DATA FROM DEV::>"+rec_data_string); { try { recsplit=rec_data_string.split("\\?"); Split=recsplit[1]; varsplit=Split.split("\\&"); simsplit=varsplit[0]; splstrSimNo=simsplit.split("="); strSimNo=splstrSimNo[1]; //extracting data lStrSimNo=strSimNo.length(); latlon=varsplit[3]; splitlatlon=latlon.split("LON:"); Lon=splitlatlon[1]; //extracting data slat=splitlatlon[0]; Splitlat =slat.split("LAT:"); Lat=Splitlat[1]; //extracting data sptime=varsplit[1].split("="); strTime=sptime[1]; //extracting data spdate=varsplit[2].split("="); strDate=spdate[1]; //extracting data svel=varsplit[4].split("="); strVel=svel[1]; //extracting data sdist=varsplit[5].split("="); strDist=sdist[1]; //extracting data salt=varsplit[6].split("="); stralt=salt[1]; //extracting data sbat=varsplit[10].split("="); strbat=sbat[1]; //extracting data Signitn=varsplit[13].split("="); Ignition=Signitn[1]; //extracting data strSSTR=varsplit[16].split("="); SSTR=strSSTR[1]; //extracting data sacc=varsplit[17].split("="); fsacc=sacc[1].split(" "); SSSTR=fsacc[0]; stracc=SSSTR.trim(); //extracting data /*=========================DATA VALIDATION STARTS HERE==================================*/ float chklat=Float.parseFloat(Lat); float chklon=Float.parseFloat(Lon); //calling the function for data validation. //it checks 1. if the unit id is 10 digits or not // 2. if the date time and latlon variables are not null // 3. if the laat lon is in given range or not //if YES.. returns valid data //if NO... returns the appropriate reason handled in the else and exits the block. // 1.if incorrect lat,lon--logs the instance and waits for the next data. SOCKET IS NOT CLOSED IF LAT LON IS ZERO. // 2.if any other validation failure-- logs and CLOSES the socket. ValResp=Validation(lStrSimNo, strDate, strTime, latlon, chklat, chklon); if(ValResp=="valid data") { //date time conversion starts here>>> sstrdate="20"+strDate.trim(); Date startDate =formatter1.parse(sstrdate); String hh=strTime.substring(0,2); String mm=strTime.substring(2,4); String ss=strTime.substring(4,6); sstrtime=hh+":"+mm+":"+ss; String DTT=sstrdate+" "+sstrtime.trim(); Date startDate1 = (Date)targetformatter.parse(DTT); Calendar call = Calendar.getInstance(); call.setTime(startDate1); call.add(Calendar.MINUTE, 330); //adding 330 min to convert GMT to IST String newTime = targetformatter.format(call.getTime()); Date startDate2 = (Date)targetformatter.parse(newTime); //converting Latitude into understandable value>>>> lat=LatParseCovert(Lat); //converting Longitude into understandable value>>>> lon=LonParseCovert(Lon); //making speed parseable for tables>>> double speed=Double.parseDouble(strVel); //getting the previous latitude and longitude for distance calculation>>> //the SP returns the previous lat,lon String latlonresp=DataManager.callEIL_spGetPrvLatLon(strSimNo); if(latlonresp!="5"){ String[] dbqry4=latlonresp.split(","); prelat=Double.parseDouble(dbqry4[0]); prelon=Double.parseDouble(dbqry4[1]); dttime=dbqry4[2]; //calculating the distance between two latitudes and longitudes>>> double dbldist=1.02*(DataManager.Distance(prelat, prelon, lat, lon)); accdbldist=Double.parseDouble(String.format("%.5f",dbldist)); String SD2=targetformatter.format(startDate2); Date date1 = formatter2.parse(dttime); Date date2 = targetformatter.parse(SD2); long difference = date2.getTime() - date1.getTime(); TimeDiff=(double)difference/(60*60*1000); //this is done to keep out incorrect lat lon from inserting into table //using distance=speed X time. where the max spd is 120kmph.>>> //if the accdbldist is greater than maximun calculated distance it can move,the variable is set to 0>>> double spdcalc=120; //speed in km/hr if(accdbldist>TimeDiff*spdcalc) { accdbldist=0; } DataManager.callEIL_spGpsDataSecbySec(strSimNo, lat, lon, speed, NoS, startDate2, Ignition, accdbldist, EventTyp, stracc,strbat); } else { //if no previous lat,lon found,inserting data into table as it is the first data from the device>>> //distance will be zero>>> accdbldist=0; //tbl GPSDATA insertion if the data is the first data from the device DataManager.callEIL_spGpsDataSecbySec(strSimNo, lat, lon, speed, NoS, startDate2, Ignition, accdbldist, EventTyp, stracc,strbat); } //updating tblsstr only if SSTR value satisfies the below condition if(!SSTR.equals("NULL")&&(!SSTR.equals(null))) { DataManager.callEIL_spSSTR(strSimNo, startDate2, SSTR, lat, lon, speed, NoS, Ignition, accdbldist); } accdbldist=0.0d; } else if(ValResp=="Incorrect lat-lon"){ //code to exit if lat,lon not correct //System.out.println("INCORRECT LAT LON"); LogManager.logError("incorrect coordinates:"+strSimNo+","+chklat+","+chklon); } else{ //code to exit if strDate,strTime,latlon is null //System.out.println("MALFORMED PACKET"); LogManager.logError("Packet Incorrect: "+rec_data_string+","+conn.getInetAddress()); conn.close(); System.gc(); } } catch (Exception e) { //e.printStackTrace(); LogManager.logException(e.getMessage()+Arrays.toString(e.getStackTrace())); } }//for block ends here } /*==================================================VALIDATION ENDS HERE=======================================================*/ catch(Exception e) { //e.printStackTrace(); LogManager.logException(rec_data_string+e.getMessage()+Arrays.toString(e.getStackTrace())); } }//else if loop 1sec data ending here (我已检查过它是否有效以及搜索[<<"z">>, <<"z">>]没有)。但不知道为什么会发生这种情况。