用进程资源图检测死锁的原理

用进程资源图检测死锁的步骤为:

  1. 确认系统剩余资源数,确认非阻塞进程;
  2. 去掉非阻塞进程的所有边,现成一个孤立的点,再将分配给该进程的资源回收;
  3. 查看剩余非阻塞进程,重复执行步骤2;
  4. 最终,所有的资源和进程都变成孤立的点,这样的图叫做“可完全简化”。

如果一个图可完全简化,则不会产生死锁。如果一个图不可完全简化,则会产生死锁。

举例:

阅读更多

如何免费使用Google Cloud的高性能GPU进行AI训练,做AIGC

最近在搞AIGC相关的东西,各个平台的用了一下,发现还是开源香啊!刚好手上有台配置不错的PC,显卡1080Ti(当年的骨灰级显卡)11GB的显存,跑了一下Stable Diffusion,还行!比大多数付费的搭载SD的服务器都好用。

但性能还是不行,不如专门的搞AI的图形显卡性能好,这就想起了当年用GCP的GPU挖ETH的经历,于是又捡起来了,搭建了Stable Diffusion服务器,性能杠杠的!15GB显存的GPU~

算了,有机会再写吧~~~

话说这些模型生成的图片质量越来越高了!

Android自定义截图

开发中遇到截取屏幕,但是还要从截图中排除特定View的图像,或者有些业务截图无法通过api截取到(比如WebGL渲染的游戏),因此不能简单的调用系统截图API,或者在截图时隐藏特定的View(那也太low了)。因此我开发了个自定义截图的功能,主要分以下几个步骤:

阅读更多

AOS中使用远程9-patch图

业务开发中会偶尔遇到使用远程9-patch图的情况。具体操作:

1、本地创建9-patch图

可以在工程的debug/res/的drawable目录中创建

2、使用aapt编译创建好的9-path图

例如编译某个目录:
aapt c -v -S ../app/src/debug/res/drawable-xxhdpi/ -C out
亦可使用 “aapt s ”命令编译单个文件

3、上传到服务端

将编译好的文件上传至服务器

4、客户端下载展示

最核心的是要判断Bitmap是否是9-patch图:

private void callbackBitmap(Bitmap resource) {
        try {

//读取9-patch信息
            byte[] ninePatchChunk = resource.getNinePatchChunk();
            if (DEBUG) {
                boolean isNinePatchChunk = false;
                if (ninePatchChunk != null) {
                    isNinePatchChunk = NinePatch.isNinePatchChunk(ninePatchChunk);
                }
                Log.i(TAG, "fetch.onSuccess: ninePatchChunk = " + ninePatchChunk + ", isNinePatchChunk = " + isNinePatchChunk);
            }

//判断是否是9-patch图
            if (ninePatchChunk != null && NinePatch.isNinePatchChunk(ninePatchChunk)) {
                NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(resource, ninePatchChunk, new Rect(), null);
                if (mLoadCallback != null) {
                    mLoadCallback.onDrawableReady(ninePatchDrawable);
                }
            } else {
                showAsDefaultBitmap(resource);
            }
        } catch (Throwable e) {
            showAsDefaultBitmap(resource);
        }
    }

完整文件:https://github.com/gongshoudao/Remote-9-patch/blob/main/NinePatchHelper.java

直播间超复杂布局,用包含关系实现布局文件的“继承”

最近开始准备找工作,打算把之前做的一些重构、优化相关的东西整理整理。

MeMe Live的直播间以前在运行时,有高达2000多个View,非常庞大、臃肿,维护起来及其空难,很容易牵一发而动全身,新招进来的同学很难驾驭。于是对它进行了重构。顺便说一句,以前的布局是用的RelativeLayout,性能差不说,还很不灵活。重构时将其改成了ConstraintLayout,每一个相关的View都得转换,每一个在Java代码中硬编码调整属性的控件都得找出来,改掉。工程量和困难度可想而知,索性最后坚持坐下来了。收获不少,对团队开发效率也提升不少。

阅读更多

关于QUERY_ALL_PACKAGES权限问题

Android11之后,resolveActivity、查询某个APP是否已安装等需要特殊处理。

要么加QUERY_ALL_PACKAGES权限,要么就在清单文件中使用<queries>标签。

由于Google Play的政策:

如果您的应用不需要使用 QUERY_ALL_PACKAGES 权限,请从您的应用清单中移除该权限。如果应用需要此权限,您现在可以在 Play 管理中心内提交声明表单。

您需要提供:

1.对需要此权限的应用核心功能的说明
2.展示需要此权限的应用核心功能的短视频
如需了解您在该表单中将需要回答哪些问题以便做好准备,请参阅这篇帮助中心文章。

