Сколько еще дорогой Исключение, чем возвращаемое значение?

Во-первых, если пользователи Вашего API не интересуются определенными, мелкомодульными отказами, то наличие определенных исключений для них не имеет ценности.

, Так как часто не возможно знать то, что может быть полезно для Ваших пользователей, лучший подход должен иметь определенные исключения, но гарантировать, чтобы они наследовались общему классу (например, станд.:: исключение или его производные в C++). Это позволяет Вашему клиенту ловить определенные исключения, если они выбирают, или более общее исключение, если они не заботятся.

17
задан Dana the Sane 15 August 2009 в 17:04
поделиться

10 ответов

Throwing an exception is definitely more expensive than returning a value. But in terms of raw cost it's hard to say how much more expensive an exception is.

When deciding on a return value vs. an exception you should always consider the following rule.

Only use exceptions for exceptional circumstances

They shouldn't ever be used for general control flow.

24
ответ дан 30 November 2019 в 10:12
поделиться

You can find a lot of useful information about this in the answers to this question, including one answer with 45 up-votes How slow are .net exceptions?

4
ответ дан 30 November 2019 в 10:12
поделиться

Использование возврата ошибок будет намного дороже, чем исключения - как только фрагмент кода забудет проверить возврат ошибки или не сможет его воспроизвести.

Тем не менее, убедитесь, что это не так. используйте исключения для потока управления - используйте их только для указания того, что что-то пошло не так.

3
ответ дан 30 November 2019 в 10:12
поделиться

В недавнем анализе производительности реальной работы мы обнаружили, что тонны исключений на младших компьютерах оказали критическое влияние на производительность приложений, так что мы посвятили несколько недель тому, чтобы пройти через и скорректировать код, чтобы не бросать так много.

Когда я говорю о критическом эффекте, это было примерно на уровне увеличения двухъядерного ЦП до 95% на одном ядре ЦП, которое использовало приложение.

1
ответ дан 30 November 2019 в 10:12
поделиться

У меня сейчас проблемы с поиском документов, подтверждающих это, но имейте в виду, что когда вы генерируете исключение, C # должен генерировать трассировку стека с того места, где вы его вызывали. . Трассы стека (и отражение в целом) далеко не бесплатны.

2
ответ дан 30 November 2019 в 10:12
поделиться

Вы должны предпочесть исключения кодам ошибок и состояниям ошибок, но не используйте исключения для нормального выполнения программы.

Исключения чрезвычайно важны по сравнению с обычным рабочим процессом, I ' мы видели огромное снижение производительности приложений при использовании блока try-catch.

1
ответ дан 30 November 2019 в 10:12
поделиться

Throwing an exception is a relatively inexpensive operation. It's catching them that incurrs the cost because of the stack walks that must occur to find the catch handlers, execute the code in the catch handlers, find the finally blocks, execute the code in the finally blocks, and then return to the original caller.

It is strongly recommended that you don't use exceptions for control flow. Using return codes to indicate errors gets expensive from a "time and materials" perspective as it will eventually incur maintenance costs.

All of that aside, your two examples don't match nor are they even valid. Since you are return b, which is of type Bar, your first method should probably be:

public Bar Foo(Bar b)
{
   if(b.Success)
   {
      return b;
   }
   else
   {
      throw n.Exception;
   }
}

which could be rewritten as:

public Bar Foo(Bar b)
{
   if (!b.Success)
      throw n.Exception;

   return b;
}
1
ответ дан 30 November 2019 в 10:12
поделиться

Обычно я избегал этого из-за дорогостоящего характера перехвата исключения. Это может быть неплохо, если такое случается нечасто.

Однако почему бы просто не вернуть null? Затем он становится таким:

public Foo Bar(Bar b)
{
   if(b.Success)
   {
      return b;
   }
   else
   {
      return null;
   }
}

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

1
ответ дан 30 November 2019 в 10:12
поделиться

Exception have two costs: warm-up to page in the exception infrastructure - if not in to memory then into the CPU cache - and per-throw cost to gather exception stack, search for exception handler, possibly call exception filters, unwind the stack, calling finalization blocks - all operations that the runtime, by design, does not optimize for.

Thus, measuring the cost of throwing exceptions can be misleading. If you write a loop that iteratively throws and catches an exception, without a lot of work between the throw site and the catch site, the cost won't look that large. However, that's because it's amortizing the warm-up cost of exceptions, and that cost is harder to measure.

Certainly, exceptions don't cost anything like they seem to if one's main experience is exceptions thrown by programs under the debugger. But they do cost, and it's advisable to design libraries in particular such that exceptions can be avoided where necessary for optimization.

7
ответ дан 30 November 2019 в 10:12
поделиться

Используя приведенный ниже код, тестирование показало, что вызов + возврат без исключений занимал около 1,6 микросекунд на итерацию, тогда как исключения (выброс плюс улов) добавляли около 4000 микросекунд. (!)

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        DateTime start = DateTime.Now;
        bool PreCheck = chkPrecheck.Checked;
        bool NoThrow = chkNoThrow.Checked;
        int divisor = (chkZero.Checked ? 0 : 1);
        int Iterations =  Convert.ToInt32(txtIterations.Text);
        int i = 0;
        ExceptionTest x = new ExceptionTest();
        int r = -2;
        int stat = 0;

        for(i=0; i < Iterations; i++)
        {
            try
            {
                r = x.TryDivide(divisor, PreCheck, NoThrow);
            }
            catch
            {
                stat = -3;
            }

        }

        DateTime stop = DateTime.Now;
        TimeSpan elapsed = stop - start;
        txtTime.Text = elapsed.TotalMilliseconds.ToString();

        txtReturn.Text = r.ToString();
        txtStatus.Text = stat.ToString();

    }
}



class ExceptionTest
{
    public int TryDivide(int quotient, bool precheck, bool nothrow)
    {
        if (precheck)
        {
            if (quotient == 0)
            {
                if (nothrow)
                {
                    return -9;
                }
                else
                {
                    throw new DivideByZeroException();
                }

            }
        }
        else
        {
            try
            {
                int a;
                a = 1 / quotient;
                return a;
            }
            catch
            {
                if (nothrow)
                {
                    return -9;
                }
                else
                {
                    throw;
                }
            }
        }
        return -1;
    }
}

Так что да, исключения стоят ОЧЕНЬ дорого.

И прежде, чем кто-то это скажет, ДА, я тестировал это в режиме Release , а не только ] Режим отладки . Попробуйте выполнить код самостоятельно и посмотрите, будут ли результаты существенно отличаться.

21
ответ дан 30 November 2019 в 10:12
поделиться
Другие вопросы по тегам:

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