Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JVM性能调优实践(二)——G1 垃圾收集器分析、调优篇

JVM性能调优实践(二)——G1 垃圾收集器分析、调优篇

作者头像
周三不加班
发布于 2019-09-03 02:49:22
发布于 2019-09-03 02:49:22
2.4K00
代码可运行
举报
文章被收录于专栏:程序猿杂货铺程序猿杂货铺
运行总次数:0
代码可运行

1前言

关于G1 GC以及其他垃圾收集器的介绍可以参考前一篇JVM性能调优实践——G1 垃圾收集器介绍篇。了解了G1垃圾收集器的运行机制之后,就可以针对一些GC相关参数来调整内存分配以及运行策略。下文的调优主要针对G1垃圾收集器进行介绍,以及会分析一下G1 GC的日志格式。

2G1 GC日志分析

在执行具体的调优任务前,需要结合GC日志以及应用本身的特点。打印详细GClog,需要添加如下启动参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps

本文使用的Java version:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) 

下面截取gc.log 中的一次YoungGC和一次MixedGC。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2018-05-26T19:51:45.808-0800: 127.031: [GC pause (G1 Evacuation Pause) (young), 0.0063650 secs]
   [Parallel Time: 5.5 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 127030.7, Avg: 127030.7, Max: 127030.7, Diff: 0.0]
      [Ext Root Scanning (ms): Min: 1.1, Avg: 1.3, Max: 1.5, Diff: 0.4, Sum: 5.3]
      [Update RS (ms): Min: 1.3, Avg: 1.4, Max: 1.4, Diff: 0.1, Sum: 5.4]
         [Processed Buffers: Min: 3, Avg: 12.5, Max: 24, Diff: 21, Sum: 50]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.1, Avg: 0.3, Max: 0.7, Diff: 0.5, Sum: 1.3]
      [Object Copy (ms): Min: 2.2, Avg: 2.4, Max: 2.5, Diff: 0.4, Sum: 9.5]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Termination Attempts: Min: 1, Avg: 1.8, Max: 3, Diff: 2, Sum: 7]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.0, Sum: 0.1]
      [GC Worker Total (ms): Min: 5.4, Avg: 5.4, Max: 5.4, Diff: 0.1, Sum: 21.6]
      [GC Worker End (ms): Min: 127036.1, Avg: 127036.1, Max: 127036.1, Diff: 0.0]
   [Code Root Fixup: 0.1 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.1 ms]
   [Other: 0.6 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.3 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 39.0M(39.0M)->0.0B(2048.0K) Survivors: 3072.0K->4096.0K Heap: 111.4M(128.0M)->72.9M(128.0M)]
 [Times: user=0.02 sys=0.00, real=0.01 secs] 

2018-05-26T19:57:20.534-0800: 461.748: [GC pause (G1 Evacuation Pause) (mixed), 0.0685311 secs]
   [Parallel Time: 67.2 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 461748.1, Avg: 461748.1, Max: 461748.1, Diff: 0.0]
      [Ext Root Scanning (ms): Min: 0.8, Avg: 2.6, Max: 7.5, Diff: 6.6, Sum: 10.5]
      [Update RS (ms): Min: 0.0, Avg: 0.3, Max: 0.7, Diff: 0.7, Sum: 1.4]
         [Processed Buffers: Min: 0, Avg: 9.2, Max: 35, Diff: 35, Sum: 37]
      [Scan RS (ms): Min: 29.7, Avg: 34.3, Max: 36.1, Diff: 6.5, Sum: 137.1]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.5, Max: 0.8, Diff: 0.8, Sum: 2.0]
      [Object Copy (ms): Min: 28.8, Avg: 29.3, Max: 29.8, Diff: 1.0, Sum: 117.1]
      [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.3]
         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 4]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [GC Worker Total (ms): Min: 67.1, Avg: 67.1, Max: 67.1, Diff: 0.0, Sum: 268.5]
      [GC Worker End (ms): Min: 461815.2, Avg: 461815.2, Max: 461815.2, Diff: 0.0]
   [Code Root Fixup: 0.3 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.1 ms]
   [Other: 1.0 ms]
      [Choose CSet: 0.4 ms]
      [Ref Proc: 0.2 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.2 ms]
   [Eden: 5120.0K(5120.0K)->0.0B(57.0M) Survivors: 1024.0K->1024.0K Heap: 64.3M(128.0M)->55.8M(128.0M)]
 [Times: user=0.07 sys=0.11, real=0.07 secs] 

