最近有人提出在lucene.net中:
Throwing an exception as a result of a normal situation is extremely bad in .net 。
在QueryParser\FastCharStream.cs 中 Refill() 方法里有这么一段:
int charsRead = input.Read(buffer, newPosition, buffer.Length - newPosition);
if (charsRead <= 0)
throw new System.IO.IOException("read past eof");
else
bufferLength += charsRead;
我们知道,在net中捕捉异常是比较耗资源的。
这里有篇文章对异常做了性能分析和测试:Performance implications of Exceptions in .NET
初看代码,感觉比较奇怪,为什么要对charsRead做异常处理?是否可以改成这样:
int charsRead = input.Read(buffer, newPosition, buffer.Length - newPosition);
if (charsRead > 0)
bufferLength += charsRead;
单从代码上看是没有问题的,但放在整个lucene的环境里就有问题。这样会造成死循环。if (charsRead > 0)
bufferLength += charsRead;
为什么会造成死循环?此段异常处理干嘛用的?造成死循环的地方是在ReadChar()方法里(确切的说是调用ReadChar方法的QueryParserTokenManager.cs里)。这里就不分析具体代码了,比较复杂。那我们有没有办法消除这个异常(这个异常是为调用此方法准备的)
下面先具体看下怎么消除异常:
QueryParser\FastCharStream.cs 中 Refill() 方法:
int charsRead = input.Read(buffer, newPosition, buffer.Length - newPosition);
if (charsRead <= 0)
throw new System.IO.IOException("read past eof");
else
bufferLength += charsRead;
改为:
int charsRead = input.Read(buffer, newPosition, buffer.Length - newPosition);
if (charsRead > 0)
bufferLength += charsRead;
ReadChar()方法:if (charsRead > 0)
bufferLength += charsRead;
public char ReadChar()
{
if (bufferPosition >= bufferLength)
Refill();
if (bufferPosition < bufferLength)
return buffer[bufferPosition++];
}
{
if (bufferPosition >= bufferLength)
Refill();
if (bufferPosition < bufferLength)
return buffer[bufferPosition++];
}
修改成:
public char ReadChar()
{
if (bufferPosition >= bufferLength)
Refill();
if (bufferPosition < bufferLength)
return buffer[bufferPosition++];
else//增加的,为了调用ReadChar()方法消除异常
return '\0';
}
在QueryParser\QueryParserTokenManager.cs 中查找ReadChar()方法(有多个):{
if (bufferPosition >= bufferLength)
Refill();
if (bufferPosition < bufferLength)
return buffer[bufferPosition++];
else//增加的,为了调用ReadChar()方法消除异常
return '\0';
}
有一下代码:也许你明白了
try
{
curChar = input_stream.ReadChar();
}
catch (System.IO.IOException e)
{
return curPos;
}
根据修改的ReadChar()方法可以修改为:{
curChar = input_stream.ReadChar();
}
catch (System.IO.IOException e)
{
return curPos;
}
curChar = input_stream.ReadChar();
if (curChar == '\0')
return curPos;
可以把try...Catch移除了。if (curChar == '\0')
return curPos;
ok完工