2016-07-23 78 views
2

我最近開發了一個Rust庫,試圖提供對一個大型數據庫(Unicode字符數據庫,作爲一個平面XML文件是160MB)的快速訪問。我也希望它的佔地面積很小,所以我使用了各種方法來減小尺寸。最終的結果是,我有一系列看起來像靜態切片:靜態數據較重的鏽圖書館似乎臃腫

#[derive(Clone,Copy,Eq,PartialEq,Debug)] 
pub enum UnicodeCategory { 
    UppercaseLetter, 
    LowercaseLetter, 
    TitlecaseLetter, 
    ModifierLetter, 
    OtherLetter, 
    NonspacingMark, 
    SpacingMark, 
    EnclosingMark, 
    DecimalNumber, 
    // ... 
} 

pub static UCD_CAT: &'static [((u8, u8, u8), (u8, u8, u8), UnicodeCategory)] = 
    &[((0, 0, 0), (0, 0, 31), UnicodeCategory::Control), 
     ((0, 0, 32), (0, 0, 32), UnicodeCategory::SpaceSeparator), 
     ((0, 0, 33), (0, 0, 35), UnicodeCategory::OtherPunctuation), 
     /* ... */]; 

// ... 

pub static UCD_DECOMP_MAP: &'static [((u8, u8, u8), &'static [(u8, u8, u8)])] = 
    &[((0, 0, 160), &[(0, 0, 32)]), 
     ((0, 0, 168), &[(0, 0, 32), (0, 3, 8)]), 
     ((0, 0, 170), &[(0, 0, 97)]), 
     ((0, 0, 175), &[(0, 0, 32), (0, 3, 4)]), 
     ((0, 0, 178), &[(0, 0, 50)]), 
     /* ... */]; 

總之,所有的數據應該只需要上漲約600KB最大(假設對齊等額外的空間),但所產生的庫3.3MB處於釋放模式。源代碼本身(幾乎所有的數據)是2.6MB,所以我不明白爲什麼結果會更多。我不認爲額外的大小是固有的,因爲在項目開始時大小爲< 50kB(當時我只有大約2kB的數據)。如果它有所作爲,我還使用#![no_std]功能。

是否有任何額外的二元膨脹的原因,有沒有辦法縮小尺寸?理論上我不明白爲什麼我不應該把圖書館減少到不超過兆字節或更少。

按照馬蒂厄的建議下,我試着用nm分析二進制文件。

因爲我所有的表都表示爲借片,這不是計算表的大小,因爲他們都在匿名_ref很多有益的。我可以確定的是最大地址0x1208f8,這與1MB的文件大小相符,而不是3.3MB。我還通過十六進制轉儲查看是否有任何可能解釋它的空塊,但沒有。

要看看它是否是借來的切片是那樣的問題,我把它們變成非借片([T; N]形式)。文件大小沒有太大變化,但現在我可以很容易地解釋數據。奇怪的是,表格佔用了我期望的多少(更奇怪的是,它們在不考慮對齊的情況下匹配我的下限,並且表格之間沒有空間)。

我也看了一下有嵌套借片的表, UCD_DECOMP_MAP以上。當我刪除所有這些數據(大約2/3的數據)時,文件大小應該大約爲1MB〜250kB(通過我的計算和最高的nm地址0x3d1d0),所以它看起來不像這些表也​​是問題。

我試圖提取從.rlib文件中的單個文件(這是一個簡單的ar格式的檔案)。事實證明,該庫的40%只是元數據文件,而實際的目標文件是1.9MB。此外,當我沒有借用引用對圖書館這樣做的目標文件是261kB!然後我又回到了原來的庫,並期待在個人_ref S的大小和發現,對於像UCD_DECOMP_MAP: &'static [((u8,u8,u8),&'static [(u8,u8,u8)])]一個表,((u8,u8,u8),&'static [(u8,u8,u8)])類型的每個值佔用24個字節(對於U8三重3個字節,5個字節的填充和16的字節作爲指針),結果這些表佔用了比我想象中更多的空間。我想我現在可以完全考慮所有的文件大小。

當然,3MB還是相當小的,我只是想盡量保持文件小!

+0

有趣的問題,但診斷這將是更容易的分解*什麼*是採取的空間在這裏,這是不明顯的問題(如果再次,我想如果你有故障的問題會是完全不同的)。因此,我不清楚你希望得到什麼樣的答案。 –

+0

@MatthieuM。我想我想知道是否有任何意想不到的事情發生在幕後,以增加使用的空間。我在[類似的庫](https://github.com/huonw/unicode_names)中注意到他對他的數據使用了'#[inline(never)]',但這不再是合法的語法。生鏽可能會將這些數據嵌入到我使用的每個功能中嗎?我可以使用哪些工具/方法診斷圖書館中的空間故障?對不起,如果問題太不清楚,無法回答! – nitrous

+1

在Linux上,我會使用[nm](http://www.thegeekstuff.com/2012/03/linux-nm-command),但是它需要在輸出上使用一些腳本來獲取每個符號的大小並將其分組每個來源的符號。 –

回答

0

感謝馬修M.和克里斯·愛默生指着我向解決方案。這是問題更新的摘要,抱歉重複!

看來,有兩個原因應該膨脹:

  1. 輸出的.rlib文件不是一個純粹的目標文件,而是一個ar存檔文件。通常這樣的文件將完全由一個或多個目標文件組成,但生鏽還包括元數據。部分原因似乎是爲了避免需要單獨的頭文件。這佔最終文件大小的40%左右。

  2. 我的計算結果並不準確的一些表,這也是最大的。使用nm我能夠發現,對於普通表(如UCD_CAT: &'static [((u8,u8,u8), (u8,u8,u8), UnicodeCategory)]),每個項目的大小爲7個字節(實際上小於我最初預期的,假設對齊爲8個字節)。所有這些表格的總數大約爲230kB,包含這些數據的目標文件在260kB(提取後)中出現,所以這一切都是一致的。

    但是,檢查nm對其他表格(例如UCD_DECOMP_MAP: &'static [((u8,u8,u8),&'static [(u8,u8,u8)])])的更密切輸出更加困難,因爲它們顯示爲匿名借用對象。儘管如此,事實證明,每個((u8,u8,u8),&'static [(u8,u8,u8)])實際上佔用了24個字節:第一個元組爲3個字節,5個字節的填充以及指針的意外的16個字節。我相信這是因爲指針還包含引用數組的大小。這增加了大約一兆字節的圖書館膨脹,但似乎佔整個文件大小。