两个收集过程的日志格式相似。先以young gc为例,分析一下日志信息。

3GC并行任务

并行任务部分主要包含Parallel Time这一行以及其下面的详细任务信息。

[Parallel Time: GC Workers]

[Parallel Time: 5.9 ms, GC Workers: 4] 这一行标记着并行阶段的汇总信息。总共花费时间以及GC的工作线程数。

后续的这两行,start-end是时间戳信息。Diff是偏移平均时间的值。Diff越小越好,说明每个工作线程的速度都很均匀,如果Diff值偏大,就要看下面具体哪一项活动产生的波动。Avg代表平均时间值。如果Avg跟Min,Max偏差不大是比较正常的,否则也要详细分析具体的偏差值大的任务。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[GC Worker Start (ms): Min: 127030.7, Avg: 127030.7, Max: 127030.7, Diff: 0.0]
[GC Worker End (ms): Min: 127036.1, Avg: 127036.1, Max: 127036.1, Diff: 0.0]

下一段显示的是详细的并行阶段的GC活动。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Ext Root Scanning (ms): Min: 1.1, Avg: 1.3, Max: 1.5, Diff: 0.4, Sum: 5.3]
      [Update RS (ms): Min: 1.3, Avg: 1.4, Max: 1.4, Diff: 0.1, Sum: 5.4]
         [Processed Buffers: Min: 3, Avg: 12.5, Max: 24, Diff: 21, Sum: 50]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.1, Avg: 0.3, Max: 0.7, Diff: 0.5, Sum: 1.3]
      [Object Copy (ms): Min: 2.2, Avg: 2.4, Max: 2.5, Diff: 0.4, Sum: 9.5]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Termination Attempts: Min: 1, Avg: 1.8, Max: 3, Diff: 2, Sum: 7]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.0, Sum: 0.1]
      [GC Worker Total (ms): Min: 5.4, Avg: 5.4, Max: 5.4, Diff: 0.1, Sum: 21.6]

Ext Root Scanning

外部根区扫描。外部根是堆外区。JNI引用,JVM系统目录,Classloaders等。后面跟着具体的时间信息。

RSet的处理

log中RS指的是RSet。RSet详细信息可以看G1 GC介绍。

  • UpdateRS:更新RSet的时间信息。-XX:MaxGCPauseMillis参数是限制G1的暂停之间,一般RSet更新的时间小于10%的目标暂停时间是比较可取的。如果花费在RSetUpdate的时间过长,可以修改其占用总暂停时间的百分比-XX:G1RSetUpdatingPauseTimePercent。这个参数的默认值是10。
  • Processed Buffers:已处理缓冲区。这个阶段处理的是在优化线程中处理dirty card分区扫描时记录的日志缓冲区。
  • Scan RS:前一篇文章也提到了,关于RSet的粒度。如果RSet中的Bitmap是粗粒度的,那么就会增加RSet扫描的时间。如下所示的扫描时间,说明还没有粗化的RSet
  • Code Root Scanning:代码跟的扫描。只有在分区的RSet有强代码根时会检查CSet的对内引用,例如常量池。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 [Update RS (ms): Min: 1.3, Avg: 1.4, Max: 1.4, Diff: 0.1, Sum: 5.4]
         [Processed Buffers: Min: 3, Avg: 12.5, Max: 24, Diff: 21, Sum: 50]

   [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.1, Avg: 0.3, Max: 0.7, Diff: 0.5, Sum: 1.3]  

如果观察到RS的处理时间较长,可以使用-XX:+G1SummarizeRSetStats参数,在GC结束后打印RSet的详细信息。一般在debug环境排查用。还有一个辅助参数G1SummarizeRSetStatsPeriod=0用来控制第几次GC后统计一次RSet信息。

Object Copy

