Archive for June, 2007

A Few .Net (2.0) Notes

Sunday, June 24th, 2007

I am currently brushing up on my .Net skills so I will be taking notes on topics that are worth taking the extra time to remember.

Classes and structs

A class is allocated on the managed heap rather than on the stack and assignment between two variables results in both variables pointing to the same instance.

While the functionality is similar, structures are usually more efficient than classes. A struct takes up the amount of space (on the stack) that the value types defined in the struct take up together. You should define a structure, rather than a class, if the type will perform better as a value type than a reference type. Specifically, structure types should meet all of these criteria: Logically represents a single value; Has an instance size less than 16 bytes; Will not be changed after creation; Will not be cast to a reference type.


The runtime optimizes the performance of 32-bit integer types (Int32 and UInt32), so use those types for counters and other frequently accessed integral variables. For floating-point operations, Double is the most efficient type because those operations are optimized by hardware.


Immutable types in .Net, such as strings: Any change to this type causes the runtime to create a new object and abandon the old one. That happens invisibly, and many programmers might be surprised to learn that the following code allocates four new strings in memory:

1
2
3
4
5
6
7
// C#
string s;
s = "wombat";          // "wombat"
s += " kangaroo";      // "wombat kangaroo"
s += " wallaby";       // "wombat kangaroo wallaby"
s += " koala";         // "wombat kangaroo wallaby koala"
Console.WriteLine(s);

Only the last string has a reference; the other three will be disposed of during garbage collection. Avoiding these types of temporary strings helps avoid unnecessary garbage collection, which improves performance.


These notes have been “borrowed” and modified from the book: MCTS Self-Paced Training Kit (Exam 70-536): Microsoft .NET Framework 2.0 Application Development Foundation

Howto: Enable Concurrent Remote Desktop Sessions in Windows XP SP2

Wednesday, June 13th, 2007

Windows XP, unlike the Server editions of Windows, does not allow multiple simultaneous remote user sessions. This can be a pain. For instance, my wife has a user account on my computer at home which she often uses when I am not at the computer. When I am at work (or where ever) and want to remote into my computer at home, I think I should be able to, even if Vanessa is using the computer. I mean, it is totally possible and built into any good OS worth a damn. I do run Windows XP Pro after-all, the more expensive version of XP for profession users. However Windows XP forces you to boot (log off) the other user before you can log in. This is most likely because Micro$oft wants you to shell out more money for the server OS. Even if you use the server edition of Windows, there are licensing issues with it that prevent you from running certain programs that you are only allowed to run on non-server editions of Windows. Oh for crying out loud! What a stupid pointless catch 22. I guess Micro$oft doesn’t see it that way because it forces you to buy more of their software.

This article outlines how to get around this annoying, draconian limitation imposed by Micro$oft.

(more…)

INSERT … ON DUPLICATE KEY UPDATE

Wednesday, June 6th, 2007

MySQL has some nifty extensions to ANSI SQL. Two of which are “INSERT … ON DUPLICATE KEY UPDATE” and “REPLACE” (As of MySQL 4.1). These statements are used when inserting data into a table where the unique key of the row you are inserting may already exist, and if it does, you want this row to be updated with new data. Instead of doing a select/insert/update routine, this gives a significant performance increase for frequently updated schemas; and what is even more important, the application code becomes simpler, less error prone, and easy to read.

“INSERT … ON DUPLICATE KEY UPDATE” will actually perform either an UPDATE or an INSERT, whichever one is necessary. The “REPLACE” statement will actually delete the row if it exists and insert the new row.

Example of “INSERT … ON DUPLICATE KEY UPDATE” (assuming column ‘a’ is the unique key):

1
2
3
INSERT INTO TABLE (a,b,c)
VALUES (1,2,3)
ON DUPLICATE KEY UPDATE b=2, c=3;

Example of “REPLACE”:

1
2
REPLACE INTO table_a (a,b,c)
VALUES(1,2,3);

Oracle 9i+ also has an extension that can somewhat similarly handle this conditional INSERT-or-UPDATE task: the MERGE statement, though not as intuitive and the code is not as easy to read. Here is an example of how one might implement MERGE for this situation:

1
2
3
4
5
6
7
8
9
10
11
MERGE INTO SCHEMA.table_a TA
USING (
 SELECT '1' a, '2' b, '3' c
 FROM DUAL
 ) E
