主頁 >  其他 > UME - 豐富的Flutter除錯工具

UME - 豐富的Flutter除錯工具

2020-12-10 18:19:34 其他

背景

目前西瓜視頻作者側 Flutter 業務場景已經覆寫了 40多個頁面 (包括視頻播放場景),用戶側核心場景包括我的 Tab 也已經是 Flutter,在開發程序中,暴露了一些問題,debug 除錯難、離開了 IDE 后猶如抓瞎、PM 設計 QA 驗收程序中拿不到有用的資訊,在市面上找了一圈,也沒有類似 iOS Flex 這樣強大的除錯工具,例如視圖大小、層級的展示,實體物件屬性的實時修改,網路請求抓取,log 日志列印,檔案查看等,所以西瓜視頻 Flutter 基礎團隊決定開發 UME,

介紹

UME (讀音:油米~) 是一個 Flutter 除錯工具包,內部集成了豐富的除錯小工具,設計UI、網路、監控、性能、logger 等,無論是研發、PM、還是 QA 均能使用,

目前已實作的功能

接下來會詳細介紹一些核心功能的使用效果以及核心實作:

模塊詳解

Widget 資訊

可以查看當前選中 widget 的大小、名稱,檔案路徑以及代碼所在行數,有了這工具,即使你不負責這個功能模塊的開發,你也能迅速找到當前代碼,

那如何能獲取到選中當前 widget 的資訊呢,大小通過RenderObject 就能拿到,那 widget 的代碼位置呢?通過WidgetInspectorService 中的 getSelectedSummaryWidget 便可以獲取到一個json字串,我們來看下它的結構:

{
    "description":"Text",
    "type":"_ElementDiagnosticableTreeNode",
    "style":"dense",
    "hasChildren":true,
    "allowWrap":false,
    "locationId":0,
    "creationLocation":{
        "file":"file:///Users/.../example/lib/home/widgets/category_card.dart",
        "line":69,
        "column":15,
        "parameterLocations":[
            {
                "file":null,
                "line":70,
                "column":24,
                "name":"data"
            },
            ... 
        ]
    },
    "createdByLocalProject":true,
    "children":[
        {
            "description":"RichText",
            "type":"_ElementDiagnosticableTreeNode",
            "style":"dense",
            "allowWrap":false,
            "locationId":1,
            "creationLocation":{
                "file":"file://../packages/flutter/lib/src/widgets/text.dart",
                "line":425,
                "column":21,
                "parameterLocations":[
                    {
                        "file":null,
                        "line":426,
                        "column":7,
                        "name":"textAlign"
                    },
                   ...
                ]
            },
            "children":[],
            "widgetRuntimeType":"RichText",
            "stateful":false
        }
    ],
    "widgetRuntimeType":"Text",
    "stateful":false
}

由于資料太多了,省略了一部分, 然后根據對應的key即可找到需要的部分,

Widget層級

可以查看當前選中 widget 的樹層級,以及它 renderObject 的詳細 build 鏈,

這個獲取到選中 widget 的一個 build 鏈還是比較簡單的,通過 InspectorSelection 獲取到當前 currentElement ,然后 使用 debugGetDiagnosticChain 方法就可以獲取到整個build 鏈了,

RenderObject 的資訊也很好得到,通過currentElement 拿到 當前的RenderObject,然后使用 toString方法就可以拿到了,

ShowCode

可以查看到當前頁面的頁面代碼,

主要實作涉及到以下幾個關鍵點:

  1. 獲取到當前頁面 widget 所屬的檔案名,

  2. 根據 dart 腳本的檔案名來找到并讀取腳本,

獲取檔案名主要利用WidgetInspectorService實作,

而讀取腳本主要使用VMService實作,

獲取當前頁面widget檔案名
  • 我們通過遍歷獲得當前頁面的renderObject串列,按照大小篩選出我們想要的目標 widget,

  • Widget 資訊中講解到過,我們可以通過WidgetInspectorServicegetSelectedSummaryWidget 方法獲取到 json 字串,

  • 提取 "creationLocation" 的值即是當前 widget 的在開發程序中的檔案地址,

  • 我們截取出來地址字串的最后一部分就是當前頁面代碼所在的檔案名了,

找到并讀取腳本
  • VMService中的getScripts方法可以獲取當前執行緒下的所有庫檔案的 ID和檔案名,

  • 我們通過比對檔案名可以獲得目標庫檔案 id,

  • 通過VMServicegetObject方法可以獲取到當前id對應的物件,我們傳入剛付訓取的庫檔案id即可獲得這個庫物件,讀取物件的source屬性,里面就是我們的原始碼了,