Object Copy:该任务主要是对CSet中存活对象进行转移(复制)。对象拷贝的时间一般占用暂停时间的主要部分。如果拷贝时间和”预测暂停时间“有相差很大,也可以调整年轻代尺寸大小。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 [Object Copy (ms): Min: 2.2, Avg: 2.4, Max: 2.5, Diff: 0.4, Sum: 9.5] 

Termination

这里的终止主要是终止工作线程。Work线程在工作终止前会检查其他工作线程的任务,如果其他work线程有没完成的任务,会抢活。如果终止时间较长,额能是某个work线程在某项任务执行时间过长。

GC Worker Other

花在GC之外的工作线程的时间,比如因为JVM的某个活动,导致GC线程被停掉。这部分消耗的时间不是真正花在GC上,只是作为log的一部分记录。

GC Work Total

并行阶段的GC汇总,包含了GC以及GC Worker Other的总时间。

GC 串行活动

一下是串行的GC活动。包括代码根的更新和扫描。Clear的时候还要清理RSet相应去除的Card Table信息。G1 GC在扫描Card信息时会有一个标记记录,防止重复扫描同一个Card。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   [Code Root Fixup: 0.1 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.1 ms]

GC Other活动

剩余的部分就是其他GC活动了。主要包含:选择CSet、引用处理和排队、卡片重新脏化、回收空闲巨型分区以及在收集之后释放CSet。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Other: 0.6 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.3 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
  • Choose CSet:选择CSet,因为年轻代的所有分区都会被收集,所以CSet不需要选择,消耗时间都是0ms。Choose CSet任务一般都是在mixed gc的过程中触发。
  • Ref Proc、Enq: 引用处理主要针对弱引用,软引用,徐引用,final,JNI引用。将这些引用排列到相应的reference队列中。
  • Redirty Cards:重新脏化卡片。排队引用可能会更新RSet,所以需要对关联的Card重新脏化(Redirty Cards)。
  • Humongous Register、Reclaim主要是对巨型对象回收的信息,youngGC阶段会对RSet中有引用的短命的巨型对象进行回收,巨型对象会直接回收而不需要进行转移(转移代价巨大,也没必要)。
  • Free CSet:释放CSet,其中也会清理CSet中的RSet

4垃圾结果收集统计

如下对比了一次youngGC和一次mixedGC的垃圾收集结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
young: [Eden: 39.0M(39.0M)->0.0B(2048.0K) Survivors: 3072.0K->4096.0K Heap: 111.4M(128.0M)->72.9M(128.0M)]

mixed: [Eden: 5120.0K(5120.0K)->0.0B(57.0M) Survivors: 1024.0K->1024.0K Heap: 64.3M(128.0M)->55.8M(128.0M)]
  • Eden: 39.0M(39.0M)->0.0B(2048.0K): Eden分区GC前39M,GC后是0。括号里面的分别是GC前后Eden分区的总大小。可以看到在一次GC后,Eden的空间做了调整。G1 GC的暂停时间是可预测的,所以YoungGC之后,会根据pause time的目标重新计算需要的Eden分区数,进行动态调整。
  • Survivors: 3072.0K->4096.0K。Survivors空间的变化,空间增长了,说明有存活对象E区晋升到S区。
  • Heap: 111.4M(128.0M)->72.9M(128.0M)。整个堆区的GC前后空间数据,G1 GC会动态调整堆区,但这次回收中没有改变堆区的容量。

5G1 CC相关参数

G1 GC是垃圾收集优先的垃圾收集器,同时有着”可预期的暂停时间“,垃圾收集过程是分代的,但堆空间是基于分区进行分配。所以整体的空间利用率,时间效率都有更大的提升。G1的YoungGC和MixedGC以及并发标记阶段都有很多机制可以控制触发时机,一般情况是不建议过度更改官方建议参数。但默认参数不一定适用于所有应用,调优前需要有明确的目标,或者问题处理思路。

