JVM中的字符串去重

本文将为你简单介绍一下Java 8 update 20中引入的字符串去重的特性。

从平均情况来看,应用程序中的String对象会消耗大量的内存。这里面有一部分是冗余的——同样的字符串会存在多个不同的实例(a != b, 但a.equals(b))。在实践中,有许多字符串会出于不同的原因造成冗余。

最初JDK提供了一个String.intern()方法来解决字符串冗余的问题。这个方法的缺点在于你必须得去找出哪些字符串需要进行驻留(interned)。这通常都需要一个具备冗余字符串查找功能的堆分析的工具才行,比如[url=http://www.yourkit.com/features/]Youkit profiler[/url]。如果使用得当的话,字符串驻留会是一个非常有效的节省内存的工具——它让你可以重用整个字符串对象(每个字符串对象在底层char[]的基础上会增加24字节的额外开销)。

从Java 7 update 6开始,每个String对象都有一个自己专属的私有char[] 。这样JVM才可以自动进行优化——既然底层的char[]没有暴露给外部的客户端的话,那么JVM就能去判断两个字符串的内容是否是一致的,进而将一个字符串底层的char[]替换成另一个字符串的底层char[]数组。

字符串去重这个特性就是用来做这个的,它在Java 8 update 20中被引入。下面是它的工作原理:

1. 你得使用G1垃圾回收器并启用这一特性:-XX:+UseG1GC -XX:+UseStringDeduplication。这一特性作为G1垃圾回收器的一个可选的步骤来实现的,如果你用的是别的回收器是无法使用这一特性的。

2. 这个特性会在G1回收器的minor GC阶段中执行。根据我的观察来看,它是否会执行取决于有多少空闲的CPU周期。因此,你不要指望它会在一个处理本地数据的数据分析器中会被执行。也就是说,WEB服务器中倒是很可能会执行这个优化。

3. 字符串去重会去查找那些未被处理的字符串,计算它们的hash值(如果它没在应用的代码中被计算过的话),然后再看是否有别的字符串的hash值和底层的char[]都是一样的。如果找到的话——它会用一个新字符串的char[]来替换掉现有的这个char[]。

4. 字符串去重只会去处理那些历经数次GC仍然存活的那些字符串。这样能确保大多数的那些短生命周期的字符串不会被处理。字符串的这个最小的存活年龄可以通过-XX:StringDeduplicationAgeThreshold=3的JVM参数来指定(3是这个参数的默认值)。

下面是这个实现的一些重要的结论:

[*] 没错,如果你想享受字符串去重特性的这份免费午餐的话,你得使用G1回收器。使用parellel GC的话是无法使用它的,而对那些对吞吐量要求比延迟时期高的应用而言,parellel GC应该是个更好的选择。

[*] 字符串去重是无法在一个已加载完的系统中运行的。要想知道它是否被执行了,可以通过-XX:+PrintStringDeduplicationStatistics参数来运行JVM,并查看控制台的输出。

[*] 如果你希望节省内存的话,你可以在应用程序中将字符串进行驻留(interned)——那么放手去做吧,不要依赖于字符串去重的功能。你需要时刻注意的是字符串去重是要处理你所有的字符串的(至少是大部分吧)——也就是说尽管你知道某个指定的字符串的内容是唯一的(比如说GUID),但JVM并不知道这些,它还是会尝试将这个字符串和其它的字符串进行匹配。这样的结果就是,字符串去重所产生的CPU开销既取决于堆中字符串的数量(将新的字符串和别的字符串进行比较),也取决于你在字符串去重的间隔中所创建的字符串的数量(这些字符串会和堆中的字符串进行比较)。在一个拥有好几个G的堆的JVM上,可以通过-XX:+PrintStringDeduplicationStatistics选项来看下这个特性所产生的影响究竟有多大。

[*] 另一方面,它基本是以一种非阻塞的方式来完成的,如果你的服务器有足够多的空闲CPU的话,那为什么不用呢?

[*] 最后,请记住,String.intern可以让你只针对你的应用程序中指定的某一部分已知会产生冗余的字符串。通常来说,它只需要比较一个较小的驻留字符串的池就可以了,也就是说你可以更高效地使用你的CPU。不仅如此,你还可以将整个字符串对象进行驻留,这样每个字符串你还多节省了24个字节。

这里是我用来试验这一特性的一个测试类。这三个测试都会一直运行到JVM抛出OOM为止,因此你得分别去单独地运行它们。


第一个测试会创建内容一样的字符串,如果你想知道当堆中字符串很多的时候,字符串去重会花掉多少时间的话,这个测试就变得非常有用了。尽量给第一个测试分配尽可能多的内存——它创建的字符串越多,优化的效果就越好。

第二三个测试会比较去重(第二个测试)及驻留(interning, 第三个测试)间的差别。你得用一个相同的Xmx设置来运行它们。在程序中我把这个常量设置成了Xmx256M,但是当然了,你可以分配得多点。然而,你会发现,和interning测试相比,去重测试会更早地挂掉。这是为什么?因为我们在这组测试中只有100个不同的字符串,因此对它们进行驻留就意味着你用到的内存就只是存储这些字符串所需要的空间。而字符串去重的话,会产生不同的字符串对象,它仅会共享底层的char[]数组。





/**
* String deduplication vs interning test
*/
public class StringDedupTest {
private static final int MAX_EXPECTED_ITERS = 300;
private static final int FULL_ITER_SIZE = 100 * 1000;

//30M entries = 120M RAM (for 300 iters)
private static List<String> LIST = new ArrayList<>( MAX_EXPECTED_ITERS * FULL_ITER_SIZE );

public static void main(String[] args) throws InterruptedException {
//24+24 bytes per String (24 String shallow, 24 char[])
//136M left for Strings

//Unique, dedup
//136M / 2.9M strings = 48 bytes (exactly String size)

//Non unique, dedup
//4.9M Strings, 100 char[]
//136M / 4.9M strings = 27.75 bytes (close to 24 bytes per String + small overhead

//Non unique, intern
//We use 120M (+small overhead for 100 strings) until very late, but can't extend ArrayList 3 times - we don't have 360M

/*
Run it with: -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics
Give as much Xmx as you can on your box. This test will show you how long does it take to
run a single deduplication and if it is run at all.
To test when deduplication is run, try changing a parameter of Thread.sleep or comment it out.
You may want to print garbage collection information using -XX:+PrintGCDetails -XX:+PrintGCTimestamps
*/

//Xmx256M - 29 iterations
fillUnique();

/*
This couple of tests compare string deduplication (first test) with string interning.
Both tests should be run with the identical Xmx setting. I have tuned the constants in the program
for Xmx256M, but any higher value is also good enough.
The point of this tests is to show that string deduplication still leaves you with distinct String
objects, each of those requiring 24 bytes. Interning, on the other hand, return you existing String
objects, so the only memory you spend is for the LIST object.
*/

//Xmx256M - 49 iterations (100 unique strings)
//fillNonUnique( false );

//Xmx256M - 299 iterations (100 unique strings)
//fillNonUnique( true );
}

private static void fillUnique() throws InterruptedException {
int iters = 0;
final UniqueStringGenerator gen = new UniqueStringGenerator();
while ( true )
{
for ( int i = 0; i < FULL_ITER_SIZE; ++i )
LIST.add( gen.nextUnique() );
Thread.sleep( 300 );
System.out.println( "Iteration " + (iters++) + " finished" );
}
}

private static void fillNonUnique( final boolean intern ) throws InterruptedException {
int iters = 0;
final UniqueStringGenerator gen = new UniqueStringGenerator();
while ( true )
{
for ( int i = 0; i < FULL_ITER_SIZE; ++i )
LIST.add( intern ? gen.nextNonUnique().intern() : gen.nextNonUnique() );
Thread.sleep( 300 );
System.out.println( "Iteration " + (iters++) + " finished" );
}
}

private static class UniqueStringGenerator
{
private char upper = 0;
private char lower = 0;

public String nextUnique()
{
final String res = String.valueOf( upper ) + lower;
if ( lower < Character.MAX_VALUE )
lower++;
else
{
upper++;
lower = 0;
}
return res;
}

public String nextNonUnique()
{
final String res = "a" + lower;
if ( lower < 100 )
lower++;
else
lower = 0;
return res;
}
}
}





[b]总结[/b]


Java 8 update 20中添加了字符串去重的特性。它是G1垃圾回收器的一部分,因此你必须使用G1回收器才能启用它:-XX:+UseG1GC -XX:+UseStringDeduplication。

[*] 字符串去重是G1的一个可选的阶段。它取决于当前的系统负载。
[*] 字符串去重会查询内容相同的那些字符串,并将它们底层存储字符的char[]数组进行统一。使用这一特性你不需要写任何代码,不过这意味着最后你得到的是不同的字符串对象,每个对象会占用24个字节。有的时候显式地调用String.intern进行驻留还是有必要的。
[*] 字符串去重不会对年轻的字符串进行处理。字符串处理的最小年龄是通过-XX:StringDeduplicationAgeThreshold=3的JVM参数来进行管理的(3是这个参数的默认值)。

原创文章转载请注明出处:[url=http://it.deepinmind.com/jvm/2014/09/17/java-string-deduplication.html]Java译站[/url]


[url=http://java-performance.info/java-string-deduplication/]英文原文链接[/url]
JVM字符串去重-内存优化利器 string deduplication即字符串去重是JDK在1.8提供的功能,目的是减少相同内容字符串的内存占用,相同内容是指equals为true的两个字符串。 目前只有在使用G1收集器的情况下才能开启,默认不开启,开启方法为增加 启动参数。java.lang.String字符串对象的数据保存在内部的byte[] value即一个名为value的byte数组中 在一次gc之后,回收的heap区域中的活对象(live objects)都会被访问一遍,对于每个string对象, 我们都会查看是否能够进行de 阅读详情

相关推荐

Java8新特性之字符串去重介绍

主要介绍了Java8新特性之字符串去重介绍,新的字符串去重特性可以帮助减少应用中String对象的内存占用,目前该特性只适用于G1垃圾收集器,并且默认不被开启,需要的朋友可以参考下

JVM常用启动参数大全(附带解释)

目录 一、官网 二、堆相关 三、方法区相关 四、执行引擎相关 五、垃圾回收相关 六、内存分配与垃圾回收的参数列表 一、官网 官网说明:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html 查看jvm启动参数:jinfo -flag NewRatio pid 二、堆相关 -XX:+PrintFlagsInitial:查看所有的参数的默认初始值 -XX:+PrintFlagsFinal:查看所有的参数的最终

秃了也弱了 2508

Java中字符串去重的特性介绍

主要介绍了Java中字符串去重的特性,是Java8中引入的一个新特性,至于是否真的用起来顺手就见仁见智了...需要的朋友可以参考下

Java 8新特性:字符串去重

8月19日,Oracle发布了JDK 8u20,JDK 8u20包含很多新特性,比如Java编译器更新、支持在运行时通过API来修改MinHeapFreeRatio和MaxHeapFreeRatio参数、新的GC调优指南文档。不过在众多新特性中,最令人期待的还属字符串去重(String Deduplication )。如何减少内存占用一直是一个永恒的话题,而在Java应用中,经常会看到Stri

dingxingmei的专栏 1604

无限维李代数局部与2-局部1/2-导子:从概念到Witt代数实例解析

在抽象代数与数学物理中,李代数是描述对称性的基本结构,而导子则是刻画其微分性质的核心算子。从经典的导子概念出发,通过引入“局部”与“分数阶”两个关键推广,形成了局部导子、2-局部导子以及1/2-导子等重要研究方向。这些推广不仅深化了对无限维李代数(如Witt代数、Virasoro代数)复杂结构的理解,其研究方法和结论也为共形场论、可积系统等物理理论提供了数学基础。本文聚焦于无限维李代数上局部与2-局部1/2-导子的系统研究,通过拆解核心概念、剖析典型代数结构,并以Witt代数为实例,详细演示了从全局1/2-

weixin_34072296的博客 392

Gemini 3.1 Flash本地部署实操:Ollama+Open WebUI零门槛运行指南

大型语言模型(LLM)本地运行是指将模型权重下载至本地设备,通过推理引擎完成离线推理的过程;其核心原理依赖量化压缩(如GGUF格式)与轻量级运行时(如Ollama)实现CPU/GPU高效加载;技术价值在于低延迟响应、数据隐私可控及免网络依赖;典型应用场景包括办公提效(邮件/周报生成)、学生学习辅助、产品原型验证等边缘AI任务;本文聚焦Gemini 3.1 Flash这一面向消费级硬件优化的轻量模型变体,结合Ollama模型管理与Open WebUI图形界面,提供从环境准备、模型拉取到流式对话的完整新手实操路

weixin_32238157的博客 492

JVM学习-G1回收器

1.简介 定义: Garbage First JDK 9以后默认使用,而且替代了CMS 收集器 适用场景 同时注重吞吐量和低延迟(响应时间),默认暂停目标是200ms 超大堆内存(内存大的),会将堆内存划分为多个大小相等的区域 整体上是标记-整理算法,两个区域之间是复制算法 它整体上使用标记整理算法,可以避免CMS垃圾回收器的标记清除算法产生的内存碎片问题。 它也属于并发的垃圾回收器 相关JVM参数 -XX:+UseG1GC -XX:G1HeapRegionSize=size 设置区域大小,区域要设置成1,

Java硬件工程师的博客 2112

别再为下载速度发愁了!手把手教你给qBittorrent/Transmission添加最新可用Tracker(附2024年实测地址清单)

本文提供2024年BT下载加速实战指南,详细解析Tracker工作原理与速度瓶颈,手把手教你为qBittorrent/Transmission添加最新可用Tracker,并附实测地址清单。通过优化配置和精选Tracker列表,显著提升下载速度和稳定性,解决连接延迟和peer数量限制问题。

weixin_28481133的博客 1262

JVM G1源码分析——字符串去重

字符串是我们日常开发使用最多的类型。字符串去重目的是优化字符串对象的内存使用,因为从统计数据上看,应用程序中的String对象会消耗大量的内存。这里面有一部分是冗余的,即同样的字符串会存在多个不同的实例(a!=b,但a.equals(b))。最初JDK提供了一个String.intern()方法来解决字符串冗余的问题。这个方法的缺点在于你必须去找出哪些字符串需要进行驻留(interned)。如果使用得当的话,字符串驻留会是一个非常有效地节省内存的工具,它让你可以重用整个字符串对象。

qq_16500963的博客 736

华为iTrustee实战:5分钟搞定TrustZone环境搭建(附BoostKit配置技巧)

本文提供了一份华为iTrustee与ARM TrustZone环境的5分钟快速搭建实战指南。详细介绍了在TaiShan服务器上利用鲲鹏BoostKit套件部署可信执行环境(TEE)的完整流程,包括环境检查、驱动安装、首个可信应用(TA)的编译与运行,并分享了关键的BoostKit配置技巧与深度排错方法,助力开发者快速为业务注入硬件级安全能力。

yoga7的博客 966

Centos7安装Tesseract5.5.0+SpringBoot集成部署(离线版)

Java 中实现 OCR(光学字符识别)功能,可以使用 Tesseract OCR,这是一个开源的 OCR 引擎,支持多种语言,并且可以在 Java 中通过 Tesseract API 进行集成。

Leopard锋的博客 2320

JVM StringTable拆解:字符串常量池、intern与G1去重

在Java内存结构与JVM调优中,字符串常量池常被简称为“池子”,但其底层是HotSpot特化的StringTable哈希表,用于保存已驻留字符串引用,并直接影响堆内存占用与垃圾回收行为。StringTableSize决定桶数量,String.intern()的入池路径和回收时机决定重复字符串能否被归并;G1的字符串去重则从底层byte[]/char[]数组合并入手降低重复内容开销。对订单地址、备注、跳转链接、日志与协议解析等运行时拼接多、重复率高的场景,合理理解StringTable、intern与去重参

weixin_32612263的博客 297

Tribon Vitesse开发教程(一)

Tribon Vitesse简介 Tribon Vitesse是Tribon提供给Python编程语言的编程接口,它是一系列的API。使用Python的语法调用这些API,结合Python语言自身的语法生成的程序叫做Vitesse程序。Vitesse是法语“速度”的意思,读作“为戴斯”。使用Tribon Vitesse可以直接访问Tribon产品信息模型和使用Tribon应用程序的功能,以控制设计

forevermemory的专栏 2593

StringTable不是字符串常量池:JVM运行时字符串去重机制深度解析

字符串去重是Java高频内存优化场景,其底层依赖JVM运行时的StringTable结构——一个独立于堆和Metaspace、由C++管理的哈希表。它通过哈希计算与桶级锁实现O(1)平均查找,支撑字面量自动入池与intern()显式入池,核心价值在于规避GC开销与类元数据耦合。典型应用场景包括日志归一化、路由键标准化、状态码缓存等,但因‘只进不出’特性易引发内存泄漏。本文聚焦StringTable的内存布局、哈希碰撞、锁竞争及监控调优,结合jcmd native_memory与jmap histo等生产级诊

weixin_33462927的博客 284

【ZZULIOJ】郑州轻工业大学oj题解整合

写在前面 关于ZZULIOJ题解 学习编程,想要巩固无非就是刷题或者做项目,然后因为我大一开始是刷郑轻的题目,就想着自己整合一下自己写的题目。既是复习也是笔记吧。 题解(内有题目描述) 1000 整数a+b 1001 植树问题 1002 简单多项式求值 1003 两个整数的四则运算 1004 三位数的数位分离 1005 整数幂 1006 求等差数列的和 1007 鸡兔同笼 1008 美元和人民币 1009 求平均分 1010 求圆的周长和面积 1011 圆柱体表面积 1012 求绝对值 1013 求两点间

蒟蒻乱写的博客 29万+

C++实现复制粘贴文本功能

要实现这个功能,我们需要使用操作系统提供的函数来操作剪贴板。在Windows操作系统中,我们可以使用Windows API函数来访问剪贴板。总结起来,使用C++实现复制和粘贴文本功能涉及使用操作系统提供的API函数来操作剪贴板。在本篇文章中,我将向您展示如何使用C++编程语言实现复制和粘贴文本的功能。我们将使用操作系统提供的API来进行剪贴板操作,并编写相应的代码来完成这个任务。如果您使用的是Linux操作系统,您需要使用适当的库和函数来访问剪贴板。函数中,我们首先将一个字符串复制到剪贴板中,然后使用。

PixelDyno的博客 1233

《剑指JVM》——第12章——G1中的String去重操作——字符串常量池3

🔥本篇概览:详细讲解了G1中的String去重操作——字符串常量池3。🌈⭕🔥

做一个善良的人,做好自己的事,如果愿意,再发一份光。 819

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

JVM G1 GC字符串去重StringDeduplication在ZGC中实现差异?StringTable与ZGC并发标记集成

G1 GC 和 ZGC 在字符串去重的实现上采用了不同的策略。G1 GC 依赖于 GC 周期,需要在 STW 暂停期间进行处理,而 ZGC 则实现了完全并发的去重,对应用性能影响更小。StringTable 在 ZGC 中扮演了更重要的角色,通过细粒度锁、读写屏障和版本控制等机制,实现了与并发标记的紧密集成。选择哪种 GC,需要权衡内存占用、STW 时间和实现复杂度等因素,以满足应用的特定需求。

weixin_41455464的博客 655

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

AggressiveOpts UseStringDeduplication 加快编译与字符串去重

-XX:+AggressiveOpts -XX:+UseStringDeduplication 加快编译 字符串去重 -XX:StringDeduplicationAgeThreshold 默认情况下,一个字符串对象经过3次GC以后还存活才会被列为去重的候选对象,可以用-XX:StringDeduplicationAgeThreshold来改变经历的GC的次数 -XX:+UseStringDeduplication并不会消除重复字符串的引用本身,它只会替换底层的char[],消除重复字符串...

kissraininglxc的专栏 985

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

JAV 中JVM对于字符串常量池膨胀的解决办法

摘要: 现代JVM通过多重机制优化字符串常量池内存管理,避免其无限制膨胀。关键优化包括:将常量池从永久代迁移至堆内存以纳入GC管理;引入字符串自动去重技术减少冗余;编译期和运行期自动去重;元空间替代永久代提升灵活性;以及GC对无引用常量的主动回收。这些机制有效防止常量池内存占用过高问题,仅在程序频繁创建大量唯一且长期引用的字符串时可能出现内存压力。开发者可通过JVM参数进一步优化常量池性能。

qq_46170459的博客 1033

java string 特性_Java中字符串去重的特性介绍

字符串在任何应用中都占用了大量的内存。尤其数包含独立UTF-16字符的char[]数组对JVM内存的消耗贡献最多——因为每个字符占用2位。内存的30%被字符串消耗其实是很常见的,不仅是因为字符串是与我们互动的最好的格式,而且是由于流行的HTTP API使用了大量的字符串。使用Java 8 Update 20,我们现在可以接触到一个新特性,叫做字符串去重,该特性需要G1垃圾回收器,该垃圾回收器默认是...

weixin_34278722的博客 527

JVM StringTable调优实战:intern原理、StringTableSize与G1去重

字符串常量池是Java内存模型里常被搜索的基础概念,底层通过全局哈希表完成字符串归一去重,理解其桶数组与链表查找原理,能解释new String、字面量和String.intern的差异。合理设置StringTableSize可降低哈希冲突和CPU热点,G1字符串去重则通过共享底层数组减少重复字符内存。这些能力在日志采集、缓存Key、协议字段等场景直接影响GC表现与内存占用。围绕参数估算、日志统计、堆快照定位和踩坑案例,梳理StringTable从结构到线上调优的完整实践链路。

weixin_34098209的博客 230

G1 GC:一个神奇的 JVM 参数,减少你的内存消耗

点击上方蓝色字体,选择“设为星标”优质文章,及时送达现代 Java 应用程序有大量的字符串操作,例如,Web 服务 API 调用(JSON、REST、SOAP 等)、外部...

涤生的博客 2934

Java中的字符串存储方式

1. 简介 十一放假期间在脉脉上看见一道面试题讨论的很火热: Java中字符串是如何存储的? 这一问题看似简单,但是背后却隐藏了很多深层机制,本文将逐一介绍相关技术原理。 2. 字符串类 字符串广泛应用于Java编程中,在Java中字符串属于对象,Java提供了String 类来创建和操作字符串。 2.1 java.lang.String java.lang.String成员变量如下: pub...

860MHz的专栏 1415

JVM系列之:String.intern的性能

文章目录简介String.intern和G1字符串去重的区别String.intern的性能举个例子 简介 String对象有个特殊的StringTable字符串常量池,为了减少Heap中生成的字符串的数量,推荐尽量直接使用String Table中的字符串常量池中的元素。 那么String.intern的性能怎么样呢?我们一起来看一下。 String.intern和G1字符串去重的区别 之前我们提到了,String.intern方法会返回字符串常量池中的字符串对象的引用。 而G1垃圾回收器的字符串去重的功

程序那些事 2万+

字符串常量池与对象重用对 JVM 内存占用的优化

微服务常驻物理内存(RSS):从原本的12.5 GB 骤降至 6.8 GB(堆内存直接瘦身 45.6%!;年轻代垃圾产生速率(Allocation Rate):从每秒 1.2 GB/s 减缓至450 MB/s;全天 GC 发生总次数:减少了整整62%,接口 P99 响应延迟由于内存争用大幅削减而进一步缩短25%。

dicky_zhang3的博客 608
上一篇: 不同的垃圾回收器的比较
下一篇: Java代码中的常见问题
spidercoco
博客等级 码龄18年 47粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值