記憶體泄露

LeakDetector 用于檢測 flutter 記憶體泄漏,總體的實作思想和 Android 平臺的LeakCannary工具類似,利用Expando來弱參考持有待檢測物件,并且使用 VMService 拿到泄漏物件的參考鏈,最終將泄漏資訊本地存盤并且展示出來,

Dart VM Service 是 Dart 提供的一套 web 服務,資料傳輸協議是 JSON-RPC 2.0,通過它提供的介面我們能獲取到 Dart 虛擬機內部的一些重要資訊,下面介紹下整個程序:

  1. 獲取 VMService 服務
  • 獲取 ObservatoryUri

    • 通過Service.``getInfo``()獲取ServiceProtocolInfo,從中取出serverUri

    • 通過vm_service中的util工具方法convertToWebSocketUrl()將上面的http格式的uri格式轉為ws://格式,

    • 獲取VmService服務物件, vm_service_io檔案中有個vmServiceConnectUri()方法,傳入一個observatoryUri就可以獲取一個VmService物件,

  1. 獲取 isolateId
  • 通過 VmService 的 getVM 方法拿到 VM 物件,VM 物件中存盤著所有的IsolateRef,

    • 通過Service.getIsolateID(Isolate.current)拿到,只有 debug 下有效,release 下會回傳null,

  1. 獲取 libraryId
  • 通過第2步拿到 isolateId 之后,然后呼叫 VmService 的getIsolate拿到對應的 Isolate 物件,

  • 遍歷 Isolate 的 libraries 欄位,這是一個 LibraryRef 的 List,然后拿當前 Library 的 uri 去List中匹配LibraryRef的 uri ,就可以獲取 LibraryRef 的 id ,

  • 拿著 isolateId 和 LibraryRef 的 id,呼叫 VmService 的 getObject 方法就可以獲取 Library,取其 id 欄位就是我們要找的libraryId(其實LibraryRef的 id 應該就是了,實際可以測驗),

  1. 獲取 objectId

由于getInstance(isolateId, classId, limit)方法存在性能和limit限制的問題,我們轉而利用invoke(isolateId, targetId, selector, argumentIds, disableBreakpoints)方法,借助 Library 頂層函式就可以獲取 libraryId 也就是 invoke 方法中的 targetId,最后我們只需要將目標物件暫存一下再通過 invoke 方法取出來就可以拿到該物件的 InstanceRef 了,進而拿到其 id 欄位就是我們要找的 objectId 了,

  1. 泄漏判斷
  • 通過 getObject(isolateId, objectId) 方法拿到 Expando 的物件的 Obj 實體,它的真實型別其實是一個 Instance,

  • 遍歷 Instance 的 fields 欄位找到 _data(_data的型別是 ObjRef,可以拿到它對應的 Instance 實體)欄位(怎么找_data?可以通過 BoundField 的 FieldRef 欄位,然后匹配 FieldRef 的 name 為 ‘_data’),在expando_path.dart中我們可以看到 Expando 的具體實作,_data 欄位是一個 List,

  • 遍歷 _data 欄位,如果都為 null,表明我們觀察的 key 物件都釋放了;如果元素不為 null,則將該該元素轉為 Instance 物件(其實就是一個 WeakProperty),取其 propertyKey 欄位就是我們實際的沒被回收的物件了,

  1. 獲取參考路徑
  • VmService 有一個getRetainingPath方法可以直接拿到一個物件的參考鏈,但是只會拿一條,

  • 需要注意在前面使用 Expando 檢測完記憶體泄漏之后,就釋放 Expando 對原始物件的參考,

  • Instance 的 id 會過期,VmService 對它的快取最大是8192,所以不要保存 id而要保存物件,

  1. 觸發GC
  • VmService 有一個getAllocationProfile(isolateId, gc=true)方法,通過它來觸發 dart vm 進行 gc,這個也是 Dev Tools 工具上觸發 gc 按鈕最終呼叫的方法,據測驗觸發的都是 FULL GC,

  1. 觸發時機
  • Route 檢測

    • 借助 framework 提供的NavigatorObserver機制,可以很輕松的監聽到頁面的進出堆疊,在 didPop、didRemove、didReplace 方法中觸發對route的泄漏檢測,

  • Widget/State 檢測

    • 一般的頁內 Widget/State 不檢測,而只檢測真正頁面對應的 Widget 和State,framework 并沒有提供一個全域監聽頁面銷毀的機制,這里我們借助hook_annotation(這個后面會解釋)來hook兩個點:RouteRootState 的 initState 方法,記錄要檢測的頁面物件;State 的 dispose 方法,如果是我們已記錄的頁面,則觸發檢測流程,