以下先整理下G1垃圾收集器可以调整的重要参数:

  • -XX:+UseG1GC:启用 G1 (Garbage First) 垃圾收集器
  • -XX:MaxGCPauseMillis:设置允许的最大GC停顿时间(GC pause time),这只是一个期望值,实际可能会超出,可以和年轻代大小调整一起并用来实现。默认是200ms。
  • -XX:G1HeapRegionSize:每个分区的大小,默认值是会根据整个堆区的大小计算出来,范围是1M~32M,取值是2的幂,计算的倾向是尽量有2048个分区数。比如如果是2G的heap,那region=1M。16Gheap,region=8M。
  • -XX:MaxTenuringThreshold=n:晋升到老年代的“年龄”阀值,默认值为 15。
  • -XX:InitiatingHeapOccupancyPercent:一般会简写IHOP,默认是45%,这个占比跟并发周期的启动相关,当空间占比达到这个值时,会启动并发周期。如果经常出现FullGC,可以调低该值,尽早的回收可以减少FullGC的触发,但如果过低,则并发阶段会更加频繁,降低应用的吞吐。
  • -XX:G1NewSizePercent:年轻代最小的堆空间占比,默认是5%。
  • -XX:G1MaxNewSizePercent:年轻代最大的堆空间占比,默认是60%。
  • -XX:ConcGCThreads:并发执行的线程数,默认值接近整个应用线程数的1/4。
  • -XX:-XX:G1HeapWastePercent:允许的浪费堆空间的占比,默认是5%。如果并发标记可回收的空间小于5%,则不会触发MixedGC。
  • -XX:G1MixedGCCountTarget:一次全局并发标记之后,后续最多执行的MixedGC次数。 默认值是8.

6G1 CC 相关调优建议

01

年轻代调优

因为G1 GC是启发式算法,会动态调整年轻代的空间大小。目标也就是为了达到接近预期的暂停时间。年轻代调优中比较重要的就是对暂停时间的处理。一般都是根据MaxGCPauseMillis以及年轻代占比G1NewSizePercent、G1MaxNewSizePercent,结合应用的特点和GC数据进行接近期望pause time的调整。为了能观察到详细的暂停时间信息,可以添加调试的启动参数-XX:+PrintAdaptiveSizePolicy。

下面摘取一段youngGC gc log的输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 26.139: [GC pause (G1 Evacuation Pause) (young) 26.139: [G1Ergonomics (CSet Construction) start choosing CSet, _pending_cards: 3484, predicted base time: 5.51 ms, remaining time: 194.49 ms, target pause time: 200.00 ms]
 26.139: [G1Ergonomics (CSet Construction) add young regions to CSet, eden: 54 regions, survivors: 9 regions, predicted young region time: 5.98 ms]
 26.139: [G1Ergonomics (CSet Construction) finish choosing CSet, eden: 54 regions, survivors: 9 regions, old: 0 regions, predicted pause time: 11.49 ms, target pause time: 200.00 ms]
, 0.0163685 secs]

target也即目标是200ms,实际的pause time是16ms。远远小于目标暂停时间。并且再CSet中的分区数是“eden: 54 regions, survivors: 9 regions”,可以适当增加CSet中的年轻代分区,也可以适当缩短暂停时间,让实际值和期望值不断接近。

02

并发标记和MiniGC调优

InitiatingHeapOccupancyPercent就是触发并发标记的一个决定阀值。当Java堆空间占用到45%便开启并发周期。并发标记的初始标记阶段伴随着一次YoungGC的暂停。会看到如下log记录:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2018-05-26T19:50:57.256-0800: 78.480: [GC pause (G1 Evacuation Pause) (young) (initial-mark), 0.0076560 secs] 

IHOP如果阀值设置过高,可能会遇到转移失败的风险,比如对象进行转移时空间不足。如果阀值设置过低,就会使标记周期运行过于频繁,并且有可能混合收集期回收不到空间。 IHOP值如果设置合理,但是在并发周期时间过长时,可以尝试增加并发线程数,调高ConcGCThreads。

03

引用处理

G1 GC对于虚引用、弱引用、软引用的处理会比一般对象多一些收集任务。如果在引用处理占用了很长时间,需要更进一步排查。在并发标记的Remark阶段会记录引用的处理,日志信息如下:

