powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Что за странная оптимизация стектрейса исключения?
5 сообщений из 5, страница 1 из 1
Что за странная оптимизация стектрейса исключения?
    #39287284
WinterGraveyard
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеем вот такой код:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
class Program
{
  static void Main()
  {
    try
    {
      new Program().Foo();
    }
    catch (Exception e)
    {
      Console.WriteLine("{0}", e.StackTrace);
    }
  }

  void Foo()
  {
    Bar();
  }

  void Bar()
  {
    Zot();
  }

  void Zot()
  {
    throw new ApplicationException();
  }
}


Компилируем, и запускаем из командной строки. Получаем:

Код: plaintext
в test2.Program.Main() в D:\Trash\test2\Program.cs:строка 11

- в стектрейсе только точка вызова в Main (из командной строки - потому что в студии стектрейс всегда будет полным).
Хорошо, предполагаем, что компилятор оптимизарует вызовы, и выкидывает методы, которые в себе содержат только вызовы другого метода. Переписываем так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
class Program
{
  static void Main()
  {
    try
    {
      new Program().Foo();
    }
    catch (Exception e)
    {
      Console.WriteLine("{0}", e.StackTrace);
    }
  }

  int _i;
  void Foo()
  {
    Bar();
    _i++;
  }

  void Bar()
  {
    Zot();
    _i++;
  }

  void Zot()
  {
    _i++;
    throw new ApplicationException();
  }
}


получаем:

Код: plaintext
1.
2.
3.
4.
в test2.Program.Zot()  в D:\Trash\test2\Program.cs:строка 39
в test2.Program.Bar()  в D:\Trash\test2\Program.cs:строка 32
в test2.Program.Foo()  в D:\Trash\test2\Program.cs:строка 26
в test2.Program.Main() в D:\Trash\test2\Program.cs:строка 14

- нормально, стектрейс полный. А теперь возвращаемся к исходному предположению об оптимизации, и на всякий пожарный смотрим IL-код первого варианта:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
.class private auto ansi beforefieldinit test2.Program
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    }

    .method private hidebysig instance void Bar () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void test2.Program::Zot()
        IL_0006: ret
    }

    .method private hidebysig instance void Foo () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void test2.Program::Bar()
        IL_0006: ret
    }

    .method private hidebysig static void Main () cil managed 
    {
        .entrypoint
        .locals init (
            [0] class [mscorlib]System.Exception e
        )

        .try
        {
            IL_0000: newobj instance void test2.Program::.ctor()
            IL_0005: call instance void test2.Program::Foo()
            IL_000a: leave.s IL_001f
        }
        catch [mscorlib]System.Exception
        {
            IL_000c: stloc.0
            IL_000d: ldstr "{0}"
            IL_0012: ldloc.0
            IL_0013: callvirt instance string [mscorlib]System.Exception::get_StackTrace()
            IL_0018: call void [mscorlib]System.Console::WriteLine(string,  object)
            IL_001d: leave.s IL_001f
        }

        IL_001f: ldc.i4.1
        IL_0025: pop
        IL_0026: ret
    }

    .method private hidebysig instance void Zot () cil managed 
    {
        IL_0000: newobj instance void [mscorlib]System.ApplicationException::.ctor()
        IL_0005: throw
    }
}


- никакой оптимизации промежуточных вызовов нет, все методы на месте (а компиляция делалась в релизе). Однако факт - первый вариант дает усеченный стектрейс. Почему?
...
Рейтинг: 0 / 0
Что за странная оптимизация стектрейса исключения?
    #39287336
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WinterGraveyardникакой оптимизации промежуточных вызовов нет, все методы на месте
а Jit компилятор как отработал?
...
Рейтинг: 0 / 0
Что за странная оптимизация стектрейса исключения?
    #39287398
WinterGraveyard
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропила Jit компилятор как отработал?
Упс. А про него-то я и не подумал. Задизейблил JIT-оптимизацию, и стектрейс стал полным. Спасибо.
...
Рейтинг: 0 / 0
Что за странная оптимизация стектрейса исключения?
    #39287414
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WinterGraveyardИзопропила Jit компилятор как отработал?
Упс. А про него-то я и не подумал. Задизейблил JIT-оптимизацию, и стектрейс стал полным. Спасибо.
JIT оптимизацию ты не задизеблишь! Ты снял галочку "Оптимизировать код" или как там по англицки.
С ней.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
.method private hidebysig static 
	void Main () cil managed 
{
	// Method begins at RVA 0x2050
	// Code size 32 (0x20)
	.maxstack 2
	.entrypoint
	.locals init (
		[0] class [mscorlib]System.Exception e
	)

	.try
	{
		IL_0000: newobj instance void ConsoleApplication3.MainApp::.ctor()
		IL_0005: call instance void ConsoleApplication3.MainApp::Foo()
		IL_000a: leave.s IL_001f
	} // end .try
	catch [mscorlib]System.Exception
	{
		IL_000c: stloc.0
		IL_000d: ldstr "{0}"
		IL_0012: ldloc.0
		IL_0013: callvirt instance string [mscorlib]System.Exception::get_StackTrace()
		IL_0018: call void [mscorlib]System.Console::WriteLine(string, object)
		IL_001d: leave.s IL_001f
	} // end handler

	IL_001f: ret
} // end of method MainApp::Main


без ней
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
.method private hidebysig static 
	void Main () cil managed 
{
	// Method begins at RVA 0x2050
	// Code size 39 (0x27)
	.maxstack 2
	.entrypoint
	.locals init (
		[0] class [mscorlib]System.Exception e
	)

	IL_0000: nop
	.try
	{
		IL_0001: nop
		IL_0002: newobj instance void ConsoleApplication3.MainApp::.ctor()
		IL_0007: call instance void ConsoleApplication3.MainApp::Foo()
		IL_000c: nop
		IL_000d: nop
		IL_000e: leave.s IL_0026
	} // end .try
	catch [mscorlib]System.Exception
	{
		IL_0010: stloc.0
		IL_0011: nop
		IL_0012: ldstr "{0}"
		IL_0017: ldloc.0
		IL_0018: callvirt instance string [mscorlib]System.Exception::get_StackTrace()
		IL_001d: call void [mscorlib]System.Console::WriteLine(string, object)
		IL_0022: nop
		IL_0023: nop
		IL_0024: leave.s IL_0026
	} // end handler

	IL_0026: ret
} // end of method MainApp::Main


Особо ниче не поменялось, но JIT`у хватило...

https://blogs.msdn.microsoft.com/ruericlippert/2009/06/10/optimize/
...
Рейтинг: 0 / 0
Что за странная оптимизация стектрейса исключения?
    #39287415
WinterGraveyard
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЕвгенийВJIT оптимизацию ты не задизеблишь! Ты снял галочку "Оптимизировать код" или как там по англицки.
Зуб даете?
Вообще-то я имел в виду (и сделал) вот это: https://msdn.microsoft.com/en-us/library/9dd8z24x.aspx - и это дало результат, что характерно. Без перекомпиляции проекта и манипуляций с флагами компилятора.
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Что за странная оптимизация стектрейса исключения?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]