爱意满满的作品展示区。
mahui

Diskly 1.5.0 发版 —— 我做的 macOS 磁盘分析与清理工具

  •  
  •   mahui · 11 days ago · 1623 views

    大家好。我做了一个 macOS 原生的磁盘分析 + 清理工具 Diskly,今天发了 1.5.0,顺便来 V2 说几句。

    Diskly 仪表盘

    为什么又造一个轮子

    DaisyDisk / GrandPerspective 都用过。两件事我一直介意:

    • 数字会骗人。iCloud / OneDrive 里没下载的占位文件,系统会按"逻辑大小"算几十 GB——但你删掉根本腾不出空间。macOS 的 firmlink (/Users 实际上是 /System/Volumes/Data/Users 的另一条路径)和硬链接会让同一份数据被算两遍——我的 2 TB 盘曾经被某工具扫出 6.46 TB
    • 看清和动手是两件事。可视化做完,清理这步要么没有,要么直接把你引去一堆"建议",一键删完你都不知道删了啥。

    所以 Diskly 的几个产品决策都围绕这两点。

    几件我较真的事

    1. 数字必须诚实

    • 全程按 本地实际占用totalFileAllocatedSize)算,云占位文件计 0 。
    • firmlink + 硬链接按 (st_dev, st_ino) 整数键去重,目录全去重 / 文件仅当 linkCount > 1 时去重(常态零开销)。
    • 实测扫 /:6.46 TB → 1.62 TB,与 df 报告基本一致(剩下的差额是 APFS clone 的固有现象,不假装修)。

    2. 多入口起步,扫过的目录秒回

    新建扫描页一屏装五种入口:拖拽 / ⌘O / 菜单 / Finder 服务 / 快速访问 + 最近扫描。

    新建扫描页

    顶部的「 Pick up where you left off 」是 1.4.x 加的——扫过的结果还在内存里时,点一下秒回(无需重扫);多份结果按内存预算淘汰,当前这份永不淘汰。

    3. 等待也该有信息

    扫几百万文件需要时间,但进度条不该是空白的

    1.5.0 里把扫描中页的下半区改了:加了一张实时构成图——按已识别字节的分类铺一张 mini 矩形树图,跟扫描结束后的总览同款配色。等待时已经能看到"占大头的是啥类型",体验连续。

    实现细节:复用 Treemap.layout 的 squarified 算法,9 个分类桶合成成一棵浅层 FileNode 树喂进去布局。每帧重建 9 节点 + 一次 squarify,O(9) 极快不会成为热点。

    4. 清理是有分寸的

    清理建议分两轨:安全可删 / 建议检查。默认只勾安全的。

    • 安全档:DerivedData 、~/Library/Caches、SwiftPM .build、Xcode iOS DeviceSupport 、CoreSimulator 缓存——可自动重建。
    • 检查档:node_modules 、长期未用应用、Docker 镜像——需要你自己判断。

    清理建议

    差异化的几个点:

    • node_modules 用 .git/logs/HEAD 修改时间判断仓库活跃度,< 90 天自动排除(不调 git 子进程,避免触发 CLT 安装弹窗)。
    • 应用最近使用走 Spotlight kMDItemLastUsedDate,取不到不猜(诚实降级,不编"很久没打开了")。
    • 全部移到废纸篓,30 天内可恢复。

    并且每条建议都能展开看实际要删的文件清单,删前可以逐条核对、单独取消:

    展开核对每一项

    5. 克制,且只属于你

    • 菜单栏只占一个图标 + 一个百分比,点开才展开。
    • 零遥测。不弹广告、不催升级、不收集任何数据。
    • 经 Apple 公证、官网直接分发。

    1.5.0 干了啥

    这一版改动比较大,主要是性能 + UX 修复。挑几个有意思的说:

    树图悬停帧率。之前 Canvas 同时画结构和高亮,鼠标每动一像素整张树图重绘 + 每个标签跑二分测量。拆成「结构层 + 高亮层」两层 Canvas,.equatable() 让 SwiftUI 在悬停时跳过结构层重渲染;标签宽度在 rebuild 时一次性 NSAttributedString.size() 二分截断好,绘制零度量。

    下钻 /Applications 不再等几十秒。Spotlight 元数据查询从串行改 DispatchQueue.concurrentPerform 并发 + URL-keyed 会话缓存。200~500 个 app × 30~80ms 串行 = 6~40s,改并发后摊到核数,体感明显。

    内存底座 −150 MBFileNode.idUUID()ObjectIdentifier(self)——900 万节点 × 16 字节 UUID 是纯开销,ObjectIdentifier 是 class 自带的零开销 identity,Identifiable 协议照样满足。

    ETA 终于准了。旧算法用瞬时速率 EMA × 剩余字节,早期抖动剧烈、末期对小波动极敏感。改成「已用时间外推」:elapsed × (1 - fraction) / fraction,稳得多。同时单调钳制下降即时反映、上升每帧最多 +5s,避免视觉抖动;前 3 秒不显示(预热),整理阶段不显示。

    ETA 文案 i18n 修复Formatting.duration 之前硬编码"秒/分/小时",英文模式下泄漏"2 分 48 秒"。改用 DateComponentsFormatter,按 locale 自动出"2m 48s"/"2 分 48 秒"。

    菜单栏「偏好设置…」真能打开了。之前点了没反应——NSApp.sendAction(Selector(("showSettingsWindow:"))) 在 popover dismiss 同步链不可靠,SwiftUI Settings scene 的注入 target 找不到。新实现 DispatchQueue.main.async 让 popover 先彻底关闭,然后按 ⌘, 快捷键 递归找主菜单 item 直接 performActionForItem(等价于用户从 App 菜单点击)。

    无默认邮件客户端兜底。这是 V2 提醒我考虑的:只用网页 Gmail / Outlook 的用户点 mailto 会失败。SupportContact.openOrCopyNSWorkspace.open,失败时复制邮箱到剪贴板 + 弹原生 alert;设置里每处邮箱旁加独立「复制」小按钮。

    完整 changelog: https://diskly.app.mahui.me/changelog

    怎么装

    brew install --cask mahui/tap/diskly
    

    或者官网 https://diskly.app.mahui.me 直接下 .dmg

    Apple 公证 + 时间戳签名,Gatekeeper 直接放行,不用右键打开。要求 macOS 14 Sonoma+,Universal 二进制(Apple Silicon + Intel)。

    价格

    $9.99 一次买断,5 台设备激活。14 天全功能试用,试用结束才需要付费。

    V2 老司机如果想体验完整版,私信我邮箱给一把激活码(几把够 V2er 用没问题)。

    反馈

    —— 昨天发了 Pier(菜单栏看端口/进程的小工具),今天又来打扰,如有问题欢迎拍。


    技术栈:Swift + SwiftUI 原生,SPM 可执行文件(不是 Xcode 工程)。扫描器固定 worker 池 + 共享队列分治,实测扫 935 万文件的 / 大约 90s 左右,峰值内存 ~5 GB 。

    Supplement 1  ·  9 days ago

    附言:私信收到不少激活码请求,但帖子里有点冷清

    发出来一天多,私信激活码的请求收到了挺多,谢谢各位捧场——看到了基本都在回,没回到的请再戳我一下。

    不过有个小请求:也欢迎在楼下冒个泡。哪怕只是一句「装了,扫了一下,体感 OK」或者「XX 这里设计有问题」,对我都比私信有用。

    为什么这么说:

    • V2 是我能直接对话用户的少数渠道,我做这个工具最在意的就是真实反馈,私信是一对一,沉淀不下来。
    • 楼里有讨论,后来人才知道这工具是真有人用、有人维护,不是发一波就跑。
    • 拍砖也欢迎,只要是真实体验我都收——不删帖、不删评论。

    具体可以聊的(随便挑一个就行):

    • 扫描速度 / 内存占用在你机器上表现如何(尤其大盘、外接盘、多盘)
    • 清理建议准不准、有没有误伤?哪些类别你不敢勾?
    • 树图、清理页、菜单栏哪里别扭、哪里看不懂
    • 你之前用 DaisyDisk / GrandPerspective / OmniDiskSweeper,Diskly 比起来差在哪、好在哪
    • 想要但还没有的功能

    顺手再澄清一下定价

    可能正文写得不够显眼,有几位私信里问到:

    $9.99 是 5 台设备的一次性买断,不是单台、不是订阅、不按年续。摊下来一台不到 2 美元,家里 Mac + MacBook + 备用机一把覆盖,后续小版本 / 大版本升级都免费。

    激活码继续发,留言也欢迎;如果觉得这工具确实帮你省了事,也欢迎直接买一份支持下。

    Supplement 2  ·  7 days ago

    1.6.0 已上架,几个改动

    接上版之后又攒了几件,主要在收 1.5.0 发出去之后大家反馈集中的痛点。已经装了的打开 Diskly,内置自更新会提示。或者:

    brew upgrade --cask --greedy diskly
    

    1. Boot Camp / 网络卷默认跳过

    楼里有老哥反馈"老机器扫得很慢",一问是装了 Windows 双系统。macOS 上挂的 NTFS 卷要过 fuse 驱动,几百万文件能慢好几分钟;SMB / AFP / NFS 网络卷更不用说。

    这版默认就跳:NTFS(Boot Camp / Tuxera)、SMB、AFP、NFS、WebDAV。扫描中页顶上一条 banner 显示「已跳过 BOOTCAMP (Windows 分区)」,旁边「包含并重新扫描」按钮 —— 直接选这种卷作为扫描目标仍然正常扫(你主动选的)。

    2. 云同步目录默认跳过

    OneDrive / Dropbox / iCloud 云盘 这类 File Provider 挂载的目录,每查一个文件属性都要跟它的 helper 进程通信回应一次,你的进程再快也没用。

    默认跳:扫到 ~/Library/CloudStorage/* 或 iCloud 云盘 时自动加进 banner 跳掉。点「包含」时,扫描并发数会从 16 拉到 32——本地 SSD 上过度并发是浪费,但云盘是 IPC 阻塞,多线程能真实掩盖往返延迟。

    3. 扫描中那张图不再「灰一片其他」

    1.5.0 加的「实时构成图」按扩展名分了 9 桶(图片/视频/音频/代码/文档…),一开扫就发现二进制、.app 包内部、/System/ 底下的东西全归"其他",一大片灰。

    这版换成跟扫描完总览同一套 8 桶:应用 / 照片 / 视频 / 系统 / 文档 / 开发 / 压缩 / 其他。带路径判断和目录继承,/Applications/Xcode.app 整体算 apps,~/Library/Developer/... 整体算 developer。颜色也跟扫描完那张图一致,看上去像同一张图的延伸。

    4. iOS DeviceSupport 不再默认勾选

    DerivedData 还是默认勾(Xcode 重编一下就回来,零成本)。但 DeviceSupport 删完之后,下次连旧 iOS 设备 Xcode 要重新拉符号包,老版本 iOS 不一定还能拉到——这个不该默认勾,挪到了「检查」档。

    5. 加了 UI 语言设置

    设置 → 通用 → 语言:跟随系统 / 简体中文 / 繁體中文 / English。切了立即生效。

    6. 修了几个问题

    • 图标在 Launchpad 比别的 app 大一圈。
    • 图标 PNG 四周露白边。
    • 切到简体中文后部分 tab 中英夹杂。

    完整 changelog:https://diskly.app.mahui.me/changelog


    顺便:激活码规则微调

    1.5.0 那条帖发出后激活码请求收到挺多,谢谢各位捧场。

    不过有件事我想从这版起调整一下规则:

    从 1.6.0 起,想要激活码的朋友,麻烦先在楼下留一条「使用体验 / bug 反馈 / 意见建议」中的任意一条,然后发邮件来,附上你那条回复的链接(或者你自己的帖子链接)。

    不是变小气——之前私信给的方式我也会继续兼容已发过的请求。改这个规则有几个理由:

    • 想看到讨论真的沉淀下来。私信是一对一,谁也看不到。楼里有真实使用反馈,后来人才知道这工具是真有人用、真有人维护、真有人骂(笑)——比我自己怎么吹有用得多。
    • 对花心思留言的人更公平。前两天有几位老哥认真写了使用感受,有人指出双系统扫描慢(就是这版修的),有人聊了对清理建议的疑虑——这种留言成本不低,但回报和"路过私信要码"的人一样,不太对。
    • 避免薅羊毛。说实话上版收到一些一句话私信,看不出是真想用还是凑热闹。给规则一道门槛,过滤一下。

    具体怎么操作就两步:

    1. 楼下回一条(随便聊点啥都行——装上试了多大盘、哪里卡、哪里好用、哪里别扭、你之前用 DaisyDisk/OmniDiskSweeper 对比起来如何、有没有想要但没有的功能,都算);
    2. 发邮件到 [email protected].me,正文贴上你那条回复的 V2 链接(或者你自己起的帖子链接);
    Supplement 3  ·  7 days ago
    上一个 append 邮箱点击会跳错。修正下申请激活码邮箱 [email protected]
    Supplement 4  ·  6 days ago

    1.6.1 已上架,一个小 patch

    接上版,这版只补一个:深色模式下菜单栏弹窗里「可释放 XX GB」那块横幅几乎看不见

    之前那一格底色是固定的浅绿 #EAF3DE,浅色模式下黑字铺上去没问题;但深色模式下文字自动变白,白字铺浅绿——对比度直接报废,实测要凑近屏幕才能勉强看出写了啥。1.6.0 我自己跑过深色模式截图,偏偏漏掉了这块,有用户给我发截图才注意到,丢人。

    修法是把那块底色从一个固定 Color 改成基于 NSAppearance 的动态色:深色模式换成低饱和深绿,浅色模式保留原 #EAF3DE。改动一共四行,效果就是上下两张图的区别。

    已经装了的打开 Diskly,内置自更新会提示。或者:

    brew upgrade --cask --greedy diskly
    

    只有这一项改动,changelog 也只这一条:https://diskly.app.mahui.me/changelog

    激活码规则跟 1.6.0 那条一样,楼下留言 + 邮件附链接,我会回。

    9 replies    2026-06-08 12:28:29 +08:00
    coronin
        1
    coronin  
       10 days ago
    很好用
    dabaov2
        2
    dabaov2  
       8 days ago via Android
    感觉 daisydisk 不太好用,除了比较直观外功能有点单一。想试用大佬的软件,可以给个码吗,感谢 ZGRkaW5nZGRkaW5nQDE2My5jb20=
    bao626
        3
    bao626  
       8 days ago
    大佬牛啊,膜~
    defcc
        4
    defcc  
       8 days ago
    我现在都是直接 codex ,让 codex 直接 "Clean my mac"
    mahui
        5
    mahui  
    OP
       7 days ago
    @defcc 👍
    zhaoxixiangban
        6
    zhaoxixiangban  
       7 days ago
    弟弟想要,弟弟能得到吗 ,已私信老哥。
    mahui
        7
    mahui  
    OP
       7 days ago
    @dabaov2 感谢反馈,激活码已发
    mahui
        8
    mahui  
    OP
       7 days ago
    zhaoxixiangban
        9
    zhaoxixiangban  
       7 days ago
    试用了,真的不错扫盘很快(用过最快的) , 可能自动把大量代码的编译产物筛出来,统一清理很方便。 很好用啊
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1059 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 22:53 · PVG 06:53 · LAX 15:53 · JFK 18:53
    ♥ Do have faith in what you're doing.