如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[GC remark 2018-05-26T19:50:57.386-0800: 78.610: [Finalize Marking, 0.0002675 secs] 2018-05-26T19:50:57.386-0800: 78.611: [GC ref-proc, 0.0001091 secs] 2018-05-26T19:50:57.386-0800: 78.611: [Unloading, 0.0204521 secs], 0.0212793 secs]

可以通过-XX:+PrintReferenceGC打印更详细的引用计数信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 [SoftReference, 0 refs, 0.0000482 secs]2018-06-03T20:52:03.887-0800: 18.033: [WeakReference, 116 refs, 0.0000321 secs]2018-06-03T20:52:03.887-0800: 18.033: [FinalReference, 1073 refs, 0.0009571 secs]2018-06-03T20:52:03.888-0800: 18.034: [PhantomReference, 0 refs, 1 refs, 0.0000211 secs]2018-06-03T20:52:03.888-0800: 18.034: [JNI Weak Reference, 0.0000192 secs], 0.0084976 secs]

一般在Ref Proc时间超过GC暂停时间的10%时就要关注。Ref Proc的信息打印在每次垃圾收集的Other信息模块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Other: 0.6 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.4 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]

如果SoftReference过多,会有频繁的老年代收集。-XX:SoftRefLRUPolicyMSPerMB参数,可以指定每兆堆空闲空间的软引用的存活时间,默认值是1000,也就是1秒。可以调低这个参数来触发更早的回收软引用。如果调高的话会有更多的存活数据,可能在GC后堆占用空间比会增加。

对于软引用,还是建议尽量少用,会增加存活数据量,增加GC的处理时间

7总结

本文简单介绍了一下G1 GC的调优参数以及G1 GC的日志内容。在具体调优过程,可以增加一些调优的参数,如-XX:+G1SummarizeRSetStats、-XX:+PrintReferenceGC、-XX:+PrintAdaptiveSizePolicy等。每次调参后还要密切关注GC log,最好能模拟生产环境进行全链路的测试。没有一个参数的调整是可以普适任何应用的,如果没有GC问题,就不需要为了优化而优化。但是对于GC的知识储备和更新,是每个应用开发工程师必备的知识模块。

---------------------

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员啊粥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【电子DIY作品】基于Ai-WB2的10A远程通断器
在日常生活中,各种智能插座、无线开关等应用十分广泛;其本质大都是GPIO控制继电器或其他开关器件,这种原理虽较为简单,但较于传感器采集进行多设备联动的模式应用范围更广、成本更低、方便快捷。
安信可科技
2025/05/28
720
用小安派R1做个 86盒中控
笔者这次没设计壳子,设计了一个 R1 屏幕保护板,屏幕正好在中间,排线在后面(防止某次过失把屏幕排线损坏)
安信可科技
2024/12/11
740
用安信可Ai-WB2-01S做一个可用网页控制的简易灯
●管理界面:浏览器地址栏"设备ip/LAMP/",比如"http://192.168.0.127/LAMP"
安信可科技
2025/03/26
820
智能家居之旅(九):HomeAssistant 的开关实体具象化了
想必大家也见过狗哥的 USB 通断器:WB2 替换 ESP8266 接入 HA 的 USB 通断器实例 用的是 Ai-WB2-01S 这个模组,配上继电器就能远程控制 USB 小夜灯了。这次要做的也差不多,但是不用继电器,毕竟它有点贵了。这次我们用 PMOS 管,不仅能控制亮灭,还能控制亮度。
安信可科技
2024/08/23
1890
STM32设计的物联网智能鱼缸
随着人们生活水平的提高,家居环境中的绿色生态和健康生活越来越受到重视。鱼缸作为家居装饰的一部分,不仅需要美观,还需要关注鱼儿的健康和生存环境。为了满足这一需求,当前设计了基于STM32的智能鱼缸系统。
屿小夏
2024/11/01
6991
STM32设计的物联网智能鱼缸
【论文复现】STM32设计的物联网智能鱼缸
随着居民生活品质的提升,家居空间内的绿色生态理念与健康生活方式日益受到人们的青睐。鱼缸,作为家居美化的一环,不仅要求外观雅致,更需兼顾鱼类的健康及其所居环境的优劣。为此,一款基于STM32技术的智能鱼缸系统应运而生。
Eternity._
2024/11/18
7170
【论文复现】STM32设计的物联网智能鱼缸
ESP8266 刷esp-homekit-devices 固件原生接入HomeKit实现物联网智能家居
简单说一下说就是采用ESP8266系列的模块,刷esp-homekit-devices 固件。原生接入HomeKit,实现家庭电气控制或者传感器信息采集及联动。不再需要HA桥接,比较适合苹果全家桶,或者智能设备想对较少。
怪兽
2022/10/04
3.8K0
ESP8266 刷esp-homekit-devices 固件原生接入HomeKit实现物联网智能家居
用安信可Ai-WB2模组做一个433网关
之前是买了一款Wi-Fi灯,是用手机APP操作,刚开始用的时候感觉很方便,后面用久了,觉得每次都要开APP操作也很烦,所以就在网上查了一下,有那种无线开关,按一下就能开关灯,把按钮贴在床头,需要开关灯就点一下,比点APP更方便!
安信可科技
2025/04/23
840
专注无线连接!安信可Ai-Thinker Ai-WB2系列帮助客户提升产品竞争力
房屋是人类居住的地方,正因为有了房屋,人类才结束了露营旷野的历史;有了房屋,人类才有了稳定的生活。从远古时代的洞穴到现代的高楼大厦,人类的庇护所——房子,在数千年的历史进程中不断地演变着。
OFweek
2023/03/07
5580
天气太冷不想出被窝?来DIY一个离线语音控制器
  在某宝购买的,只需要9.9元,语音识别固定,支持57条语音,基本的是够用了,基本的风扇控制、灯控制、电饭煲控制、温度控制等都具备,基本上比较全面。