記憶體查看

Memory 可用于查看當前Dart VM 物件所占用情況,

需要拿到 vm 記憶體的話就必須得依賴 Dart VM ,上文說到,通過 vm_service 就可通過它提供的介面拿到,

通過 Future<MemoryUsage> getMemoryUsage 就能獲取到當前 isolate 所占用的資訊,來看下 MemoryUsage 的結構, 每個屬性都有詳細的解釋,這里就不再贅述了,

/// The amount of non-Dart memory that is retained by Dart objects. For
/// example, memory associated with Dart objects through APIs such as
/// Dart_NewWeakPersistentHandle and Dart_NewExternalTypedData.  This usage is
/// only as accurate as the values supplied to these APIs from the VM embedder
/// or native extensions. This external memory applies GC pressure, but is
/// separate from heapUsage and heapCapacity.
int externalUsage;

/// The total capacity of the heap in bytes. This is the amount of memory used
/// by the Dart heap from the perspective of the operating system.
int heapCapacity;

/// The current heap memory usage in bytes. Heap usage is always less than or
/// equal to the heap capacity.
int heapUsage;

那如何獲取到每個類物件的記憶體資訊呢?

通過 getAllocationProfile 獲取分配物件的資訊,通過members屬性來獲取到每個 class 所占用的堆資訊,

對齊標尺

對齊標尺用來測量當前 widget 所在螢屏的一個坐標位置,開啟吸附開關后可以自動吸附最近 widget,

標尺顯示當前坐標還是非常簡單的,通過手勢移動的坐標,來改變Positioned的位置即可,并通過螢屏的大小來計算出當前的距離,下面會著重講一下自動吸附的實作,

要吸附最近的 widget ,就必須找到當前位置的所在的 widget ,然后并畫出當前 widget 的一個大小范圍,最后設定標尺的位置即可,那么如何找到當前坐標的 widget 呢?

通過globalKey我們可以獲取到當前頁面的一個RenderObject,然后通過它的debugDescribeChildren 獲取到它的所有子節點,然后通過describeApproximatePaintClip獲取到當前物件坐標系中的Rect,之后在根據一些坐標轉換,判斷是不是在當前坐標范圍,最后根據RenderObject 的大小做一個排序,這樣我們就能知道最小的那個一定是當前坐標位置中最近的 widget 了,得到最近的 widget 之后,我們只需要將標尺的中心位置設定成離 widget 最近的四個角即可,

顏色吸管

可以查看到當前頁面任何像素的顏色,方便除錯 UI,

這個功能首先分為兩步,1、背景放大 2、獲取當前像素的顏色值,

如何放大圖片

在Flutter中,要想給圖片加一些效果,我們可以用到 BackdropFilter, 其實就是加上一層濾鏡效果,發現引數其實并不多,通過 ImageFilter就能添加具體的濾鏡,想要做一個放大的效果,我們可以使用 ImageFilter.matrix ,它能夠放大背景圖片, filterQuality 引數可以用來設定放大效果的質量,那如何放大對應的位置以及放大的倍數呢?

通過Matrix4便可以設定,通過我們手勢移動的位置,加上 scale 就能計算出它的矩陣引數,并賦值給ImageFilter.matrix就能得到放大效果,

如何獲取圖片像素及顏色值

在Flutter中想要截圖的話就必須借助RepaintBoundary了,配合globalKey我們就能獲取當螢屏的當前截圖了,

RenderRepaintBoundary boundary = rootKey.currentContext.findRenderObject();
Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png"/>獲取到截圖后,我們就需要通過移動的位置來獲取到圖片的當前像素值了,可以通過ImagegetPixelSafe 來獲取到 用 Uint32 編碼過的像素顏色值了(#AABBGGRR),最后我們只需要把abgr轉換成 argb 就好了,

int abgrToArgb(int argbColor) {
  int r = (argbColor >> 16) & 0xFF;
  int b = argbColor & 0xFF;
  return (argbColor & 0xFF00FF00) | (b << 16) | r;
}

網路除錯

