gpt4 book ai didi

c# - 这段代码需要太长时间的原因是什么?

转载 作者:行者123 更新时间:2023-11-30 15:54:46 25 4
gpt4 key购买 nike

试图解决另一个 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 , forint.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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com