用户8913398
2021/08/16
1.1K0
天气太冷不想出被窝?来DIY一个离线语音控制器
ESP32开源示波器.综述
昨天逛阿木论坛的时候从六位万用表看到4位万用表。偶然找到了一个基于ESP32的商品级别的开源万用表,花时间研究了硬件喝软件收获颇多,浅写一篇文章记录一下。
云深无际
2024/08/20
2750
ESP32开源示波器.综述
AI读心术再升级!一副眼镜直接控制波士顿机器狗,脑控机器人成真
来自麻省理工的研究人员发表了Ddog项目,通过自己开发的脑机接口(BCI)设备,控制波士顿动力的机器狗Spot。
新智元
2024/02/06
1510
AI读心术再升级!一副眼镜直接控制波士顿机器狗,脑控机器人成真
多个完整设计提供参考包括单片机、8086、STM32制作教程和资料-转发分享
在网上收集了接近上千个完整设计的单片机、8086、STM32制作教程和资料-转发分享(涵盖了大部分的毕设课设题目),学习单片机的最好教程,也可以作为帮助大家在做电子课设毕设时有利的帮助,可以从以下百度网盘下载(按照编号下载)。 实例代码:
嵌入式互联网
2022/02/09
2.9K0
多个完整设计提供参考包括单片机、8086、STM32制作教程和资料-转发分享
年中回顾特别季:我从0到1的物联网项目启动之旅
春节返工后,我就开始规划这个项目。契机源于春节期间,我发现老家竟开了近十家自助棋牌室,而且朋友也有意投入。更巧的是,年初时我还借助《腾讯混元大模型帮我开发一个自助棋牌室系统》。身为程序员的我,在思考了自助棋牌室背后的技术需求后,嗅到了一丝丝商机:何不开发一个自助棋牌室系统?转眼已过半年之久,借腾讯云开发社区《年中回顾特别季》这个机会,在此分享项目开展过程、遇到的问题以及解决方案,同时也期待能遇到志同道合的伙伴。
王二蛋
2024/10/10
7220
投融资汇总 | 本周(12.24-12.30)未来医疗占比猛增,阿里两项亿级投资
本周阿里巴巴有两项亿级投资,一项投向了交通支付和人脸识别技术研发公司小码联城,一项投给了光场内容技术服务提供商叠境数字。 本周国内外硬科技投融资共31起,其中人工智能11起。区块链技术投资数量与上周相比有所回落,语音识别和人脸识别融资数量有所增加。同时,深度学习和机器视觉等基础技术研发公司的融资数量也小幅增长。3R公司融资数量与上周相比有所减少。 本周阿里巴巴有两项亿级投资,一项投向了交通支付和人脸识别技术研发公司小码联城,一项投给了光场内容技术服务提供商叠境数字,叠境数字致力于将光场技术和人工智能研究成果
镁客网
2018/05/30
4570
海尔发布智慧家庭人工智能解决方案,CTO赵峰解读AI开放创新平台
编辑部 【新智元导读】 11月28日, 海尔发布智慧家庭行业首个人工智能解决方案及涵盖人工智能交互系统、基于深度学习的智慧家庭解决方案两大平台级应用落地成果。会上,海尔U+与搜狗在发布会上共同签署了战略合作协议,双方将组建联合研发团队,共同研发实现用户与智能家电自然交互的终端设备和智能产品。此外,海尔U+联合搜狗、中科院、先声互联、阿里、灵隆科技、出门问问等共同启动海尔U+智慧家庭“+AI Family”计划。 11月28日,“U+云脑,+AI生态“海尔U+人工智能智慧家庭解决方案发布会在北京开幕,发布会上
新智元
2018/03/21
1.8K0
海尔发布智慧家庭人工智能解决方案,CTO赵峰解读AI开放创新平台
智哪儿×广州光亚展专栏:对话2023GILE六大微波雷达传感企业,当前传感技术在智能场景的技术优势、服务场景和对其发展的预判
作为照明及智能家居产业最重要的行业盛会之一,2023年第二十八届广州国际照明展览会(光亚展,GILE 2023)将以“「光+」未来”为主题,于2023年6月9日在中国进出口商品交易会展馆正式开幕。6月9日至12日,2023光亚展将设立不同主题馆展示“光+”概念,再度汇集国内外企业,共同描绘一幅未来照明生态的恢弘画卷。
智哪儿
2023/05/17
4840
智哪儿×广州光亚展专栏:对话2023GILE六大微波雷达传感企业,当前传感技术在智能场景的技术优势、服务场景和对其发展的预判
让每个家庭都拥有一个“钢铁侠”管家
比尔·盖茨在1997年建成的豪宅“未来之屋”,让智能家居进入了大家的视线。电影《钢铁侠》则进一步满足了我们对智能家居的想象,“钢铁侠”托尼·史塔克以老管家的名字打造的智能系统贾维斯(J.A.R.V.I
BestSDK
2018/02/28
1.4K0
让每个家庭都拥有一个“钢铁侠”管家
有关单片机的毕业设计_1500一套毕业设计贵吗
对大部分同学来说,毕业设计根本不知道从哪下手,完全处于蒙圈状态,为帮助大家能顺利毕业,精心准备800多套单片机毕业设计与您分享!
全栈程序员站长
2022/11/09
2.2K0
AIoT应用创新大赛-植物生长分析仪
传统的豆芽生长设备,只是完成豆芽的生长过程。相对于其他市面上的自动豆芽生长器,它只是简单的进行循环浇水,保持湿度,保持恒温。然后用遮光布遮光,持续到豆芽长成豆苗。对于豆芽的生长健康状态从不关心。并且如果豆芽死了。它也没有任何反馈。就只能重新种植。本设计豆芽生长状态分析仪主要是跟踪豆芽生长的全过程。可以随时观察豆芽的生长因素参数。将温度,湿度,co2,照度实时进行采集。并绘画成生长曲线。我们将和正常曲线进行对比。如果曲线出现偏差,进行及时报警提醒没有任何状态监控。在生长过程中,如果出现豆芽生长环境因素恶劣情况,经进行报警提醒。同时此仪器可以通过网络告知大家豆芽此刻处于生长阶段的哪个阶段,比如幼苗期,萌芽期等。所以不需要人实时去观察豆芽处于哪个生长阶段。
用户9341755
2022/02/22
8340
AIoT应用创新大赛-植物生长分析仪
推荐阅读
相关推荐
【电子DIY作品】基于Ai-WB2的10A远程通断器
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验