Compile-debug и в продакшн!


Делаем в >29.08.2014, 06:11. Просмотров 3464. Ответов 3

Делаем в IDE FASM’a кнопку Debug и дружим его с OllyDbg

статья была взята здесь

Статья посвящена всем любителям компилятора FASM и тем кто пишет код используя его IDE.

Известно что любое написание кода, особенно на ассемблере, не обходится без его отладки. Иначе, как искать ошибки и вообще тестировать своё творение?

Для отладки программ использую легендарный отладчик OllyDbg. Не буду тут описывать его возможности и все преимущества, те, кто в теме, и знаком с этим замечательным дебаггером, знают всё сами.

Итак, однажды, мне в голову пришла идея встроить в IDE FASM’a отладчик OllyDbg, так чтоб скомпилированная программа одним кликом запускалась в «Ольке».

Зачем и почему я это затеял?

Ну, наверно, из-за того, что я очень ленив и мне надоело делать лишние движения

  1. Скомпилировать
  2. открыть файл с программой
  3. загрузить его в отладчик

Куда проще ― кликнуть одну кнопку и код автоматически компилируется и автоматически загрузится в отладчик.

На самом деле причина даже не в лени, а в удобстве.

Можно было бы не парится с этой интеграцией и использовать, например, BAT-файлы или скрипт на VBS, но, опять же, это нужно постоянно создавать, править файлы и т.д. и т.п. Лично мне такое решение не подходит ― слишком много ненужных движений.

Ближе к делу. Фактически ― всё, что нам нужно для того, чтобы встроить в IDE FASM’a отладчик OllyDbg ― это добавить в FASMW всего одну кнопку. Debug например. Ну и, соответственно, привязать некое действие к этой кнопке (обработчик).

Известно, что отладчик OllyDbg может принимать параметры при запуске. Например, вот так можно загрузить программу test.exe для отладки:

и загружает для отладки файл test.exe, естественно, если он существует.

Запустить OLLYDBG.EXE с параметрами из своей программы можно воспользовавшись например функцией ShellExecute.

На FASM’e это будет выглядеть так:

Нечто подобное нам и нужно встроить в IDE FASMW.

Приступаем к операции. Открываем сорцы фасма, конкретно нам нужен файл FASMW.ASM именно его нам предстоит немного дополнить. Файл FASMW.ASM находится в директории \SOURCE\ >

