One-time optimization practices that can increase by 300%

Source: Internet
Author: User
Performance Optimization generally begins with a performance bottleneck. The project has such a control that contains many items. Each item may have the same or different fonts. This control is often used in large quantities on the same form. This control has a performance bottleneck when using GDI to draw the text of each item.


IntptrHandle = font. tohfont ();//Performance bottleneck

//...

Safenativemethods. Deleteobject (handle );

This control obtains the font handle by calling the font. tohfont () method when using GDI to draw words. This method is very slow. This method is called when the widget draws every item. There are many such controls in form, so the number of calls is considerable. This causes this performance bottleneck.

Because the operating system does not allow GDI to have more than 9999 handle numbers. If there are more than 9999,ProgramIt will collapse. Therefore, we absolutely cannot linearly increase the number of GDI handle in the program with some factors. Generally, handle is created when you use GDI to draw a text, and is deleted after use. This can also prevent the leakage of GDI.

In many cases, the font is the same. If the handle created by font can be cached, the performance will be greatly improved. However, if the cached handle is not deleted in time, if the font is too many, the maximum number allowed by the operating system will be reached, causing program crash.

Here are my solutions:
1. Use the safefonthandle class to prevent GDI leakage. Safefonthandle is derived from safehandlezeroorminusoneisinvalid, while safehandlezeroorminusoneisinvalid is derived from criticalfinalizerobject. GC will perform special processing on criticalfinalizerobject to ensure all key terminationCodeAll have the opportunity to execute.

Code
# Region The safefonthandle class

internal sealed class safefonthandle: safehandlezeroorminusoneisinvalid
{< br> private safefonthandle ()
: base ( true )
{< BR >}

Public safefonthandle (intptr preexistinghandle, bool ownshandle)
: base (ownshandle)
{< br> base . sethandle (preexistinghandle);
}

Protected Override BoolReleasehandle ()
{
ReturnSafenativemethods. deletenativefonthandle (Base. Handle );
}
}

# Endregion

2. Use the handlecollector class to prevent the font handle from exceeding the maximum operating system limit. Handlecollector tracks the handle of the font and forces garbage collection when it reaches the specified threshold. After garbage collection, safefonthandle releases the font handle.

Code
[Suppressunmanagedcodesecurity]
Internal   Static   Class Safenativemethods
{
Private   Static Handlecollector fonthandlecollector =   New Handlecollector ( " Gdifonthandle " , 500 , 1000 );

Internal   Static Intptr createnativefonthandle (Font font)
{
Intptr handle = Font. tohfont ();
If (Handle ! = Intptr. Zero)
{
Fonthandlecollector. Add ();
}
Return Handle;
}

Internal   Static   Bool Deletenativefonthandle (intptr handle)
{
Bool Success = Deleteobject (handle );
If (SUCCESS)
{
Fonthandlecollector. Remove ();
}
Return Success;
}

[System. runtime. interopservices. dllimportattribute ("Gdi32.dll")]
Internal Static Extern BoolDeleteobject (system. intptr gdiobject );
}

3. The weak reference cache class weakreferencecachepool <tkey, titem> is used to cache the safefonthandle. This will not affect the normal garbage collection of safefonthandle by GC, thus releasing the handle of font. For more information about the weak reference cache class weakreferencecachepool <tkey, titem>, see a weak reference cache class.Article.

Code
Internal   Static   Class Safefonthandlefactory
{
# Region Instance data

Private StaticWeakreferencecachepool<Font, safefonthandle>_ Cachepool= NewWeakreferencecachepool<Font, safefonthandle>();

# Endregion

# RegionMethods

Public   Static Safefonthandle createsafefonthandle (Font font)
{
If (Font =   Null )
{
Throw   New Argumentnullexception ();
}

Safefonthandle = _ Cachepool [font];
If (Safefonthandle =   Null )
{
Intptr nativehandle = Safenativemethods. createnativefonthandle (font );
Safefonthandle =   New Safefonthandle (nativehandle, True );
_ Cachepool [font] = Safefonthandle;
}
Return Safefonthandle;
}

# Endregion
}

In this way, the handle of GDI is successfully cached, and after use, the handle of GDI does not linearly increase. As long as GC collection occurs, the handle of GDI is cleared, or when the total number reaches the threshold specified by handlecollector, it is also cleared. The GC garbage collection mechanism is used to automatically balance performance and memory usage.

Here is the test code. The performance test is as follows:

do not use weak reference cache
time elapsed: 350 ms
CPU cycles: 952,061,115
Gen 0: 1
Gen 1: 0
Gen 2: 0
GDI increment: 0

Use Weak reference Cache
Time elapsed: 42 Ms
CPU cycles: 142,020,499
Gen 0: 0
Gen 1: 0
Gen 2: 0
GDI increment: 0

Welcome to shoot bricks...

 

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.