在除錯 Flutter 網路的時候,要 mock 資料或者查看請求非常麻煩,需要連代理,使用抓包工具才可以進行這些操作,想要簡單的在手機上就能完成這些操作,所以網路除錯模塊目前支持的功能:

  • 支持所有網路請求抓取

  • 資料支持結構化展示,長按可以復制到剪貼板

  • 收藏請求,單獨展示;清空非收藏串列

  • 請求過濾與搜索(支持部分匹配、正則匹配)

  • 請求匯出 curl

  • 持久化與匯出 HAR

  • mock 回應內容

    • 完整har檔案映射

    • 修改單個欄位

  • 結構化資訊長按復制

看到這,你可能會問這是怎么攔截到所有的網路請求的呢?

這里通過 Dart 在編譯時的插樁從而達到對特定 API 的 Hook 效果(其實就是替換掉某個方法的實作從而添加自己的實作),由于篇幅問題,這里暫時不展開講 Hook 的具體流程,之后也會有另外的文章來詳細說這個,

Flutter 中的所有網路請求走的都是 package:http/src/base_client.dartBaseClient 類中的_sendUnstreamed, 因此,我們只需要 hook _sendUnstreamed 方法便可以攔截到所有的網路請求,

Logger

會展示使用 debugprint 函式列印的日志,特別是播放器的一些日志,在沒有 IDE 的情況下,查看日志還是很方便的,

攔截 print 有兩種方式:

  • Dart 中有一個runZoned方法,可以給執行物件指定一個 Zone,Zone 表示一個代碼執行的環境范圍,Zone 類似一個代碼執行沙箱,不同沙箱的之間是隔離的,沙箱可以捕獲、攔截或修改一些代碼行為,如 Zone 中可以捕獲日志輸出、Timer 創建、微任務調度的行為,同時 Zone 也可以捕獲所有未處理的例外,runZoned(...)方法定義:

R runZoned<R>(R body(), {
    Map zoneValues, 
    ZoneSpecification zoneSpecification,
    Function one rror
}) 
zoneValues: Zone 的私有資料,可以通過實體zone[key]獲取

zoneSpecification:Zone 的一些配置,可以自定義一些代碼行為,比如攔截日志輸出行為等,

這樣所有呼叫 print 方法輸出日志的行為都會被攔截,

runZoned(() => runApp(MyApp()), zoneSpecification: new ZoneSpecification(
    print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
      print(line);
}));
  • 通 hook 的方式

由于在 hook 的 print 方法里可能會呼叫 print 來列印日志造成死回圈,這里我們只 hook debugPrint 方法,對 package:flutter/src/foundation/print.dartdebugPrintThrottled 進行 hook 即可,

Channel Monitor

可以查看到所有的 channel 呼叫,包括方法名,時間,引數,回傳結果,


hook package:flutter/src/services/platform_channel.dartMethodChannel 類的invokeMethod方法即可,

目前存在的問題

目前只是完成了初步的版本,很多功能還需要繼續完善以及更多的新功能;接下來會從一些細節上繼續深入;現在網路除錯、channel 監控、Logger這些功能依賴于Hook方案,后續 Hook方案也會考慮開源,

總結

以上介紹了一些 UME 的核心功能以及實作,還有很多豐富的功能由于篇幅問題在這里就不繼續展開了,之后還會有更多有趣的東西出現,未來會考慮開源一些核心功能,

加入我們

我們是負責西瓜視頻客戶端 Flutter 基礎技術研發團隊,我們在 Flutter 工程,研發工具等方向深耕,支撐業務快速迭代的同時,提高 Flutter 開發調式打包效率,

如果你對技術充滿熱情,歡迎加入西瓜視頻 Flutter 基礎技術團隊或者西瓜基礎業務團隊,目前我們在上海、北京、杭州、均有招聘需求,內推可以聯系郵箱: tech@bytedance.com ;郵件標題: 姓名 - 作業年限 - 西瓜 - iOS/Android

更多分享

一例 Go 編譯器代碼優化 bug 定位和修復決議

位元組跳動破局聯邦學習:開源Fedlearner框架,廣告投放增效209%

抖音品質建設 - iOS啟動優化《原理篇》

iOS 性能優化實踐:頭條抖音如何實作 OOM 崩潰率下降50%+


歡迎關注「 位元組跳動技術團隊 」

簡歷投遞聯系郵箱「 tech@bytedance.com 」

點擊閱讀原文,快來加入我們吧!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/232621.html

標籤:其他

上一篇:你熟知的開源專案,幕后推手竟然是他們?

下一篇:視頻教程|3D版切水果游戲開發實戰8:專案發布

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more