- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
试图解决另一个 SO question ,我想出了以下我认为非常优化的算法。但是在运行时 DotNetBenchmark
在所有解决方案中,令我感到非常惊讶的是我的代码运行在 387 ms
的惊人平均值上与 ~ 20-30 ms
相比其他一些答案已实现。
[MethodImpl(MethodImplOptions.AggressiveInlining)]
int CalcMe(string input) // I used Marc Gravel's input generation method
{
var operands = input.Split(' ');
var j = 1; // operators index
var result = int.Parse(operands[0]); // output
// i = numbers index
for (int i = 2; i < operands.Length; i += 2)
{
switch (operands[j])
{
case "+":
result += int.Parse(operands[i]);
break;
case "-":
result -= int.Parse(operands[i]);
break;
case "*":
result *= int.Parse(operands[i]);
break;
case "/":
try
{
result /= int.Parse(operands[i]);
break;
}
catch
{
break; // division by 0.
}
default:
throw new Exception("Unknown Operator");
}
j += 2; // next operator
}
return result;
}
只需提取 String.Split()
给来电者 Main()
方法,我将执行降低到 110 ms
,但这仍然没有解开谜团,因为所有其他答案都直接处理输入。
我只是想了解也许可以改变我对优化的思考方式。我看不到任何我只使用的关键字。 switch
, for
和 int.Parse()
几乎所有其他解决方案。
编辑 1:测试输入生成输入生成是从 Marc 对原始问题的回答复制而来的,如下所示:
static string GenerateInput()
{
Random rand = new Random(12345);
StringBuilder input = new StringBuilder();
string operators = "+-*/";
var lastOperator = '+';
for (int i = 0; i < 1000000; i++)
{
var @operator = operators[rand.Next(0, 4)];
input.Append(rand.Next(lastOperator == '/' ? 1 : 0, 100) + " " + @operator + " ");
lastOperator = @operator;
}
input.Append(rand.Next(0, 100));
return input.ToString();
}
最佳答案
[MethodImpl(MethodImplOptions.AggressiveInlining)]
在这里几乎什么也做不了。当您想告诉编译器只需将代码复制并粘贴到多个地方以避免不必要的方法调用时,就会使用内联。在大多数情况下,知道什么时候自己做是非常聪明的。
var operands = input.Split(' ');
导致 JIT 遍历整个字符串、进行搜索、拆分字符串并填充数组,这可能需要很长时间。
开关(操作数[j])
在字符串上切换也会产生影响,因为它必须在 case 上调用 equals。如果您关注性能(例如 char),您会希望在 switch 中使用简单类型。
int.Parse
这实际上做了一堆分配,甚至处理了不安全的代码。您可以在此处查看解析代码:
https://referencesource.microsoft.com/#mscorlib/system/number.cs,698
或者如果链接断开:
[System.Security.SecuritySafeCritical] // auto-generated
internal unsafe static Int32 ParseInt32(String s, NumberStyles style, NumberFormatInfo info) {
Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
NumberBuffer number = new NumberBuffer(numberBufferBytes);
Int32 i = 0;
StringToNumber(s, style, ref number, info, false);
if ((style & NumberStyles.AllowHexSpecifier) != 0) {
if (!HexNumberToInt32(ref number, ref i)) {
throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
}
else {
if (!NumberToInt32(ref number, ref i)) {
throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
}
return i;
}
[System.Security.SecuritySafeCritical] // auto-generated
private unsafe static void StringToNumber(String str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, Boolean parseDecimal) {
if (str == null) {
throw new ArgumentNullException("String");
}
Contract.EndContractBlock();
Contract.Assert(info != null, "");
fixed (char* stringPointer = str) {
char * p = stringPointer;
if (!ParseNumber(ref p, options, ref number, null, info , parseDecimal)
|| (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer)))) {
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
}
}
}
关于c# - 这段代码需要太长时间的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49534226/
在我们的服务出现一些预期的增长之后,突然间一些更新花费了非常长的时间,这些过去非常快,直到表达到大约 2MM 记录,现在它们每个需要大约 40-60 秒。 update table1 set fiel
我在服务中实现了一个传感器事件监听器,只要采样周期和最大报告延迟低于 1 秒,该监听器就可以正常工作,但一旦我将采样周期增加到超过 1 秒,传感器就根本不会更新。 我希望采样周期为 10 秒(可能是
我使用 Tkinter GUI 来启动测量和分析过程,基本上只需单击一个按钮即可开始。由于这些测量可能需要一段时间,我尝试添加一个进度条,即这个: http://tkinter.unpythonic.
我正在尝试使用套接字发送数据包,但出现错误。 invalid conversion from ‘omnetpp::cPacket*’ to ‘inet::Packet*’ [-fpermissive]
我刚刚发现 String#split 有以下奇怪的行为: "a\tb c\nd".split => ["a", "b", "c", "d"] "a\tb c\nd".split(' ') => ["a
您好,我正在尝试 ClojureScript,我正在使用 Klipse作为我的 REPL 差不多。这可能不是它的预期用途,但因为我没有做任何太复杂的事情,所以现在没问题。 我遇到的一个问题是尝试设置计
根据下面的数据,ClockKit 会生成一次 future 的 CLKComplicationTimelineEntry 项,但对于过去的时间点,会进行 24 次调用!这是为什么? 更多详情: 我注意
我有一个 MySQL 表,这个表有一个名为 datetime_utc 的 DATETIME 列。如您所料,它是 UTC 日期和时间。在我的 Bookshelf 模型中,我定义了一个虚拟 getter,
大家好,我是二哥呀! 昨天,一位球友问我能不能给他解释一下 @SpringBootApplication 注解是什么意思,还有 Spring Boot 的运行原理,于是我就带着他扒拉了一下这个注解的源
我是一名优秀的程序员,十分优秀!