Почему не делает.NET/C#, оптимизируют для рекурсии последнего вызова?

Что мне здесь не хватает? Я уверен, что мы можем указать область, где стек создается в шаблоне CFN, используя параметры, и у нас есть активные шаблоны, которые создают наш стек в соответствующей области на основе значения параметра. Псевдопараметр AWS :: Region - это значение, которое AWS CloudFormation разрешает как область, в которой создается стек. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html

Вот подраздел примера шаблона

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "InstanceType": {
      "Description": "Instance Type",
      "Type": "String",
      "Default": "t2.xlarge"
    },
    "SubnetUSEAST1": {
      "Description": "Subnet on which Ec2 instance needs to be created",
      "Type": "String",
      "Default": "subnet-xxxxxxxx"
    },
    "SubnetUSWEST2": {
      "Description": "Subnet on which Ec2 instance needs to be created",
      "Type": "String",
      "Default": "subnet-yyyyyyyy"
    }
  },
  "Conditions": {
    "useast1": {
      "Fn::Equals": [
        {
          "Ref": "AWS::Region"
        },
        "us-east-1"
      ]
    },
    "uswest2": {
      "Fn::Equals": [
        {
          "Ref": "AWS::Region"
        },
        "us-west-2"
      ]
    }
  },
  "Resources": {
    "EC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "InstanceType": {
          "Ref": "InstanceType"
        },
        "NetworkInterfaces": [
          {
            "SubnetId": {
              "Fn::If": [
                "useast1",
                {
                  "Ref": "SubnetUSEAST1"
                },
                {
                  "Ref": "SubnetUSWEST2"
                }
              ]
            },
            "AssociatePublicIpAddress": "false",
            "DeviceIndex": "0"
          }
        ]
      }
    }
  }
}

102
задан Community 23 May 2017 в 12:17
поделиться

3 ответа

JIT-компиляция является хитрым уравновешиванием между не пребыванием в течение слишком большого количества времени, делая фазу компиляции (таким образом замедляющий недолгие приложения значительно) по сравнению с не выполнением достаточного анализа для хранения приложения конкурентоспособным в долгосрочной перспективе по отношению к стандарту заранее компиляция.

Интересно NGen шаги компиляции не предназначены к тому, чтобы быть более агрессивным в их оптимизации. Я подозреваю, что это вызвано тем, что они просто не хотят иметь ошибки, где поведение зависит от того, были ли JIT или NGen ответственны за машинный код.

сам CLR поддерживает оптимизацию последнего вызова, но определенный для языка компилятор должен знать, как генерировать соответствующее , код операции и JIT должны быть готовы уважать его. F# fsc генерирует соответствующие коды операций (хотя для простой рекурсии он может просто преобразовать все это в while цикл непосредственно). csc C# не делает.

См. это сообщение в блоге для некоторых деталей (вполне возможно теперь устаревший данный недавние изменения JIT). Обратите внимание, что изменения CLR для 4,0 x86, x64 и ia64 будут уважать его .

80
ответ дан Peter Mortensen 24 November 2019 в 04:32
поделиться

Этот представление обратной связи Microsoft Connect должно ответить на Ваш вопрос. Это содержит официальный ответ от Microsoft, таким образом, я рекомендовал бы идти этим.

спасибо за предложение. Мы рассмотрели испускающие инструкции по последнему вызову в ряду вопросов в разработке компилятора C#. Однако существуют некоторые тонкие проблемы, которые продвинули нас избегать этого до сих пор: 1) Существуют на самом деле нетривиальные накладные расходы к использованию .tail инструкции в CLR (это не просто команда перехода, поскольку последние вызовы в конечном счете становятся во многих менее строгих средах, таких как функциональные среды выполнения языка, где последние вызовы в большой степени оптимизированы). 2) Существует немного реальных методов C#, где было бы законно испустить последние вызовы (другие языки поощряют кодировать шаблоны, которые имеют больше хвостовой рекурсии и многих, которые полагаются в большой степени на оптимизацию последнего вызова, на самом деле делают глобальную перезапись (такую как Продолжение Передающие преобразования) для увеличения количества хвостовой рекурсии). 3) Частично из-за 2), случаи, где переполнение стека методов C# из-за глубокой рекурсии, которая должна была успешно выполниться, довольно редки.

Однако мы продолжаем смотреть на это и нас, май в будущем релизе компилятора находит некоторые шаблоны, где имеет смысл испускать .tail инструкции.

Между прочим, как на это указали, стоит отметить, что хвостовая рекурсия оптимизирована на x64.

73
ответ дан Ahmed Abdelhameed 24 November 2019 в 04:32
поделиться

Мне недавно сказали, что компилятор C# для 64 битов действительно оптимизирует хвостовую рекурсию.

C# также реализует это. Причина, почему это не всегда применяется, состоит в том, что правила, используемые для применения хвостовой рекурсии, очень строги.

8
ответ дан Peter Mortensen 24 November 2019 в 04:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: