Summarize some examples of coding and design principles

Source: Internet
Author: User
This chapter describes some coding and design principles that are not covered in other parts of the book. Contains a few. NET application scenarios, some do not cause too much harm, some will cause obvious problems. The rest will have a different effect depending on how you use it. If you want to summarize the principles that appear in this chapter, it is:

Excessive optimizations can affect the abstraction of the Code
This means that when you want higher optimization performance, you need to understand the implementation details of each level of code. This chapter will have a lot of relevant introductions.

Class vs struct Body

Instances of the class are allocated on the heap and accessed through a reference to the pointer. The cost of passing these objects is low because it is just a copy of a pointer (4 or 8 direct). However, objects also have some fixed overhead: 8 or 16 bytes (32 or 64-bit systems). These costs include pointers to method tables and synchronization fields for other purposes. However, if you look at the memory consumed by an empty object through the Debug tool, you will find that it is 13 or 24 bytes large (32-bit or 64-bit system). This is. NET is caused by the memory alignment mechanism.

The structure is not overhead, and its memory usage is the synthesis of the field size. If the struct is a local variable declared in a method (function), it allocates controls on the stack. If a struct is declared as part of a class, this structure uses memory that is part of the memory layout of the class (so it is allocated on the heap). But when you pass a struct to a method (function), he replicates the byte data. Because it is not on the heap, the struct does not cause garbage collection.

So there's a compromise here. You can find a variety of suggestions about the size of the structure, but I'm not going to tell you an exact number here. In most cases, you need to maintain a relatively small size, especially if they need to be passed frequently, and you need to ensure that the size of the structure does not cause too much problem. The only thing you can be sure of is that you need to analyze it according to your own application scenario.

In some cases, the difference in efficiency is quite large. When an object overhead does not seem to be a lot, the difference can be seen by comparing an array of objects and structures. Under 32-bit systems, a data structure is assumed to contain 16-byte, and the array length is 100w.
Using space occupied by an object array
8 byte array Cost +
(4 byte pointer address x1,000,000) +
((8 bytes Header + 16 bytes of data) x1,000,000)
=28mb

Space occupied by using struct arrays
8 byte array Cost +
(16 bytes Data x1,000,100)
=16mb

If you use a 64-bit system, the array of objects uses 40MB, and the struct array is still 16MB.
As you can see, in an array of structures, data of the same size consumes less memory. As objects in an object array increase, the pressure on the GC increases.
In addition to space, there are CPU efficiency issues. The CPU has a multilevel cache. The smaller the cache closer to the CPU, the faster the access, and the easier it is to optimize for sequentially saved data.
For a struct array, they are contiguous values in memory. Accessing the data in the struct array is simple, and the corresponding value can be obtained if the correct position is found. This means that there is a huge difference in the iterative access of large array data. If the value is already in the CPU's tell cache, it will be accessed faster than an order of magnitude higher than the access RAM.

If you want to access an item in an array of objects, you need to get a pointer reference to that object before you go to the heap to access it. When iterating over an array of objects, it causes the data pointer to jump in the heap, updating the CPU cache frequently, thus wasting many opportunities to access the CPU cache data.

In many cases, the overhead of reducing CPU access to memory by improving the location of data stored in memory is a major reason for using structs, which can significantly improve performance.

Because the structure is always copied when used, so be careful when coding, otherwise you will produce some interesting bugs. For example the following chestnuts, you are not able to compile by:

struct point{public    int x;    public int y;} public static void Main () {    list<point> points = new list<point> ();    Points. ADD (new Point () {x = 1, y = 2});    points[0].x = 3;}

The problem is that in the last line, you try to modify a value of the point element in the list, which is not possible because points[0] returns a copy of the original value. The correct way to modify the value is

Point P = points[0];p. x = 3;points[0] = p;

However, you can adopt a more rigorous coding strategy: Do not modify the structure. Once the struct is created, never change his value. This eliminates the compilation problem above and simplifies the use of structs.
As I mentioned before, structs should be small in size and avoid spending a lot of time copying them, but occasionally some large structures are used. For example, an object with the details of a final business process, in which a large amount of time stamps need to be saved:

Class order{public    DateTime receivedtime {get; set;}    Public DateTime acknowledgetime {get; set;}    Public DateTime processbegintime {get; set;}    Public DateTime warehousereceivetime {get; set;}    Public DateTime warehouserunnerreceivetime {get; set;}    Public DateTime warehouserunnercompletiontime {get; set;}    Public DateTime packingbegintime {get; set;}    Public DateTime packingendtime {get; set;}    Public DateTime labelprinttime {get; set;}    Public DateTime carriernotifytime {get; set;}    Public DateTime processendtime {get; set;}    Public DateTime emailsenttocustomertime {get; set;}    Public DateTime carrerpickuptime {get; set;}    Lots of other data ...}

To simplify the code, we can divide the time data into our own substructure so that we can access the order object in such a way:

Order order = New Order (); Order.Times.ReceivedTime = Datetime.utcnow;

We can put all the data in our own class:

class ordertimes {public DateTime receivedtime {get; set;}        Public DateTime acknowledgetime {get; set;}        Public DateTime processbegintime {get; set;}        Public DateTime warehousereceivetime {get; set;}        Public DateTime warehouserunnerreceivetime {get; set;}        Public DateTime warehouserunnercompletiontime {get; set;}        Public DateTime packingbegintime {get; set;}        Public DateTime packingendtime {get; set;}        Public DateTime labelprinttime {get; set;}        Public DateTime carriernotifytime {get; set;}        Public DateTime processendtime {get; set;}        Public DateTime emailsenttocustomertime {get; set;}    Public DateTime carrerpickuptime {get; set;}    } class Order {public ordertimes times; }

However, this introduces an additional 12 or 24 bytes overhead for each order object. If you need to pass the Ordertimes object as a whole into various method functions, this may make sense, but why not pass the order object into the method? If you have thousands of order objects at the same time, it can result in more garbage collection, which is caused by additional object-added references.
Instead, change ordertime to struct, and access the properties of the Ordertimes struct through the properties on the Order (for example: Order.Times.ReceivedTime) without causing a copy of the struct (. NET optimizes this access). This way the ordertimes structure is basically part of the memory layout of the order class, almost like no substructure, and you have more beautiful code.
This technique does violate immutable structural principles, but the trick here is to treat the fields of the Ordertimes structure as fields of the order object. You don't need to pass the Ordertimes struct as an entity, it's just a way of organizing your code.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.