自 7 月 12 日起,如果缺少此声明,您将无法提交新应用和应用更新。请您务必在 7 月 12 日之前提交此声明,或者从您的应用清单中移除该权限。从 7 月 12 日起,对于不符合政策要求或未提交此声明表单的应用,我们可能会将其从 Google Play 下架。

感谢您一直以来与我们通力合作,共同努力让 Google Play 成为值得您和用户信赖的可靠平台。
阅读更多

dump Java Thread 的几种状态及其含义

The values of the Java thread state and the internal VM thread state can be:

  • R – Runnable – the thread is able to run when given the chance.
  • CW – Condition Wait – the thread is waiting. For example, because:
    • The thread has been blocked for I/O
    • A wait() method is called to wait on a monitor being notified
    • The thread is synchronizing with another thread with a join() call
  • S – Suspended – the thread has been suspended by another thread.
  • Z – Zombie – the thread has been killed.
  • P – Parked – the thread has been parked by the new concurrency API (java.util.concurrent).
  • B – Blocked – the thread is waiting to obtain a lock that something else currently owns.

并行收集器

并行收集器也称作吞吐量优先收集器,是一种跟串行收集器类似的分代/世代收集器。跟串行收集器不同的是,并行收集器使用多线程的方式来加速垃圾回收。

使用-XX:+UseParallelGC参数开启并行收集器。默认情况下,使用此参数后,minor收集和major收集都会采用并行的方式,进一步较少垃圾回收的负载。

并行垃圾收集器的线程数量

在具有N(N大于8)个物理线程的机器上,串行收集器使用N的分数作为垃圾回收线程数量。

比例大约为5/8 * N。如果N小于8,则使用N作为线程数。在有些平台上,这个数值为5/16*N。此数值也可以通过命令行参数指定。在单处理器的机器上,并行收集器的表现可能不如Serial收集器,因为并行收集器有较高的开销,例如同步。当应用程序运行在配置了中大型堆内存的虚拟机上时,在双核环境下,并行收集略好与串行收集。在更多核的机器上,并行收集的性能优势更为显著。

阅读更多

HotSpot中的垃圾收集器

Java HotSpot虚拟机包含了三类垃圾收集器,每一类都有不同的性能特征。

串行(Serial)收集器

串行收集器在单线程中进行垃圾回收,由于没有线程之间的切换,因此垃圾回收工作相对较高效。

对单核处理器的硬件来说,串行收集器是最佳选择。因为它无法发回多核设备的优势。只适合小型应用程序。

Serial收集器在某些设备和操作系统上是默认配置,当然你也可以可以使用

-XX:+UseSerialGC

参数手动指定HotSpot虚拟机使用串行收集器。

并行(Parallel)收集器

parallel收集器也被称为 throughput collector(吞吐量优先)收集器,它与Serial收集器的主要区别在于,垃圾回收过程在多线程中进行,加速了垃圾回收过程。parallel收集器一般用于运行在多核、多线程设备上的中大型应用程序。

可以通过

-XX:+UseParallelGC

启用parallel收集器。

阅读更多

HotSpot中的“世代/分代”(Generations)概念 for Java 10

Java的优势之一是它对开发者屏蔽了复杂的内存分配和垃圾回收,但当垃圾回收成为瓶颈时,了解它的内部实现机制是有必要的。

当运行时没有任何指针指向一个对象时,那这个对象就是个“垃圾”。最直截了当的垃圾收集算法遍历所有“可达”对象,剩下所有的对象都视为“垃圾”😀。这种算法的时间消耗跟“存活”的对象数量成正比,对于持有大量“存活”对象的大型程序禁止这么干。

采用分代收集的虚拟机整合了不同的垃圾回收算法。不成熟的垃圾收集器检测堆中每个存活的对象,而分代收集则观测根据程序运行经验以最少的工作完成垃圾回收。最重要的观测属性是“weak generational hypothesis”(弱世代假设),这种状态的大多数对象都存活很短的时间。

下图中的蓝色区域是对象常规的寿命分布。X轴是以字节为单位的对象寿命,Y轴的字节数量是相应生存期的对象的总字节数。左边的断崖表示对象在创建之后很快被回收(即对象已“死”)。例如Iterator,通常指存活一次迭代。

对象寿命
阅读更多

Spine导出格式说明之——JSON格式(上)

Spine可以导出为JSON或者二进制格式。JSON可读性强、便于检查和修改但体积大;二进制可读性差,修改成本高,但文件体积小,加载速度快。

可以说Spine导出的JSON格式数据是骨骼数据实例的序列化版本。它由一系列的骨骼(bones)、插槽(slots)、皮肤(skins)和动画(animations)组成。

骨架(Skeleton)

skeleton节点存储骨架的元数据,结构如下:

阅读更多