ON (TA.a = E.a)
WHEN MATCHED THEN
 UPDATE SET TA.b = E.b, TA.c = E.c
WHEN NOT MATCHED THEN
 INSERT (TA.a, TA.b, TA.c)
 VALUES (E.a, E.b, E.c);

Comparing Oracle’s 11 line method to MySQL’s 3 line method, I must hand it to MySQL for its simpler and superior method.

References:
forums.devshed.com, dev.mysql.com, dev.mysql.com, www.mysqlperformanceblog.com, www.oracle.com

More C++ Preprocessor Directives

Tuesday, June 5th, 2007

The #pragma directive is a compiler specific directive which compiler vendors may use for their own purposes. For instance, a #pragma is often used to allow suppression of specific error messages, manage heap and stack debugging, etc.

You can see the C# .Net equivalent here.

In Microsoft Visual C++ 8 (Visual Studio 2005), one useful use for the #pragma directive is to modify compiler warnings. This is from Microsoft:

#pragma warning( warning-specifier : warning-number-list [; warning-specifier : warning-number-list...] )
#pragma warning( push[ ,n ] )
#pragma warning( pop )

The warning-specifier can be one of the following.

Warning-specifier Meaning
1, 2, 3, 4 Apply the given level to the specified warning(s). This also has the effect of turning a specified warning on that is off by default.
default Reset warning behavior to its default value. This also has the effect of turning a specified warning on that is off by default. The warning will be generated at its default, documented, level.See Compiler Warnings That Are Off by Default for more information.
disable Do not issue the specified warning message(s).
error Report the specified warnings as errors.
once Display the specified message(s) only once.
suppress Pushes the current state of the pragma on the stack, disables the specified warning for the next line, and then pops the warning stack, resetting the pragma state. You can only specify one warning for each suppress specifier, but multiple warning pragmas can operate on one line of code.suppress is only supported for C6000 warnings (code analysis warnings), which are enabled with the /analyze (Enterprise Code Analysis) compiler option.

The warning-number-list can contain any warning numbers. Multiple options can be specified in the same pragma directive as follows:

#pragma warning( disable : 4507 34; once : 4385; error : 164 )

This is functionally equivalent to:

// Disable warning messages 4507 and 4034.
#pragma warning( disable : 4507 34 )
 
// Issue warning 4385 only once.
#pragma warning( once : 4385 )
 
// Report warning 4164 as an error.
#pragma warning( error : 164 )

The compiler will add 4000 to any warning number that is between 0 and 999.

The compiler only supports up to 56 #pragma warning statements in a compiland.

For warning numbers in the range of 4700-4999, those associated with code generation, the state of the warning in effect when the compiler encounters the open curly brace of a function will be in effect for the rest of the function. Using the warning pragma inside the function to change the state of a warning greater than 4699 will only take effect after the end of the function. The following example shows the correct placement of warning pragmas to disable, and then restore, a code-generation warning message:

// pragma_warning.cpp
// compile with: /W1
#pragma warning(disable:4700)
void Test() {
   int x;
   int y = x;   // no C4700 here
   #pragma warning(default:4700)   // C4700 enabled after Test ends
}
 
int main() {
   int x;
   int y = x;   // C4700
}

Note that within a function body, the last setting of the warning pragma will be in effect for the entire function.

The warning pragma also supports the following syntax:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

Where n represents a warning level (1 through 4).

The pragma warning( push ) stores the current warning state for all warnings. The pragma warning( push, n) stores the current state for all warnings and sets the global warning level to n.

The pragma warning( pop ) pops the last warning state pushed onto the stack. Any changes made to the warning state between push and pop are undone. Consider this example:

#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
// Some code
#pragma warning( pop )

At the end of this code, pop restores the state of all warnings (including 4705, 4706, and 4707) to what it was at the beginning of the code.

When you write header files, you can use push and pop to ensure that changes to warning states made by the user do not prevent your headers from compiling properly. Use push at the beginning of the header and pop at the end. Suppose, for example, you have a header that does not compile cleanly at warning level 4. The following code changes the warning level to 3 then restores the original warning level at the end of the header:

#pragma warning( push, 3 )
// Declarations/ definitions
#pragma warning( pop )

See /FI and /w for compiler options that help you suppress warnings.