当我发现奇怪的事情时,我试图使用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"
,即使结果相同,因为二进制文件不包含任何y
或x
。即使我重新拨打电话,我也可以重现这一点。
所以我的问题是为什么会发生这种情况,如何让单个二进制搜索更快?
(我正在运行Erlang/OTP 19 [erts-8.0.2]
。)
答案 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">>]
没有)。但不知道为什么会发生这种情况。