Судя по всему Автор FASM’a предусмотрел что нам может понадобится кнопочка Debug) Раскомментируем эту строку убрав знак «;». Теперь если скомпилировать этот отредактированный исходник и запустить получившийся FASMW.EXE ( >

Assembler

Тем самым каждый раз при запуске FASMW будет читать свои файл конфигураций FASMW.INI, брать оттуда путь к отладчику и помещать его в тот самый буфер debugger rb 1000h

Всё это нужно для функции ShellExecute которую мы вписали выше.

Assembler
29.08.2014, 06:11

Программа на fasm + ollydbg
Скомпилировал программу на fasm, далее загрузил в олли, вот ассемблерный код — 00401000 > $ 6A 00.

Fasm + linux + ide
Господа! В данный момент приходится кодить на fasm под Linux (Debian). Хотелось бы узнать ваше.

Делаем кнопку из компонета Image
Всем ПРИВЕТ! С помощью ниже описанного кода можно сделать из компонента Image кнопку с анимацией.

Создание debug-режима в своей ide
Как это можно реализовать? Ясно, что надо в рантайме заменить кусочек памяти, занимаемый.

18.02.2015, 14:09 2

Осталось прикрутить отладочную инфу, генерируемую FASM`ом к Olly.

Добавлено через 5 минут
Конвертер вроде бы уже написан

25.02.2020, 12:24 3

connect fasm with VS2005 В этой теме есть ссылка на архив с утилитой pecvt.exe, добавляющую отладочную информацию в obj-файл.

В сорце конвертера нет 2-х заголовочных файлов и соответств. файлов с кодом.

28.08.2020, 14:32 4
28.08.2020, 14:32
28.08.2020, 14:32

Подключение плагина OllyDbg v2.01: Отладчик его не распознает
Подключаю плагин, который использовался в OllyDbg v1.01. Отладчик его не распознает. Есть ли.

linux+avr+asm+debug=IDE под linux
Здравствуйте! Допрашиваю Гошу с пристрастием уже два дня. Хочется аналог AVR Studyo под линукс.

Compile-debug и в продакшн!

We recommend upgrading to the latest Google Chrome or Firefox.

Join GitHub today

GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.

rocksdb / INSTALL.md

Users who have contributed to this file

Important: If you plan to run RocksDB in production, don’t compile using default make or make all . That will compile RocksDB in debug mode, which is much slower than release mode.

RocksDB’s library should be able to compile without any dependency installed, although we recommend installing some compression libraries (see below). We do depend on newer gcc/clang with C++11 support.

There are few options when compiling RocksDB:

[recommended] make static_lib will compile librocksdb.a, RocksDB static library. Compiles static library in release mode.

make shared_lib will compile librocksdb.so, RocksDB shared library. Compiles shared library in release mode.

make check will compile and run all the unit tests. make check will compile RocksDB in debug mode.

make all will compile our static library, and all our tools and unit tests. Our tools depend on gflags. You will need to have gflags installed to run make all . This will compile RocksDB in debug mode. Don’t use binaries compiled by make all in production.

By default the binary we produce is optimized for the platform you’re compiling on ( -march=native or the equivalent). SSE4.2 will thus be enabled automatically if your CPU supports it. To print a warning if your CPU does not support SSE4.2, build with USE_SSE=1 make static_lib or, if using CMake, cmake -DFORCE_SSE42=ON . If you want to build a portable binary, add PORTABLE=1 before your make commands, like this: PORTABLE=1 make static_lib .

You can link RocksDB with following compression libraries:

  • zlib — a library for data compression.
  • bzip2 — a library for data compression.
  • lz4 — a library for extremely fast data compression.
  • snappy — a library for fast data compression.
  • zstandard — Fast real-time compression algorithm.

All our tools depend on:


  • gflags — a library that handles command line flags processing. You can compile rocksdb library even if you don’t have gflags installed.

If you wish to build the RocksJava static target, then cmake is required for building Snappy.

Linux — Ubuntu

  • Upgrade your gcc to version at least 4.8 to get C++11 support.
  • Install gflags. First, try: sudo apt-get install libgflags-dev If this doesn’t work and you’re using Ubuntu, here’s a nice tutorial: (http://askubuntu.com/questions/312173/installing-gflags-12-04)
  • Install snappy. This is usually as easy as: sudo apt-get install libsnappy-dev .
  • Install zlib. Try: sudo apt-get install zlib1g-dev .
  • Install bzip2: sudo apt-get install libbz2-dev .
  • Install lz4: sudo apt-get install liblz4-dev .
  • Install zstandard: sudo apt-get install libzstd-dev .

Linux — CentOS / RHEL

Upgrade your gcc to version at least 4.8 to get C++11 support: yum install gcc48-c++

Notice: Once installed, please add the include path for gflags to your CPATH environment variable and the lib path to LIBRARY_PATH . If installed with default settings, the include path will be /usr/local/include and the lib path will be /usr/local/lib .

Install ASAN (optional for debugging):

OS X:

  • Install latest C++ compiler that supports C++ 11:
    • Update XCode: run xcode-select —install (or install it from XCode App’s settting).
    • Install via homebrew.
      • If you’re first time developer in MacOS, you still need to run: xcode-select —install in your command line.
      • run brew tap homebrew/versions; brew install gcc48 —use-llvm to install gcc 4.8 (or higher).
  • run brew install rocksdb

FreeBSD (11.01):

You can either install RocksDB from the Ports system using cd /usr/ports/databases/rocksdb && make install , or you can follow the details below to install dependencies and compile from source code:

Install the dependencies for RocksDB:

export BATCH=YES cd /usr/ports/devel/gmake && make install cd /usr/ports/devel/gflags && make install

cd /usr/ports/archivers/snappy && make install cd /usr/ports/archivers/bzip2 && make install cd /usr/ports/archivers/liblz4 && make install cd /usr/ports/archivesrs/zstd && make install

cd /usr/ports/devel/git && make install

Install the dependencies for RocksJava (optional):

export BATCH=yes cd /usr/ports/java/openjdk7 && make install

Build RocksDB from source: cd

Build RocksJava from source (optional): cd rocksdb export JAVA_HOME=/usr/local/openjdk7 gmake rocksdbjava

OpenBSD (6.3/-current):

As RocksDB is not available in the ports yet you have to build it on your own:

Install the dependencies for RocksDB:

pkg_add gmake gflags snappy bzip2 lz4 zstd git jdk bash findutils gnuwatch

Build RocksDB from source:

Build RocksJava from source (optional):

cd rocksdb export JAVA_HOME=/usr/local/jdk-1.8.0 export PATH=$PATH:/usr/local/jdk-1.8.0/bin gmake rocksdbjava

iOS:

  • Run: TARGET_OS=IOS make static_lib . When building the project which uses rocksdb iOS library, make sure to define two important pre-processing macros: ROCKSDB_LITE and IOS_CROSS_COMPILE .

Improve your productivity by using the debugger in Rational Developer for Power Systems Software

IBM® Rational® Developer for Power Systems Software™ provides integrated development and debugging tools for IBM® AIX®, IBM® PowerLinux™, or IBM i. It helps developers create and maintain applications on IBM Power Systems™ with rich source-editing features, visual design and analysis tools, integrated search and compile error feedback, and remote debugging based on Eclipse.

The integrated debugger is an interactive, source-level graphical debugger. It works on Microsoft Windows and Linux-based workstations connected remotely to a debugger engine running on either AIX or PowerLinux.

The integrated debugger enables you to debug programs written in C, C++, and COBOL. Using the integrated debugger, you can diagnose problems quicker as you deepen your understanding of your own program.

We use C/C++ on AIX to describe the features of the integrated debugger in this article.

Starting a debug session

This section describes how to prepare your program for debugging and how to launch a debug session by using the Remote System Explorer. We also introduce the basic debug features, such as setting breakpoints, stepping through your program, displaying variables, and monitoring expressions.

Compile the program with debug information

To debug your program at source code level, you need to compile your program with certain compiler options that instruct the compiler to generate debug information in the object files. For the IBM XL C/C++ compiler Enterprise Edition for AIX, compile with the -g option.

Set up the Remote System Explorer

To debug a remote application on AIX or Power Linux, set up a remote system connection first. You can do this through the Remote System Explorer perspective. As an example, we will describe how to set up a remote connection to an AIX host.

  1. From the Remote Systems navigator, double click New Connection > AIX, to open a New Connection dialog window.
  2. Enter the AIX host name. You can also modify the connection configuration at the Next page.
  3. A new node is created in the navigator after you click the OK button.
Figure 1. Creating a connection to a remote AIX system

You can expand the Files > My Home tree to browse the files under your home directory or the Files > Root tree to browse from the root directory. It might prompt you for the user ID and password when making the remote connection. When you enter the password, you can check the Save Password check box so that you do not have to enter the password again.

Launch a debug session

After creating a remote connection from the Remote Systems Explorer, you can start to debug a remote application from the Remote Systems navigator.

  1. Expand the remote file system tree to expose the remote executable file that you compiled with debug information.
  2. Right-click the remote file, and select Debug > Remote Application.


This will start a debug session on the remote executable. If you want to configure the launching parameters, you can select the Debug > Remote Application. action to open the launch configuration dialog window. You can modify the following debug startup parameters in that view:

  • If the Automatically stop at the first executable line of main method option is selected, the debugger will automatically stop at the first line of the main method.
  • You can enter the program arguments from the Arguments tab
  • You can enable the Production Debug feature from the Advanced tab.

You can also attach to a running process using the debugger. To do this, expand the Processes > My Processes tree from the Remote Systems navigator, right-click the process that you want to attach, and select Attach > Process.

Using the IBM debugger

After launching a debug session, you would normally debug it from the Debug perspective. The following screen capture shows the UI for a debug session in the Debug perspective.

Figure 2. The Debug perspective

The debugger displays a lot of information, and it is grouped into different sections called views. The sections that follow describe those that are most relevant to various debugging-related tasks.

The view that you will probably use the most is the Debug view, which is the main control center for your debug session. In addition to the Debug view, the UI contains several other views for displaying special information, including the Breakpoints, Variables, and Monitors views and, for advanced debugging, Modules, Memory, and Registers views. The icons in each view’s toolbar provide additional useful actions, and you can hover your mouse cursor over each of them to display a tool tip that describes the action. To learn more, experiment with each of them.

Debug view

The Debug view is the starting point for any debug session. For each process under Debug, the view displays all of the running threads. In turn, for each suspended thread, a list of stack frames is visible, representing the call hierarchy. Also, the source file currently being debugged is displayed in the Source editor. When a debug session is selected, it is considered the active debug context. Other debug views show content based on the current active debug context. Selecting a debug session automatically updates other debug views to show the matching content.

Set breakpoints

The Breakpoints view is the central location for controlling breakpoints. You can always see a list of breakpoints that you have set in the Breakpoints view, and you can add a new breakpoint by right-clicking in the view and selecting one of the entries from the Add Breakpoint submenu. You can also set a source line breakpoint from the annotation column of the editor. In the Breakpoints view, enabled breakpoints have a check mark beside them. You can enable and disable breakpoints by checking or clearing that box.

Step through your program

You can step through your program by using the Step Into, Step Over, and Step Return toolbar buttons. These commands are also available from the Run menu or by using the keyboard shortcuts: F5, F6, and F7, respectively. If you direct the program to run (F8), execution will resume until it hits a breakpoint, the program terminates, or an exception occurs.

You can use the Animated Step Into action to perform repeated step into your program. The animation pace can be set directly on the animated step icon or from the Preferences page. The default pace is 2 seconds.

Examining variables

The Variables view lists in-scope variables each time a thread or program stops.

After every program stop, changes to in-scope variables will be highlighted in the Variables view. There are several actions available, which you can see by right-clicking anywhere inside this view to bring up the context menu.

You can change variable values here. If you edit a variable from the Variables view, the new value becomes effective immediately. You can also change the representation of a variable. For example, to display an integer in binary format instead of the default decimal, use the Change representation context menu of a selected variable.

Monitors

You can use the Monitors view to monitor a collection of variables and expressions of interest, for easy access and modification. The values of the monitored variables or expressions are updated each time the program stops. If a variable is out of scope, its value will not be displayed until it comes back into scope. This is especially useful for observing global variables as they change throughout your debug session. You can monitor any valid expression, such as a simple local variable, to a particular index in an array.

Getting help

The debugger UI is built on the Eclipse open development platform, so it benefits from that advanced help system. For example, hovering your cursor over a tool bar button produces a tool tip, and pressing F1 brings up the context-sensitive help for the current view or the currently selected menu action.

You can use one of the following ways to monitor a new expression:

  • Right-click inside the Monitors view, and select Monitor Expression. Enter the expression that you want to monitor in the dialog window that opens.
  • Select an expression from the source editor, and then select the Monitor Expression action from the context menu.
  • Right-click a variable from the Variables view, and select Monitor Local Variable.

Using advanced debugging techniques

Breakpoint conditions

Sometimes a piece of code is called many times, even from different threads, but you want to stop in that code only if a particular condition is met. This is where the Optional parameters page of the breakpoint wizard is very useful.

  1. Right-click a breakpoint in the Breakpoints view, and choose Edit to invoke the Edit Breakpoint wizard.
  2. Then click the Next button to go to the «Optional parameters» page, where you can specify how you want to handle these situations.

You can select the thread on which you wish to stop, the frequency of suspension, and even define a Boolean expression that must be true before suspending. You may also have multiple conditional breakpoints at the same location, and they can be easily enabled and disabled from the Breakpoints view.

Figure 3. The breakpoint conditions page

Modules view

The Modules view displays all of the loaded modules for the debugged program. By default, only modules with debug information are displayed. You can clear the Show Modules with Debug Information toolbar button to also show the modules without debug information.

You can expand each module to show the compilation units, source files, and functions that it contains. You can double-click a source file or function to open it in the source code editor. You can also set an entry breakpoint on a function from the context menu.

Figure 4. The Modules view

Memory view

The Memory view enables you to examine and modify the contents of memory at a specific address, usually that of a variable. You can also choose which format the memory will be displayed in, such as hex, ASCII, EBCDIC, signed integer, or unsigned integer. The address of the expression used as the base memory is called a memory monitor, and you can use the Monitors pane in the Memory view to add and remove memory monitors.

Note:
Memory monitors are different from the monitors used in the Monitors view described in the preceding section.

Figure 5. The Memory view

Display registers

You can display and modify the contents of various registers by using the Registers view. The registers are logically grouped in the view. The Registers view is similar to the Variables view in that it indicates register changes by highlighting the changed items. You can add registers to the Monitors view and monitor them for changes. In addition, if a register’s value is a memory address, you can monitor it by using the Memory view.

Figure 6. The Registers view

Debug console

You can use the debug console to send debug commands to the debug engine. You can issue commands directly to the debug engine and view the resulting output in the debug console, which helps enable a fairly interactive debug. The commands supported are debug engine-dependent, and you can display them by typing help in the debug console.

In Figure 7, the commands list pane is on the right. It lists all of the commands that have been entered. The commands history pane on the left displays the output from entered commands. You can use the toolbar buttons to clear the commands history and list panes, import, export, and run lists of commands.

Figure 7. The debug console

Debug a client/server application

You can use the Rational Developer for Power Systems Software debugger to debug your client/server application. For example, if the client side of your application is written in Java and running on Windows or Linux, and the server side of your application is written in C/C++ and running on an AIX system, you can use the Java debugger to debug the Java front end and use the complied language debugger to debug the C/C++ back end. You can step through both programs to see how they interact with each other.

Source visualization

The debugger provides three different source visualization options:

  • Source view, which shows the default application’s source code
  • Disassembly view, which displays the instruction codes
  • Mixed view, which includes both source and instruction codes

You can choose the views by right-clicking in the editor view and choosing Switch View.


Figure 8. Different source visualization views

Debugging a core dump

The integrated debugger for IBM Power provides a post-mortem debugging feature that allows the user to debug a core file generated by a running executable file. An executable can generate a core dump when it runs into a segmentation fault, which can be caused by a null pointer reference.

To debug a core dump, just select the core file from the Remote Systems navigator, right-click, and select Debug Post-Mortem > Core File. The debug session started from the core dump will automatically stop at the stack frames where the core dump happens. You can examine the variables from the Variables view to find out what triggers the core dump.

Production Debug

The integrated debugger for Power provides a Production Debug feature that you can use to debug a production binary file, using the debug information from another binary. Under this scenario, you would create a binary with debug information by using the -g compilation flag and then create a production binary by stripping away the debug information from the debuggable binary. The production binary is the one that you send to your customer.

There are cases where you will need to diagnose a problem on the customer’s machine. When this happens, you can copy the debuggable binary to the customer’s machine. Using the Production Debug feature, you can start a debug session on the production binary but use the debug information from the debuggable binary:

  1. From the Advanced tab of the launch configuration dialog window, select Enable production debug.
  2. Add the directory that contains the corresponding debuggable binary to the Debuggable binaries path list. In a production debug scenario, the production binary is still the one running on the machine, but the debug information is retrieved from the debuggable binary, instead.

Production debug can also be enabled by associating a debuggable binary with a loaded module. One use case for production debugging is that the customer ran into a core dump when using the production binary and calls you, the developer, in for assistance. You can debug the core dump by following the procedures in Debugging a core dump. However, because the core dump is produced by the production binary, which does not contain any debug information, the developer cannot debug it at source level. The developer can clear the Show modules with debug information toggle toolbar button to expose the main executable module. Then you can associate a debuggable binary with the main module from the context menu and diagnose the problem at source level.

Team Debug

Team Debug is a feature that allows the transfer of debug sessions between IBM® Rational Team Concert™ team members. Transferring a debug session is useful in team environments where different team members are experts or owners of different components of an application. Sharing debug sessions enables faster problem resolution by allowing the transfer of existing debug sessions without the receiver having to establish the correct environment and start the debug session over again.

During a debug session, a team member can transfer the debug session and its current state to another team member. The transfer includes the current thread states, breakpoints, and monitors. The receiving team member can continue to debug the application after accepting the notification that someone has transferred a debug session. A team member can also park the debug session on the Rational Team Concert server, where the debug session remains in its current state until someone retrieves it from the team repository to continue debugging it.

Code coverage

Rational Developer for Power Systems provides a cross-platform, cross-language code coverage capability. You can use it to see how well your test cases are exercising your compiled language applications by generating statistics that show the percentage of lines in your code that have been run by a test case. The code coverage features are implemented using debug technology.

Using the code coverage tools, you can launch a code coverage session by following steps similar to those for launching a regular debug session. You can see the coverage statistics of all compiled elements in a tree structure from the Code Coverage Report view. Use the Compiled Code Coverage Launch History view to manage all previous launches.

Figure 9. The Code Coverage Report view

Summary

The integrated debugger in Rational Developer for Power Systems Software provides rich debugging capabilities with support for different compiled languages and different platforms. In addition to the basic debug functionality, such as stepping and setting line breakpoints, the tool offers numerous advanced features, including Memory view, multiple breakpoint types, core dump debugging, Production Debug, Team Debug, and code coverage. See the documentation link in Related topics for an in-depth explanation of each topic.

Why debug=false in ASP.NET applications in production environment

Have you ever wondered what harm does the flag Debug=True brings to your application?

Besides hurting your application’s performance in production house, it turns website lifecycle into a vicious circle.

Here is my understanding of using on your application’s web.config file:

When is switched on within the application’s web.config file, it causes a number of non-optimal things to happen including:

1) You will see a lot more files in Temporary ASP.NET files folder when you use debug=true.

2) Your pages will not timeout when you have debug=“true” which is no an ideal production scenario.

3) Batch compilation will be disabled even if the batch attribute is true in the element.

4) The System.Diagnostics.DebuggableAttribute gets added to all generated code which causes performance degradation. Basically, when you have debug=true, the DebuggableAttribute gets added to all generated code.

5) All client-javascript libraries and static images that are deployed via WebResources.axd will be continually downloaded by clients on each page view request and not cached locally within the browser. This can slow down the user experience quite a bit for things like Atlas, controls like TreeView/Menu/Val >

6) When is set, the WebResource.axd handler will automatically set a long cache policy on resources retrieved via it – so that the resource is only downloaded once to the client and cached there forever (it will also be cached on any intermediate proxy servers). If you have Atlas installed for your application, it will also automatically compress the content from the WebResources.axd handler for you when is set – reducing the size of any client-script javascript library or static resource for you (and not requiring you to write any custom code or configure anything within IIS to get it).

7) When the debug attribute in the Web.config file is set to true, it generates symbolic information(.pdb information) every time the compiler compiles your .aspx pages as well as disables code optimization. If the application is not being debugged, you should change this attribute to false.

While the debugger is attached and in break mode, no requests to pages in the application execute. Therefore, you should not debug an application on a production Web server while it is in use.

Only one debugger can be attached to the Aspnet_wp.exe process at a time.

The CLR Debugger only debugs managed code, and it only debugs applications on the computer on which the CLR Debugger is running. If you need to debug remotely or if you need to debug code other than managed code, you should use the Visual Studio .NET debugger.

Now, let’s see how can you turn OFF this flag at the server level ?

As obvious as this, please use the following configuration feature on the machine.config file:

You will disable the switch and this will disable the ability to trace output in a page, and turn off the ability to show detailed error messages remotely. Note that these last two items are security best practices you really want to follow (otherwise hackers can learn a lot more about the internals of your application than you should show them).
For more information on this, please refer: http://msdn.microsoft.com/en-US/library/ms228298(VS.80).aspx

And, now let us see in what scenario you might want to turn on Debug=True:

ASP.NET supports compiling applications in a special debug mode that facilitates developer troubleshooting. Debug mode causes ASP.NET to compile applications with extra information that enables a debugger to closely monitor and control the execution of an application. Applications that are compiled in debug mode execute as expected. However, the performance of the application is affected.
To avo >

Because many parts of an ASP.NET application (such as .aspx, .asmx and .ascx pages) are dynamically compiled at run-time, you need to configure the ASP.NET run-time process to compile the application with symbolic information before the application can be debugged. To do this, set the debug attribute in the configuration section of the Web.config file that is located in the root of the application folder to true, as follows:

Alternatively, you can set the Debug attribute of the Page directive to true in your .aspx pages, as follows:

Let’s do a small exercise to illustrate why do we really need to set debug=true in your application’s configuration.

Add the following code snippet in Page_Load method of Default.aspx of your sample web application. This code will cause a divide-by-zero(as expected) error message whenever you request the page.

protected void Page_Load(Object sender, EventArgs e)
(
int32 i = 0;
i = i/0;
)

Check the output if you have debug=»false» (first) and the same page with debug=»true» (second) in Code above.

Output when debug=»false»
[OverflowException: Arithmetic operation resulted in an overflow.]
_Default.Page_Load(Object sender, EventArgs e) +18
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061
Output when debug=»true»

[OverflowException: Arithmetic operation resulted in an overflow.]
_Default.Page_Load(Object sender, EventArgs e) in C:\My Documents\Visual Studio 2010\WebSites\DebugTrue\Default.aspx.vb:8
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061

Notice that with debug=“true”, you get a more detailed stack output and it even tells you that the problem happened on line number 8 in a page located at C:\My Documents\Visual Studio 2010 Websites\DebugTrue\Default.aspx.vb:8.

If you are a debugger freak and have some knoweldge about WinDbg dump analysis, you should agree with me in my following notes:

To find out if any of the applications on your server run with debug=true you can run a nifty command in sos.dll called !finddebugtrue which will list out all applications where debug=true in the web.config

Debug set to true for Runtime: 61b48dc, AppDomain: /SampleApplication

Debug set to true for Runtime: 1f50e6d8, AppDomain: /MemoryIssues

Total 16 HttpRuntime objects

And to find out if you forgot to compile some of your assemblies in release mode run !finddebugmodules

Loading all modules.

Searching for modules built in debug mode.


SampleApplication.dll built debug

MemoryIssues.dll built debug

fl4sq-9i.dll built debug

wepr1t3k.dll built debug

r9ocxl4m.dll built debug

zmaozzfb.dll built debug

The dlls above with weird 8 character names are the dlls generate when JITing the aspx pages, so they will go away when debug=false.

ScottGu has written an excellent blog on this issue, have a look at the below blog from him:

Have a happy read and share your thoughts.

Let me know if you have any questions and issues on this, I will be happy to answer them.

I noticed that when you set compilateion debug = false, then the menu display at the top will ignore security settings and display all mlen items freely to all users regardless of role or login status. Any comment about this?

Hi, I believe that this setting debug flag has nothing to do with UI rendering issues. This attribute belongs to the system.web namespace which solely governs the compilation life-cycle of your application. What i can imagine would be happening in your case is, if you are testing that in IE, then it may be your IE settings or CSS which would be doing that..

Hope this helps, let me know if you find a solution for this problem..

Compiling for Production: Release vs. Debug

We have developed a number of different applications (ASP.NET web site,
Windows services, DLLs, Windows forms, etc.) in C# 2.0. We have developed
and unit tested all these applications/components using Debug mode. Now we
are ready to compile everything for release to production. However, we don’t
know whether we should compile all the applications/components/assemblies
using Release mode (or keep everything in Debug mode).

We’ve tried researching Debug mode vs. Release mode but have been unable to
find any concrete information on which one is better, which one should be
used in production and why, if Debug in production is good or bad, etc.

So, we’re posting the question(s) here:

— Should we compile in Release mode for a production release and why?
— Are there any issues releasing Debug mode applications/assemblies into
production?
— What (if any) are the main differences between Release and Debug modes?

We have developed a number of different applications (ASP.NET web site,
Windows services, DLLs, Windows forms, etc.) in C# 2.0. We have developed
and unit tested all these applications/components using Debug mode. Now we
are ready to compile everything for release to production. However, we don’t
know whether we should compile all the applications/components/assemblies
using Release mode (or keep everything in Debug mode).

Release. Debug gains you nothing unless you actually plan on debugging the
application in the field, which is rare. What debugging does, mainly, is
turn off most aggressive optimizations (like eliminating local variables,
extracting loop invariants and other things that make your code run faster
but weaken the connection between the binary and the source). It may insert
extra information to allow for edit-and-continue sessions. Some constructs
like P/Invoke and dynamic code generation may deliberately use slower but
more predictable implementations to help you detect problems (this may just
be restricted to when you’re actually running the code under a debugger,
though, I’m not certain). None of this helps your customer much, and the
code may run slower.

For managed code, the differences between debug and release code tend to be
less dramatic than for unmanaged code, mainly because it’s all JIT-compiled
bytecode anyway. That said, you may experience rare cases where a debug
build doesn’t have a problem experienced by a release build (and vice versa)
due to initialization or timing issues. These usually indicate a subtle bug
that’s simply doesn’t manifest under certain conditions. You should always
perform any tests on the release version as well, as a sanity check.
Nothing’s more embarrassing than having to say «but it worked on my machine».

A debug build is ideal for quickly diagnosing and fixing problems, but you
can still debug a release build if necessary, and it’s important to be able
to replicate your customer’s situation. What you should always do is have
the compiler produce debugging symbols (.PDB) for your application, even in
release mode. In Visual Studio, producing these is controlled by the options
onder project properties -Build -Advanced.

These symbols are not for distribution to your customer (unless you don’t
mind them seeing your source file names and line numbers. ) but they will
help you in debugging an issue on the same binary the customer has, should
this turn out to be necessary.

Intel® SGX: Debug, Production, Pre-release —What’s the Difference?

Since releasing the Intel® Software Guard Extensions (Intel® SGX) SDK, we’ve had a few questions about debug vs pre-release vs release mode (production) enclaves.

Part of the security model of Intel® Software Guard Extensions is to prevent software from peaking inside and getting at secrets inside the enclave. but no-one writes perfect code the first time round; so how do you debug an enclave?

Intel® SGX HW Debug Architecture

The Intel SGX architecture supports two modes for Enclaves a Debug mode and Production (non-debug) mode. Production Mode enclaves have the full protection provided by the architecture. In the HW architecture debug mode enclaves differ from production enclaves in 4 basic ways.

  1. Debug Enclaves are created with the ATTRIBUTES.DEBUG bit set. This field appears in the output of the EREPORT instruction REPORT.ATTRIBUTES (see Enclave Data Structures chapter in the Intel x86 Software Developers Manual). The debug bit is not measured as part of the build process so Debug and Production enclaves can have the same measurement.
  2. Keys returned by the EGETKEY instruction leaf in debug enclaves are different for the same enclave in production mode.
  3. Debug enclaves can be introspected by an enclave aware debugger (using the Intel SGX debug instructions) – a normal debugger cannot introspect a debug enclave.
  4. Performance counters are enabled inside debug enclaves.

The Intel SGX SDK includes the Intel SGX debugger as a Microsoft Visual Studio* plugin. See the Enclave Debugger section of the Intel® Software Guard Extensions Evaluation SDK User’s Guide for additional details.

Intel® SGX SDK Compilation Profiles

Traditionally a developer would have two basic profiles for compiling their code:

  • Debug: compiler optimizations are disabled, debug symbols are kept, suitable for source level debugging (typical for any SW development, standard terminology of common IDEs), plus the enclave will be launched in enclave-debug mode.
  • Release: compiler optimizations are enabled, no debug symbols are kept, suitable for production build, for performance testing and final product release (typical for any SW development, standard terminology of common IDEs), plus the enclave will be launched in enclave-production (non-debug) mode.

In addition we have added two more profiles to the support offered in the Intel SGX SDK:

  • Pre-release:same as Release with regard to optimization and debug symbol support, but the enclave will be launched in enclave-debug mode, suitable for performance testing.
  • Simulation: builds the Intel SGX application linked with the «simulation» libraries, not a real enclave, this allows the enclave to be run on any non-Intel SGX-enabled Intel platform.

Currently the evaluation SDK allows the developer to create and run enclaves using the Debug and Pre-release profiles. Enclaves compiled under the Release profile will not work until the developer completes the production licensing process. If you would like to deliver a production-quality application using Intel SGX, please contact the Intel SGX Program for more information about a production license.

Compile-debug и в продакшн!

MontaVista Software — Infobox Company company company name = MontaVista Software, Inc. company type = Privately held company foundation = flagicon|U.S. Menlo Park, California (September 7 1998) [ [http://www.theregister.co.uk/2004/10/18/linux mobile real time/… … Wikipedia

MontaVista — Software, LLC. Type Privately held company Industry Internet, Computer software Founded Menlo Park, California (September 7, 1998) … Wikipedia

Type system — Type systems Type safety Inferred vs. Manifest Dynamic vs. Static Strong vs. Weak Nominal vs. Structural Dependent typing Duck typing Latent typing Linear typing Uniqueness typing … Wikipedia

Interpreter (computing) — In computer science, an interpreter normally means a computer program that executes, i.e. performs, instructions written in a programming language. An interpreter may be a program that either executes the source code directly translates source… … Wikipedia

Atari Assembler Editor — The Atari Assembler Editor cartr >Wikipedia

Turbo Pascal — Infobox Software name = Turbo Pascal caption = Turbo Pascal 4.0 (1987) startup screen. developer = Borland released = latest release version = latest release date = latest preview version = latest preview date = operating system = CP/M, CP/M 86,… … Wikipedia

Emacs — infobox software caption = GNU Emacs 22.0.91.1 with multiple buffers and syntax highlighting for LaTeX, C#, and C. developer = the GNU project author = Richard Stallman released = release year|1976 frequently updated = yes programming language =… … Wikipedia

Exploratory programming — is an important part of the software engineering cycle: when a domain is not very well understood or open ended, or it s not clear what algorithms and data structures might be needed for an implementation, it s useful to be able to interactively… … Wikipedia

Eiffel (programming language) — Infobox programming language name = Eiffel paradigm = object oriented year = 1986 designer = Bertrand Meyer developer = Bertrand Meyer Eiffel Software latest release version = 4.2 latest release date = Feb 6, 1998 typing = static typing, strong… … Wikipedia

PDP-8 — A PDP 8 on display at the Smithsonian s National Museum of American History in Washington, D.C.. This example is from the first generation of PDP 8s, built with discrete transistors and later known as the Straight 8. The 12 bit PDP 8 was the… … Wikipedia

Evim — Vim Vim Logo Basisdaten Entwickler: Bram Moolenaar und andere Aktuelle Version … Deutsch Wikipedia

How to debug in production

Dec 4 ’17 ・3 min read

We’ve all seen bugs in production. Sometimes we can reproduce them, sometimes we can’t.

When we can reproduce them, then we fix it quickly. The we do some regression tests to see if we broke anything else. And then we’re done.


When we can’t reproduce it, that’s a totally different story.

How do we know that we can’t reproduce it?

This sounds simple, doesn’t it? We tried to use the system, and the problem hasn’t occurred. It is possible that we just couldn’t reproduce it yet? Is it possible that we’re only one step away from reproducing it?

Let’s move from philosophical questions to pragmatic ones. Is it a waste of time tying to reproduce a NullPointerException? Is it a bigger waste of time blindly adding some code? How do we know it?

Usually we have a process about reproducing. This process is usually implicit, nobody writes it down. My process looks something like this:

  1. Read the bug report
  2. Quickly check the exception trace, hoping that it reveals an obvious problem
  3. Try to reproduce it based on what’s written on the bug report
  4. Analyze the logs and the related source code to figure out what could’ve happened
  5. Try to reproduce it again
  6. In case of multi-threaded programming, tweak the threads and locks to reproduce an odd situation

At every step I might go back to read the bug report and the logs. After a day or two I can either reproduce the bug, or I give up the search.

When I give it up, then I do either or both of the two things:

  1. Reproduce and fix the issue with a unit-test.
  2. Add more logging.

If we reproduce a problem with a unit test, then we’re likely to fix only a symptom. Say for instance, if we add another null-check, then we still won’t know why a certain method receives invalid data. Soon we’ll see other NullPointerException -s.

When we add logging, then we’ll use lots of resources like CPU, Disk, Memory. Operators won’t allow it most of the time. They usually agree that it’s crucial to fix the bug. Yes, they want to help you figure out the root cause. No, sorry, they can’t let you add logging.

Luckily, there are a few approaches to get debug data from production effectively.

Logging fix 1: Sampling

One approach is sampling. We don’t have to log every user session. We can select every 1000th user session and log all of their data. Alternatively, we can use a random generator to select every 1000th user session and log that.

This is useful only if the bug occurs quite frequently. Just keep in mind, we need to sample user sessions, not log events. So we’ll get detailed information on what went wrong.

You might make the log sampling configurable. So if production operators finds that our logging still uses too many resources during peek time, they might turn it off for a couple of hours.

An alternative of log sampling is A/B testing. If our architecture allows, we might turn on debug logging on a fraction of our servers.

Logging fix 2: Logging a session in memory

Sometimes we can log debug data in memory. If an error occurs in that user session, then we can write it to a file. If not, then we simply release the memory we’ve allocated.

This is useful if the error occurs infrequently. In this case we have to do something to catch the bug as soon as it happens. However, production operation won’t necessarily be happy about it. It depends on the memory needs of our debug logging.

We can combine this kind of logging with log sampling. Say for instance, we log debug data for every 10th user session, and write it to file when an error occurs.

Logging fix 3: In-memory ring buffer, by Kofa.

István Kovács explained a third approach: an in-memory ring buffer. Every log goes into this in-memory ring buffer. This buffer has a configurable size. Also, it’s a ring buffer, so the most recent logs overwrite the oldest lines.

The logs that usually go to a file, they still go to a file. When an error occurs, the whole ring buffer gets written to a file.

This is really cool because the memory overhead is limited. If you set the size of the ring buffer right, then you’ll have all the debug data you need. On the other hand, you might spend some time to find the right size for this ring buffer.

Полиглоты в продакшн Python-а

Сразу, в порядке завлекалочки. Нашей целью будет научиться писать программы-полиглоты, способные интерпретироваться сразу на нескольких языках программирования (одним, «базовым» из которых является Python). При этом, в случае интерпретации на одном из них, программа будет генерировать другую программу, функционально схожую (или даже эквивалентную) той, которая выполняется в случае интерпретации на другом языке.

И самое интересное: подходы, используемые при написании этой программы, будут интересны не столько академически, сколько практически — при разработке программы с использованием этих подходов разработка будет проще и удобнее (хоть поначалу и чуточку непривычно), а программа будет эффективнее, чем без них.

Впрочем, это звучит страшнее, чем является.

__debug__

Начнём с достаточно простого — с кодогенерации. Программисты на Python знают, что в Python нет никакого препроцессора (как, например, в C), который бы позволял создавать макросы, в зависимости от каких-то параметров генерирующие различный код на этапе compile-time. «Динамичность» Python-а, конечно, позволяет генерировать что угодно и когда угодно на runtime, но… иногда возможность влиять на compile time тоже полезна, и даже необходима.

Препроцессора в Python, конечно, нет. Но все программисты на Python наверняка знают директиву assert, позволяющую добавить в код программы проверку, что в каком-то месте значение какого-то выражения инвариантно.

При этом они наверняка помнят, что эта директива при запуске интерпретатора Python «с оптимизацией» (т.е., ключом -O ) игнорируется и интерпретатором не выполняется.

Сравним, например,

Что из этого следует? Что, варьируя значение оптимизации при старте генерации байт-кода, можно получить совершенно разный байт-код. Код, который по-разному ведёт себя в зависимости от того, был он запущен в режиме оптимизации или без. Что это, как не зачаток препроцессора?
Зачем нам это может быть полезно? Для того, чтобы существенно разделять в поведении debug- и release-build-ы. Всё как «в больших языках» — куча проверок, логов и информативности в debug-build-е, быстрый и эффективный код в release-build-е. Но не мало ли для этого одной директивы assert?

Итак, assert ведёт себя по-разному в зависимости от настройки оптимизации, которая была в момент генерации байт-кода (при этом я надеюсь, что все помнят/знают, что байт-код вовсе не обязательно перегенерировать каждый раз? Более того, его, т.е. файлы .pyc / .pyo , можно распространять без исходников, из которых они были сгенерированы).
Из этого вполне логично следует, что генератору байт-кода доступна информация, была ли включена оптимизация на момент его запуска. А как, кстати, он умеет оптимизировать код?

Так вот, эта самая информация доступна ему в виде константы __debug__ . Обратите внимание — действительно константы. Не так что часто в абсолютно динамическом языке Python-а можно найти константы :) Но раз уж это константа, то оптимизатор таки умеет генерировать код по-разному, в зависимости от её значения:

И это, и, как частный случай, оптимизация директивы assert (ну, плюс ещё удаление docstring-ов при -OO ) и составляет фактически весь спектр умений оптимизатора.

Этот оптимизатор настолько прост, что, хоть он и умеет оптимизировать генерацию кода для операторов or и and над переменными (так, что вторая часть проверки не будет выполняться в случае ненадобности), но оптимизировать генерацию кода, когда первой проверкой является константа (так, что вторая часть проверки не будет генерироваться в случае ненадобности), он уже не умеет:

Обратите внимание: хоть оптимизация и была включена, хоть сгенерированный код и способен пропустить проверку на x > 5 , если после проверки он выяснит, что константа __debug__ установлена в True , но саму проверку он будет делать. Поэтому, если необходимо избавиться даже от генерации какого-то кода в release-build-е, придётся оптимизировать код «по старинке» — делать вложенные проверки, сначала на значение __debug__ , и только внутри неё на x > 5 :

Кстати, тернарный оператор тоже не оптимизируется на проверку константы:

Вспомним, для чего мы это делаем: для того, чтобы иметь возможность в debug-build-ах иметь сколь угодно детальную отладочную информацию (например, выводящуюся в сервисные логи), которая бы при этом опускалась и не влияла на производительность release-build-ов.

Зато теперь, когда мы точно знаем, что и как можно делать с переменной __debug__ (никаких составных логических операций, никаких тернарных операций — только чистая проверка одной переменной __debug__ на валидность), мы можем сделать, например, следующее:

Это уже что-то. Теперь мы можем понавставлять log(что-нибудь) хоть в каждую вторую строку кода — на производительность release-build-а это нисколько не повлияет.

Ну, честно говоря, почти нисколько. Пусть теперь на release-build-е мы и не пишем каждую строчку лога посредством жутко медленного вызова процедуры __do_some_heavy_logging() печати строчки на древнем рулонном АЦПУ — но вызов каждой функции log() , пусть и пустой, в release-build-е сохранится. И генерация сообщения для него (если она тоже вычислительно нетривиальна). Но тут уже ничего не поделаешь. В Python препроцессора нет, и совсем опускать вызов log() на debug-build-ах у нас не получится. Впрочем…

GPP: GNU Python Preprocessor

… Впрочем, если препроцессора нет в самом Python-е, почему бы не взять его извне? Чего только не сделаешь в стремлении оптимизировать release-build.

Слава богам, на свете существует GPP — Generic Preprocessor, General-Purpose Processor, а теперь ещё и новый backronym — GNU Python Preprocessor. Почему бы и нет?

Особо описывать его и перечитывать man вслух неохота. Скажу только, что синтаксис его фактически повторяет синтаксис препроцессора в C: #define , #if и т.п.

Что очень даже удобно — в Python со знака диеза начинаются комментарии. Осознаёте, что это значит.

Правильно. Сейчас мы будем писать программу-полиглот.

Да. Это вполне себе полноценный полиглот. Программа на двух языках — языке Python (не обладающем препроцессором), и на языке GPP.

При этом это программы не уровня print «Hello world» , одинаково ведущей себя на 4242 различных языках и диалектах программирования. Отнюдь, наши программы будут иметь вовсе даже различные задачи. Программа на Python (1) должна будет решить ту задачу, ради которой мы её пишем. Программа на GPP (2) должна сгенерировать программы на Python (3)/(4), решающие задачу, ради которой мы её пишем.

Причём, обратите внимания на два забавных факта. Во-первых, программа на GPP будет генерировать не одну, а как минимум (в нашем случае) две различных программы на Python. Одну (3) — соответствующую debug-build-у, другую (4) — соответствующую release-build-у. А во-вторых, (1) определённо вовсе не равно (4) (ради того, чтобы релиз-билд отличался от промежуточного разработческого в сторону повышения производительности за счёт выкидывания отладочного кода, мы всё и затеяли), и даже не обязан быть равным (3)! Но лучше, конечно, чтобы хотя бы (1) был равен (3). Иначе запутаемся. Слишком много уровней, на которых одновременно надо мыслить. Типичная проблема при написании программы-полиглота.


Ну что, попробуем?

Пишем исходник на GPP:

В общем, неплохо. Если мы вызывали GPP с параметром -Ddebug , то он в каждое место исходника, где встречался вызов функции log() , подставит вместо него вызов функции __do_some_heavy_logging(msg) . По сравнению с кодом, основанным на __debug__ , уже прямая выгода — меньше на один промежуточный вызов функции. Если же мы вызывали GPP без такого параметра, то каждый вызов функции log() он заменит на пустую строку…

Ура! То, что нам надо… или нет?

А если мы выполним этот код сразу в интерпретаторе Python-а без препроцессинга? Тогда при любом вызове функции log() интерпретатор просто не найдёт её — у нас же она определена в препроцессоре.

А значит, надо её определить и на уровне Python-а. Причём так, чтобы не помешать препроцессору. Второй блин:

Уже лучше. Без препроцессинга — создаём функцию log() и используем её каждый раз при вызове log() в коде. С препроцессингом, без переменной препроцессора debug — вызовы log() заменяем на пустую строку. С препроцессингом, с переменной препроцессора debug : вызовы log() заменяем на вызовы __do_some_heavy_logging() .

Хорошо? Уже лучше. Но есть один нюанс: у нас (1) получился не равным (3). Что, конечно, хоть и красиво, но потенциально опасно в процессе разработки. Лучше всё-таки сделать так, чтобы препроцессированный в режиме debug код был абсолютно эквивалентен коду без препроцессинга. И поэтому весь его поместить внутри проверки #ifdef debug .

Вот так намного лучше. В секции #ifdef debug — только непрепроцессорный код, и поэтому программа будет себя одинаково вести и с препроцессором и переменной -Ddebug , и без препроцессора. В секции else только препроцессорный код (и поэтому он сработает только в release-build-е). Так-то. И даже Python-овой переменной __debug__ больше не надо.

Cython

Теперь, когда мы научились генерировать Python-овый код препроцессором и при этом сохранять запускаемость без прохода препроцессором, почему бы не взять задачу посложнее?

Почему бы нам не попробовать написать программу, которая после прохода GPP в режиме release (без переменной -Ddebug ) генерирует код на вообще другом языке программирования? Ну, или на почти другом?

А, например, затем, что этим языком может быть язык Cython. Основанный на Python-е и близкий к нему по синтаксису, но при этом явно типизированный. И имеющий милую и полезную в хозяйстве возможность: программа/модуль на Cython может транслироваться в исходник на C, а из этого исходника после компиляции может создаться модуль, пригодную для использования из Python-ового кода.

Единственное что — программы на Cython обратно не совместимы с Python-ом. А вот программы на Python обычно являются корректными программами на Cython. С одной стороны, это упрощает задачу до почти что тривиальности. С другой — мы не пионеры, чтобы создавать себе трудности и героически решать их, мы просто хотим писать на Python эффективно.

Итак, цель: написать модуль на Python (1′), имеющий функцию, производящую какие-то вычисления. Этот модуль должен спокойно импортироваться и использоваться самим Python-ом без какого бы то ни было препроцессинга — чтобы удобнее разрабатывать было. Кроме того, этот модуль должен являться программой на GPP (2′). Которая, в случае соответственного указания переменных GPP, должна сгенерировать программу на Cython (3′). Содержащую алгоритм, полностью аналогичный программе (1′), но при этом типизированный. Такой, что после трансляции исходника (3′) в C (4′) и компиляции создастся бинарная библиотека Python-а, выполняющая всё то же самое, что и в (1′), только, за счёт компилированного кода, намного быстрее.

В качестве решаемой задачи возьмём, например, вторую задачу Project Euler: найти сумму всех чётных чисел Фибоначчи, не превышающих четырёх миллионов. Представим, что нам её надо решать как часть гораздо большей проблемы, и задачу мы по-прежнему хотим решать на Python-е. Просто именно эту функцию мы хотим оптимизировать по производительности, переписав её на Cython-е. При этом хотим сохранить возможность запускать этот же код и без обработки Cython-ом (и GPP), как обычный Python-овый код, из соображений удобства разработки.

Желаемый процесс выглядит разработки следующим образом: мы делаем модуль Python-а, из которого мы в процессе разработки и отладки и будем импортировать вычисляющую решение нашей задачи функцию. Этот же код при сборке release-build-а будет интерпретирован посредством GPP, который сгенерирует при этом эквивалентную программу на Cython (с необходимой для данной задачи типизацией данных); далее в процессе сборки release-build-а программа на Cython будет транслирована Cython-ом в программу на C, которая будет скомпилирована в библиотеку, доступную для использования Python-овому коду. И в release-build-е вызывающий Python-овый код будет импортировать функцию уже не из Python-ового модуля, а из бинарной библиотеки, скомпилированную и очень быструю.

Как же должна выглядеть функция, решающая вторую задачу? Спойлер, конечно… но это вторая задача, и любой разумный программист, дочитавший до этой строчки и не ускользнувший в царство Морфея, наверняка спокойно решит её сам. Поэтому не будет большой потерей для учебного процесса, если я напишу эту функцию:

Соответственно, мы пишем модуль fibo.py , который содержит эту функцию, в основной программе импортируем функцию из этого модуля и вызываем, передав верхнюю границу для задачи.

Хоть эта функция даже для верхней границы в четыре миллиона и выполняется достаточно быстро даже в интерпретируемом Python, но в данном случае она просто демонстрирует возможности, которых мы можем добиться. Поэтому попытаемся оптимизировать её, несмотря ни на что. Перепишем её на Cython.

В принципе, уже имеющаяся у нас функция на Python является вполне валидной функцией на Cython. Более того, будучи скомпилирована Cython-ом, она даже будет работать быстрее. Раза этак в два-три. Потому что полностью исчезнет этап обработки байт-кода, и вместо него машинный код будет сразу выполнять необходимые операции над Python-овыми объектами.

Но это не предел. Если мы решим типизировать наши данные (при этом, к сожалению, потеряв приятную неограниченность Python-ового типа данных long), то наш код будет работать ещё быстрее.

Что мы будем (можем) типизировать в Cython? Входные аргументы функций. Выходные результаты функций. Промежуточные переменные.

Вот и типизируем всё. Посчитаем, что 64 bit should be enough for everybody, и все переменные приведём к unsigned long long. Заодно и познакомимся с Cython-ом, кто его не знает:

Код хороший, достаточно читабельный для питонистов, и вполне понятный. Он имеет только два недостатка:

  1. Он уже не является валидным кодом на Python. Впрочем, мы это решим. Препроцессором. Но…
  2. Он не работает.

Ну не то что бы совсем не работает. Просто не решает нашу задачу. Этим кодом прекрасно создаётся, в терминологии Cython, «C function». Которую можно вызывать из другого кода на Cython или даже на C, но которую нельзя вызывать из кода на Python. Что нам не подходит.
Придётся модифицировать эту функцию так, чтобы она осталась «Python function». С чуточку медленным вызовом (впрочем, вызов из кода на Cython можно сохранить быстрым), возвращающую PyObject (если кого-то волнуют внутренности Python-ового интерпретатора).

Итак, мы имеем функцию на Python, которая решает нашу задачу пусть и медленно, зато модуль с ней удобнее отлаживать — запускать на интерпретацию без промежуточной обработки. И функцию на Cython, которую обычный интерпретатор Python уже не поймёт, но которая зато наиболее производительна:

Воспользуемся нашим любимым GPP (или что, вы его ещё не полюбили?), вспомним те знания, которые мы приобрели в процессе создания первой программы-полиглота Python/GPP, и напишем для начала программу на GPP:

Неплохо. Но если мы попытаемся прочитать её как программу на Python, считая строки с диезами за комментарии, мы увидим, что это вовсе не полиглот. А невалидная программа на Python — сразу после строчки с def идёт строчка с cpdef . Будем думать, как же замаскировать от интерпретатора Python код на Cython.

Предыдущий опыт подсказывает нам, что блок #ifdef debug должен содержать только код на Python, а блок #else — только препроцессорный код. Или комментарии. Но как спрятать от интерпретации Python-ом блок #else ? Если мы закомментируем его — посредством GPP мы не сможем его раскомментировать. Если мы создадим какой-нибудь макрос GPP, который комментирует этот блок в debug-build и декомментирует в release-build — это будет невалидным кодом на Python, без прохода GPP.

Посмотрим повнимательнее на стыки языков и попробуем сделать что-нибудь там. Подсказку нам может дать то, как выглядят и где находятся нежелательные Cython-строчки при интерпретации получившегося кода как Python-функции:

… Они находятся прямо под сигнатурой функции, в том месте, где должны находиться… docstring-и!

Ага. Идея ясна. Попробуем поправить этот код так, чтобы Cython-овые строчки выглядели docstring-ами (или просто свободными строками) при интерпретации Python-ом. А с интерпретацией GPP — нет.

Это ещё далеко не рабочий код, это только начало. Но идея ясна: с точки зрения Python (и, что обязательно — одновременно после препроцессинга GPP без -Ddebug ), код на Cython станет docstring-ом.

Но теперь у нас возникла проблема: проход препроцессором в режиме -Ddebug генерирует пустой docstring, а проход препроцессором в release-режиме генерирует только конечный триплет двойных кавычек от docstring-а. Тупик.

Что-то надо сделать, чтобы избавиться от триплета кавычек в препроцессинге, но сохранить его без препроцессинга?
Или вообще — чтобы в режиме препроцессинга триплеты кавычек исчезали, а без препроцессинга оставались? Нет, конечно, можно каждый триплет обрамлять своим собственным #if debug , или что-нибудь в этом духе, но это громоздко. Вот если бы можно было в режиме препроцессинга их прятать… комментировать!

И точно. В GPP же есть возможность создавать свои комментации для препроцессора. Вот и создадим их, многострочные, как в C: /* . */ . Триплетами кавычек мы с точки зрения Python-а будем «комментировать» (точнее, всё-таки прятать) Cython-овый код, а C-style кавычками мы с точки зрения Cython будем комментировать триплеты кавычек. А C-style кавычки, чтобы они не проявились в Python-е, спрячем внутрь Python-овых комментариев.

Всё прекрасно. Этот код генерирует всё, что надо, во всех режимах. Он позволяет одну и ту же функциональность отлаживать в Python-режиме, и одновременно он готов к компиляции Cython-ом. Он великолепен.

Down to Earth

… Ладно, согласен, он не великолепен. Положа руку на сердце, вынужден признать — он отстой. Его совершенно нереально поддерживать. Его можно только копипастить. Эта путаница знаков препинания совершенно неинтуитивна. Если нам понадобится указывать эту конструкцию для каждой функции, то код станет выглядеть как Дрезден после бомбёжки. В реальном продукте такого быть не должно.

Хорошо. В лучших традициях доктора Хауса, первый диагноз и первое лечение оказались неверными и опасными для пациента. Делаем дифференциальный диагноз ещё раз, на основании того, что мы уже знаем.

Нам надо сделать две препроцессорные ветки. Ветка #ifdef debug должна без препроцессинга генерировать не выполняющийся при интерпретации Python-ом код. Ветка #else должна содержать как раз работающий код. Это всё должно выглядеть достаточно понятно и читабельно, и использовать это должно быть просто.

Следовательно, вариант с комментированием всего и вся и перекрываниями области комментирования в разных языках отметается. Он в любом случае был негоден — а что если бы где-нибудь в Python-е встретилась бы последовательность /* ?

Хорошо. Какие у нас ещё варианты?

Препроцессорные макросы. Да, именно они. Это всё упрощает. В точности как мы делали в самом первом эксперименте с GPP и логгированием.

Заведём макрос cython() , которым мы будем обрамлять весь код, который не предназначен для обработки Python-интерпретатором. И поместим в него всё Cython-оотносящееся. При интерпретации GPP этот макрос будет восприниматься именно как макрос; без интерпретации он будет ничего не делающей Python-овой функцией. Что-то типа такого:

Вот, это выглядит намного проще и понятнее. Хотя ещё не закончено. Если мы пропустим этот код через препроцессор, то, на удивление, мы увидим целых две проблемы:

Во-первых, хоть Cython-овый код теперь прячется препроцессором достаточно неплохо, но Python-овый заголовок функции всё ещё светится. Делать нечего — придётся в каждой функции, для которой мы собираемся создавать Cython-овый аналог, писать ещё и кусок с явной проверкой на #ifdef debug .

Во-вторых, GPP просто так не обладает концепцией «строк». Поэтому если мы хотим макросу cython передавать аргумент именно как единственный строковый компонент, который при раскрытии должен не печатать сами кавычки, мы должны указать соответствующую настройку в GPP. Последние правки…

Вот теперь всё в порядке. Такой код не страшно и в продакшн. Главное — не забывать не использовать двойные кавычки внутри аргумента cython() .

Что же, научились мы многому. Писать программы на Python и Cython одновременно. Убирать debug-код в релиз-билде. Немножко познакомились с особенностями оптимизатора Python-а. Теперь представим, как может выглядеть наша функция в режиме all included, в окончательном коде:

Don’t run production ASP.NET Applications with debug=”true” enabled

One of the things you want to avo > switch on within the application’s web.config file.

Doing so causes a number of non-optimal things to happen including:

1) The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)


2) Code can execute slower (since some additional debug paths are enabled)

3) Much more memory is used within the application at runtime

4) Scripts and images downloaded from the WebResources.axd handler are not cached

This last point is particularly important, since it means that all client-javascript libraries and static images that are deployed via WebResources.axd will be continually downloaded by clients on each page view request and not cached locally within the browser. This can slow down the user experience quite a bit for things like Atlas, controls like TreeView/Menu/Val > Note that the reason why these resources are not cached when debug is set to true is so that developers don’t have to continually flush their browser cache and restart it every-time they make a change to a resource handler (our assumption is that when you have debug=true set you are in active development on your site).

When is set, the WebResource.axd handler will automatically set a long cache policy on resources retrieved via it – so that the resource is only downloaded once to the client and cached there forever (it will also be cached on any intermediate proxy servers). If you have Atlas installed for your application, it will also automatically compress the content from the WebResources.axd handler for you when is set – reducing the size of any client-script javascript library or static resource for you (and not requiring you to write any custom code or configure anything within IIS to get it).

What about binaries compiled with debug symbols?

One scenario that several people find very useful is to compile/pre-compile an application or associated >

The good news is that you can do this without having the have the switch enabled in production. Specifically, you can use either a web deployment project or a web application project to pre-compile the code for your site with debug symbols, and then change the switch to false right before you deploy the application on the server.

The debug symbols and metadata in the compiled assemblies will increase the memory footprint of the application, but this can sometimes be an ok trade-off for more detailed error messages.

The Switch in Maching.config

If you are a server administrator and want to ensure that no one acc > switch enabled within the application’s web.config file, one trick you can use with ASP.NET V2.0 is to take advantage of the section within your machine.config file.

Specifically, by setting this within your machine.config file:

You will disable the switch, disable the ability to output trace output in a page, and turn off the ability to show detailed error messages remotely. Note that these last two items are security best practices you really want to follow (otherwise hackers can learn a lot more about the internals of your application than you should show them).

Setting this switch to true is probably a best practice that any company with formal production servers should follow to ensure that an application always runs with the best possible performance and no security information leakages. There isn’t a ton of documentation on this switch – but you can learn a little more about it here .

Hope this helps,

Updated: Tess has a great follow-up post with more details about what happens when debug=»true» is enabled. You can read it here.

59 Comments

Scott, many thanks for the retail=»true» tip, we’ll be implementing that right away!

We currently use a web site project and use Publish Web Site to pre-compile it. I originally thought that this would automatically set debug=false in the web.configs it publishes but it does not. However, it does compile the site without any PDBs.

Does this mean that only your point 4 is relevant if debug=true is left unaltered?

Slightly off-topic — can you give an indication when the next release of the web application project will be available?

The first three points all count for ASP.NET 1.1. The WebResource.axd handler isn’t supported in V1.1 — so that part is only V2.0 specific. I don’t believe the switch was supported in V1.1.

Hope this helps,

will the resources be cached on the local web browser without checking if there is a new file/version on the server, or will every request will get «HTTP/1.0 304 Not Modified» instead?

Yes, good advice. One of my websites was running sooo slow and was already thinking of switching hosting prov >

In the documentation you link to about the deployment element, it notes that the custom error settings are disabled. Is this saying that my defaultRedirect or status code specific error pages will not work if I have them set in my web.config?

Your custom errors will work fine with the retail switch set. I think what is disabled is the ability to turn customerrrors off — meaning the ability to expose the raw exception to remote customers directy (which you want to make sure you never do with a production app).

When the Visual Basic Refactoring plugin is installed Visual Studio crashes almost every hour. When do you plan to update the plugin?

Can you send me email (scottgu@microsoft.com), and I can then loop you in with the VB team. Note that the plugin is not built by Microsoft (it is a third party component), but they can help you figure out how to get it fixed.

Thanks for all of your valuable insights. We are using the Web Deployment Project with the out of box Web Site configuration (ie. not Web Application Projects). I have the same issue as Brian’s post about not being able to change the debug option to false in the Project settings. Any solution to this?

Also, any word on when the final release of the Web Deployment Project add-in will be released?

Scott, thanks for the information! I knew it affect the performance. I have it on in the past in order to receive detailed error application message. According to you it’s not worth so I turn it off. I do have the custom error page but I don’t see the physical path to the error page through view> source, with or without debug=»true» turn on.

I believe the stack trace that Danny mentions above only happens if you are local on the machine. For remote access we never send the stack trace unless you have custom errors turned off.

Hope this helps,

Good question about the caching. I think the client behavior depends on what your client is configured to-do with the browser. You can select either check for changes always, or just have it set to automatic.

Hope this helps,

I have an even better reason to not deploy debug code. When you compile in debug mode, the PDB file includes references to the enviroment on which it was compiled. You will note that when an exception gets thrown in code that has debug mode on, it shows you the code that contains the error, as well as the path to the file. This path is always the location where the code was compiled, NOT the location where the code was running from.

This has two problems 1) you reveal your dev landscape naming to anyone who sees the error, which could create some security problems

2) More importantly, when an exception is thrown, the CLR tries to retrieve the code «live» from the location containted in the PDB. If you deploy debug code to production, it tries to retrieve the code from your dev server when the exception is thrown. It tries to log in to the dev server. The problem is that it logs into the dev server, using your production credentials (of the aspnet user) Assuming your password is not the same in prod and dev, it fails this authentication. If it gets a few errors in a row (3 on my server) the dev account gets locked out!

Obviously this is only an issue if your prod server has network level connectivity to your dev server.

Good catch Tim — I’ll pass to the documentation team to get this fixed.

IS is possible in code to tell if I am under «Debug=true»? on the production server?

I think it would be nice if I could detect this in code and then send the webmaster an email to warn him about the issue?

HttpContext.IsDebuggingEnabled comes close to that. It tells you whether debug is enabled in config for the current request. So if you override debug in sub dirs, this doesn’t necessarily match the application.

Hope this helps,

Caching doesn’t seem to work for me. I have debug=»false» in web.config, cache set to «automatic» in IE 6, but Fiddler shows that WebResource.axd files are still getting downloaded without a 304 response from the server. What the hack am I doing wrong? Below is a line from fiddler showing the 200 response:

Result Host URL Body CachingContent-Type User-defined

5200 localhost /Main/WebResource.axd?d=Lx2tZgJ4CZYMCVBRSPKlzFU6GQN8tje_qDYAkRGohU_PNMQRZvviv5aGvpyf4x4c31VqrwggfhZInZA1QZ2ks4pWzVpDbf9eLwRHKPP0qrA1&t=632796902540000000 23,612 public Expires: Sat, 21 Apr 2007 04:19:00 GMT text/javascript

Nevermind; I just realized that ctrl-r forces IE to discard cache and retrieve fresh content.

The cache header above says that it is being cached for 1 year (until April 2007). So I think the server is sending down the right stuff. My guess is that your browser is still requesting it for some reason (are you sure it isn’t set to «always»?)

I am loving the asp.net 20 and vs 2005 however

no matter what I do I can’t seem to get webresource.axd to work properly. The problem seems to occur when decrypting the framework javascript used for validation. What I am doing wrong here?

Can you send me email (scottgu@microsoft.com) with more details of what you are running into?

To pre-compile the code for a site with debug symbols, I have to use the web application project model or create a new web deployment project? So is this not possible with an ASP.NET Web site? I’m a little frustrated with 2.0 because when I upgraded from 1.1, I’ve been forced to change every web project to the new web site model. This was a huge pain because an ASP.NET Web site is not precompiled into its own assembly and so I can’t refer to its namespace. Now I have to change them back to get the benefits of debug=false with debug symbols included? My boss will not be impressed.

When we deploy our website using web deployment project, even in release mode (and YES debug=»false» — in fact this is forced by deployment) we noticed that #If Debug statements in the code are still evaluating to TRUE! We can tell because of the verbose error messages. Any idea why this might be happening??

Can you send me an email (scottgu@microsoft.com) with more details on this? We can then figure out why this is happening.


This is cool but. whith https all resources wasn’t cached.

Correct — the HTTPS protocol doesn’t allow caching of resources client-side.

Hope this helps,

It’s often noted that this impacts performance but not specifically why; thank you for the details.

Can you confirm: I’m assuming that the Retail Deployment also overr .

Yep — setting the retail flag should override the @Page directive as well.

Hope this helps,

Hi David:
We just went ahead and turned off debugging on our ASP.Net 1.1 site written using Notepad :)
I was wondering however, this still doesn’t seem to have solved the problem. Is there anything else I can add/modify in the web.config file or somewhere else to speed up the site when that unfortunate user hits the page first and waits?? I am running the site on a Dual Xeon 3.0 with 2 GB running on SCSI RAID 5 hardware. So I think that’s enough :)

How many assemblies do you have within the application’s \bin folder? And are you doing anything to load up data to cache on the first request?

Given that hardware you shouldn’t see much of a load time issue — so it is odd that you are.

Have you tried calling Microsoft support to have them help debug it?

i have been working with webresource.axd. It works ok, but when you use it over ssl (https) it doesn’t work. It looks like asp.net can’t send it to the browser (i mean, the resource, especially validators). It must be something i missed. But i cant find a solution. Can you advice me?

What you might be running into are cases where you have a mixed page — with some resources over https and others over straight http.

Is this the case?

P.S. Note that you can use webresources.axd over https — that is supported.

we’re having an issue where we get a secure nonsecure error on a checkout page that we want secured and found the culprit to be webresources.axd as it is the only thing making calls to port 80. but we are having a beast of time trying to figure out how to secure it. Any thoughts?

Can you send me email (scottgu@microsoft.com) with some more details about how your page is configured? I can then help you get this fixed.

What if my I update my webapplication, will the resources also be updated? Will this be a problem if the client is using version 1.1 and I’m updating it to 1.2?

If you update your web application the resources should also be updated.

Hope this helps,

Scott! Very sober article indeed. I am using VS 2005 Web Application Model. I use the Build > Publish menu option to publish the entire application. Problem I have with this approach is that it restarts the application causing users to sign out. Is there any way I can avoid this by publishing only updated files? I am looking forward impateintly to your answer. Thanks in advance.

When you update the .dll assemblies within the \bin directory, or update the web.config file of the application, the application will restart. This will cause in-memory session state to be lost — although forms-authentication tickets are not reset (so your users shouldn’t be logged out).

Hope this helps,

I appreciate your reply. I agree with your answer. It means that when I publish my application on production server it not only restarts the application but also forces users to log out mainly because the session state is lost. So what is the industry standard solution to avoid this issue? Since I have to publish the fixes when there are users logged into my website. Does Visual Studio 2005 single file publish without publishing the entire project?

Thanks a lot for your help.

Good post — Thanks Scott. But it doesn’t discuss any potential issues with mixing debug settings at the web.config, page level, and in user controls. Are there any you know of?

We’ve gotten this error that pops up after we have edited a commonly used user control in .Net 1.1 : «‘mycontrol_ascx’ is ambiguous in the namespace ‘_ASP'». I’ve seen a couple references to this issue on blogs, but no definitive response. I’m speculating it may be related to using Debug=True at the page level, but not on the user control or in web.config.

What people typically do with updates is to perform them at certain non-peak times of the day (for example: in the evening or morning).

Note that if you don’t use session state, or use an out of process session state configuratiuon, there is no interruption to users.

Hope this helps,

Can you send me an email with more details about the error you are seeing? I can then loop in a few folks to help investigate.

Can i change the web.config file line after publishing it to the server?

Yes — you can change this setting even after the app is published to the server.

Are you saying that even if I compiled the application using «release» instead of «debug» but leave the web.config set to debug=true that I will experience this sub-optimal performance?

Yes — you want to make sure you always set debug=»false» in your web.config file. This prevents ASP.NET from running in debug mode and doing extra work.

We have a page containing a number of user controls and in the code behind we are looping through all the controls on the page and performing some actions depending on the type of the control. We are basing this on the following:

select case aControl.GetType.ToString()

Which has been fine on our development boxes, but when deployed to the production box with debug=»false», the namespace seems to change to «_ASP». Why is this and is there any way around this?

I’d recommend definining an interface that you have your usercontrols or pages implemnet. You can then safely check for that at runtime.

Hope this helps,

Is there a way to do the same type of configuration in ASP.NET 1.1 ?

Is there a way to achieve the same «restriction» using ASP.NET 1.1 ? I have many (150 !) applications in ASP.NET 1.1 and last week 2 of them forgott to change debug=true in their Web.config. As i’m running many applications in the same application pool 2 of them grow up to 1,5 GB ! Seems to be related to debug=true

Unfortunately there isn’t a way to automatically override this in ASP.NET 1.1. We added the feature in V2.0 after seeing people run into in it with 1.1.

Hope this helps,

Have you tried calling Microsoft product support? They are great at debugging these types of issues, and should be able to figure out what is going on.

when i set debug=false then run build, the output window still tells me im building as debug?

is this correct?

Example:
—— Build started: Project: D:\. \eadweb\, Configuration: Debug .NET ——

Unfortunately this is a bug with the information to the output window — it always says it is a debug configuration when building a web-site in the IDE.

Sorry about that,

Can you send me an email with more details on this issue? I can then have someone help debug it.

I’ve also recieved the «‘mycontrol_ascx’ is ambiguous in the namespace ‘_ASP'».

The issue arose after setting debug=»false» on our servers and we found the cause to be a second usercontrol with the same name. Maybe the debug=»true» setting allowed these two usercontrols to be compiled and exist within separate dll’s.

The solution we used was to specify the ClassName attribute in the control directive for the usercontrol.

Scott,
Can you give me one ideea why when I run the site using DNS as htpps://domain.com it runs very slow, but whern I use htpps://phisicalboxname.com it runs very fast. Of cause this is something I can do from our internal network but external users can’t.

Comments have been disabled for this content.

Цукерберг рекомендует:  Отслеживания окончания воспроизведения видео
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих