3 回答
TA貢獻(xiàn)1804條經(jīng)驗(yàn) 獲得超3個(gè)贊
我不得不有點(diǎn)不同意:
private float connection[]; private float bias;
第一個(gè)(數(shù)組)是引用類型。換句話說:指向某個(gè)內(nèi)存區(qū)域的(潛在)指針。顯然:只要該指針指向null(“無處”),就不需要額外的內(nèi)存。
但是請不要誤會(huì),您的對象本身需要適合內(nèi)存。意思是:當(dāng)您實(shí)例化一個(gè)新Neuron對象時(shí),JVM 會(huì)請求存儲(chǔ) Neuron 對象所需的內(nèi)存量。這意味著:分配了一些內(nèi)存來容納該數(shù)組引用,當(dāng)然:用于 float原始值的內(nèi)存,它們都是立即分配的。
在該成員字段中存儲(chǔ)的是 0、100.00 還是 10394.283 并不重要:因?yàn)?JVM 確保您有足夠的內(nèi)存來容納所需的位和字節(jié)。
因此:當(dāng)您真的有數(shù)百萬個(gè)對象時(shí),對象中的每個(gè)浮點(diǎn)字段都會(huì)增加 32 位。無論該字段中的值來自何處。
當(dāng)然,如果您的數(shù)組稍后將包含 5、10 或 1000 個(gè)條目,那么這將彌補(bǔ)您的大部分內(nèi)存消耗。但是最初,當(dāng)您剛剛創(chuàng)建數(shù)百萬個(gè)“空”Neuron對象時(shí),您必須為類中存在的每個(gè)字段和任何字段“付費(fèi)”。
意思是:當(dāng) 100 個(gè)Neuron對象中只有 1 個(gè)需要這兩個(gè)字段時(shí),您可以決定:
BaseNeuron沒有所有 4 個(gè)字段的類從該類派生的一個(gè)或多個(gè)類,添加他們需要的字段
還要注意,從設(shè)計(jì)的角度來看,這也是更好的選擇:“空”值總是意味著:額外的代碼來處理它。意思是:如果該數(shù)組可以為空……那么當(dāng)然,所有處理該字段的代碼都必須在使用它之前檢查該數(shù)組是否為空。將其與:一個(gè)沒有該數(shù)組的類與一個(gè)您知道該數(shù)組始終已設(shè)置并準(zhǔn)備好使用的類進(jìn)行比較。
我并不是說你絕對必須改變你的設(shè)計(jì),但正如所解釋的:你可以減少你的內(nèi)存占用,并且你可以通過這樣做使你的設(shè)計(jì)更清晰。
TA貢獻(xiàn)1806條經(jīng)驗(yàn) 獲得超5個(gè)贊
即使沒有在構(gòu)造函數(shù)中使用:
public?Neuron(float[]?connection,?float?bias)?{
????this.connection?=?connection;
????????this.bias?=?bias;
}在執(zhí)行構(gòu)造函數(shù)之前初始化所有實(shí)例字段(so?nameand too)。propability這些是用默認(rèn)值初始化的:
private?String?name;?//?nullprivate?float?propability;?//?0F
但是這些默認(rèn)值沒有任何成本(null和0)。
所以不要為此煩惱。
我有一個(gè)類,我想使用大約 10 到 10 萬個(gè)。因此,我不想不必要地浪費(fèi)內(nèi)存位置。
如果是的話,我是否有另一種選擇(除了讓它們成為自己的類之外)來減少內(nèi)存使用?
如果這些對象有一些公共數(shù)據(jù),則在實(shí)例之間共享這些數(shù)據(jù)。依賴共享數(shù)據(jù)不變性的輕量級模式說明了這種
做法。
對象String使用它。
完全同意 GhostCat 的評論:即使不使用字段也會(huì)消耗內(nèi)存。不多,但他們消耗。但這對于 Java 中的許多類都是正確的。
例如,我們不會(huì)用數(shù)組替換所有列表,因?yàn)閿?shù)組通常消耗較少。我們會(huì)這樣做,因?yàn)樵谖覀兊奶囟ㄇ闆r下,列表內(nèi)存占用是一個(gè)真正令人擔(dān)憂的問題。
綜上所述,在優(yōu)化和改變我們的設(shè)計(jì)之前,我認(rèn)為首先要做的是衡量和判斷你是想優(yōu)化以獲得金子還是堅(jiān)果。
使用您的實(shí)際代碼和main()產(chǎn)生 100 萬個(gè)神經(jīng)元的方法,我注意到大約131 Mo消耗了:
public static void main(String[] args) {
? ? long beforeUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
? ? List<Neuron> neurons = new ArrayList<>();
? ? for (int i = 0; i < 1_000_000; i++) {
? ? ? neurons.add(new Neuron(new float[] { 0, 15.4F, 1.1F, 2.1F, 3.4F, 4.5F, 8.9F, 158.9F, 8648.9F, 80.9F, 10.9F, 1450.9F, 114.9F, 14.5F, 4444.4F }, 1.9F));
? ? }
? ? long afterUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
? ? long actualMemUsed=(afterUsedMem-beforeUsedMem)/1_000_000;
? ? System.out.println(actualMemUsed + " Mo");
? }
客觀的說,低。
通過刪除未使用的字段,它大約下降到124 Mo(更少 7 Mo):
private String name;
private float propability;
131 Mo 和 124 Mo 對于如此多的創(chuàng)建對象來說是相當(dāng)?shù)偷闹担?00 萬。
如果該類聲明了十幾個(gè)未使用的字段,情況就會(huì)有所不同。將浪費(fèi)不可忽略的內(nèi)存量,并且整個(gè)類在設(shè)計(jì)方面根本不明確:低內(nèi)聚性。
但事實(shí)并非如此。
TA貢獻(xiàn)1818條經(jīng)驗(yàn) 獲得超8個(gè)贊
好吧,是的,它們有所不同,但根據(jù)您的用例/jvm 實(shí)現(xiàn)/您擁有的硬件資源,這種不同有多大值得商榷。如果您在具有 500mb 內(nèi)存和 1 個(gè) cpu 的服務(wù)器上運(yùn)行您的應(yīng)用程序并且您的應(yīng)用程序正在以高速率創(chuàng)建這些對象(隨著時(shí)間的推移對象數(shù)量)并且垃圾收集器無法在該速率之后清理,那么最終是的你會(huì)遇到內(nèi)存問題。因此,從技術(shù)上和 Java 語言規(guī)范來看,它們占用內(nèi)存,但實(shí)際上并基于您的用例,這可能不是任何問題。
添加回答
舉報(bào)
