5.1.1. 程序优化

5.1.1.1. 提供64位版本

  • 寻址能力

    • 32位寻址能力为2的32次方,即4*2^30为4GB。

      其中系统分一半内存(系统空间)以便管理与调度系统各应用程序,还剩2GB可有程序使用(用户空间)。

    • 64位寻址能力则为2的64次方,即16*2^60为16EB。

      当然这个是理论值,目前Windows的实现+的物理内存是16TB左右,也就是44位。

      64位的地址线实际上连64根都不到,只实现了40~50根,因为足够用了,Windows x64版本限制了44位寻址,最大16TB内存,所以造成了所谓的AMD64空洞(用户空间在低位,内核空间在高位,而44位寻址不完全,中间必然有空洞)

  • .NET内存溢出

    处理器/系统 32位操作系统 64位操作系统
    32位进程 800-1200 MB 2800 MB
    与/ 3GB 32位进程 1800 MB N / A
    64位进程 N / A 如果使用的是4 GB的进程或更多,如果更多的内存2800 MB(约的RAM +页面文件70%)
  • x64

    项目 - 属性 - 生成 - 目标平台

    选择x64

5.1.1.2. DataSet无法及时被GC

this.cReportKEY1.EditDataSet.Merge(_ds, false, System.Data.MissingSchemaAction.AddWithKey);
_ds = null;
_ds.Dispose();
GC.Collect();

在_ds.Dispose()前需要显示指定 _ds = null; 以便GC能够及时回收内存

  • 容量提升
    • 与_ds填充的数据量有关,本案例中容量提升了大约30%,由17万提高到22万(黄永慎测)
    • 减少字段数

5.1.1.3. Excel数据导出

采用QueryTable方式,直接从数据库中将数据导入到Excel中

  • 一分钟可以导出约30万条数据(包含210列)(陈家昌测)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;

namespace exportToExcel
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

        int pid = 0;
        Excel.Application m_objExcel = null;
        public Form1()
        {
            InitializeComponent();
            m_objExcel = new Excel.Application();

            GetWindowThreadProcessId(new IntPtr(m_objExcel.Hwnd), out pid);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            string path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "export.xlsx");
            string filename = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, Guid.NewGuid() + ".xlsx");
            System.IO.File.Copy(path, filename);
            query_table_getdata(filename);
            Debug.Write(sw.ElapsedMilliseconds);
            MessageBox.Show(sw.Elapsed.TotalSeconds.ToString());
        }

        public void query_table_getdata(string sourpath)
        {
            Excel.Workbooks m_objBooks = null;
            Excel.Workbook m_objBook = null;
            Excel.Sheets m_objSheets = null;
            Excel.Worksheet m_objSheet = null;
            Excel.Range m_objRange = null;

            m_objExcel.Visible = true;

            string lsConn = "OLEDB;" + @"Provider=SQLOLEDB.1;Data Source=line;uid=sa;Password=******;Initial Catalog=db_hz;Persist Security Info=False;";
            string lsSQL = "Select * from mf_pss";
            
            m_objBooks = m_objExcel.Workbooks;
            string path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, sourpath);
            m_objBook = m_objBooks.Open(path, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

            m_objSheets = (Excel.Sheets)m_objBook.Worksheets;
            m_objSheet = (Excel.Worksheet)m_objSheets.get_Item(1);
            m_objRange = m_objSheet.get_Range("A2", Type.Missing);

            Excel.Range VSTORange = ((Excel.Range)m_objSheet.Cells[1, 1]);

            Excel.ListObject ListObject = m_objSheet.ListObjects.Add(Excel.XlListObjectSourceType.xlSrcExternal,
              ((object)lsConn), false, Excel.XlYesNoGuess.xlYes, VSTORange);
            ListObject.QueryTable.CommandText = ((object)lsSQL);
            ListObject.QueryTable.RowNumbers = false;
            ListObject.QueryTable.FillAdjacentFormulas = false;
            ListObject.QueryTable.PreserveFormatting = true;
            ListObject.QueryTable.RefreshOnFileOpen = false;
            ListObject.QueryTable.BackgroundQuery = true;
            ListObject.QueryTable.SavePassword = false;
            ListObject.QueryTable.SaveData = true;
            ListObject.QueryTable.AdjustColumnWidth = true;
            ListObject.QueryTable.RefreshPeriod = 0;
            ListObject.QueryTable.PreserveColumnInfo = true;
            ListObject.QueryTable.Refresh(false);


            m_objBook.Connections[1].Delete();
            m_objBook.Save();
            // m_objBook.Close(false, Type.Missing, Type.Missing);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            m_objExcel.Quit();
            Process p = Process.GetProcessById(pid);
            p.Kill();
        }
    }
}