iQIYI 앱 안드로이드 저가형 기기 성능 최적화

01

   배경소개하다

스마트폰 시장에서는 고급형 모델이 가장 많은 관심을 받는 경우가 많지만, 저가형 모델도 무시할 수 없는 점유율을 차지하고 있습니다. 저가형 시장의 요구를 충족하기 위해 많은 제조업체에서는 저가형 휴대폰 시리즈를 계속해서 출시하고 있습니다. 또한, 시스템 하드웨어의 빠른 반복으로 인해 지난 몇 년 동안의 중~고급 모델은 이제 저가형 모델로 분류되었습니다. iQiyi 앱은 거대한 사용자 기반을 보유하고 있으며, 그 중 저가형 모델 사용자도 상당한 부분을 차지합니다. 저가형 기계 최적화는 이러한 사용자에게 안정적이고 원활하며 효율적인 사용자 경험을 제공할 수 있습니다. 다음은 콜드 스타트, 유창성, 로딩 속도라는 세 가지 차원에서 저가형 기기를 위한 iQiyi APP의 최적화 전략을 소개합니다.


저가형 기계 등급 전략
최적화를 소개하기 전에 저가형 머신의 기준을 살펴보겠습니다. 저가형 머신에 대한 판단은 일반적으로 장치 모델, 메모리 크기, 시스템 버전과 같은 요소를 기반으로 합니다. iQiyi 앱에는 정책 배경에서 시나리오(시작, 유창성 등) 및 계층(메모리, 모델, 시스템 등)별로 최적화 전략을 구성하여 다양한 환경에서 최고의 경험을 보장할 수 있는 자체 저가형 기계 등급 전략이 있습니다. 시나리오.

02

   최적화 시작

출시는 앱이 사용자에게 열어주는 첫 번째 문입니다. 시간이 많이 소요되는 시간은 사용자의 후속 시청 경험과 유지에 직접적인 영향을 미치며 비즈니스 지표에 상당한 영향을 미칩니다. 따라서 스타트업 최적화는 기술 최적화 방향의 핵심 작업 내용입니다.

관련 소개

시작 단계의 시작점과 끝점: iQiyi 앱은 홈페이지 데이터가 시작점으로 Application.attachBaseContext를 사용하여 이 단계의 지속 시간을 일반적인 온라인 콜드 스타트 ​​시간으로 간주합니다. 이는 주로 Application 생성 단계, MainActivity 생성 및 표시 단계, 광고, 홈페이지 상단 및 하단 탐색 데이터 로드 및 렌더링, 홈페이지 데이터 로드 및 렌더링을 거치게 됩니다.
이 과정에서 비즈니스 계층이 어떤 작업을 했는지 정리하고, 그 실행의 필요성과 시기, 스케줄링 스레드의 합리성을 평가해야 하며, 메인 스레드의 상태를 모니터링해야 한다. 장기 수면 상태에 빠졌습니다. 메인 스레드 메시지/백그라운드 메시지 모니터링 및 관리, 기대에 미치지 못하는 작업이 트리거되는지 여부, 시스템 리소스가 완전히 활용되는지 여부, 사전 로드를 위해 유휴 기회가 완전히 활용되는지 여부 등
비즈니스 기능의 원자화: 시작 단계의 작업을 순차적으로 예약하고 리소스를 합리적으로 할당하기 위해 일련의 작업 관리 프레임워크 TaskManager가 개발되었으며 비즈니스 기능 구현은 사용자 정의 작업으로 패키징되어 충분한 세부 사항으로 분할되었으며 작업, 실행 예정 스레드, 실행 타이밍 등 간의 실행 종속성을 결정한 다음 통합 처리를 위해 TaskManager에 전달합니다. 이 작업 관리 계층은 시작 최적화 구현의 기초입니다.


최적화 실습

화면 홈 페이지 병합 열기

초기에 iQiyi APP에는 오프닝 화면과 홈 페이지라는 두 가지 활동이 있었습니다. 이 두 가지 활동은 사용자 경험에 문제를 가져왔습니다. 저가형 기기는 화면을 열고 홈 페이지에 들어갈 때 확실히 지연됩니다. 즉시 표시되지 않으며 사용자는 홈페이지 데이터를 볼 수 있으며 사진은 처음부터 로딩 과정을 거칩니다.
화면 열기 단계의 대부분의 장면에는 화면 열기 광고와 홈페이지를 하나의 활동으로 병합합니다. 화면 열기 광고 단계를 사용하여 화면 열기 페이지 아래에 홈페이지를 로드하고 홈페이지 데이터와 UI를 분리합니다. 병렬 처리를 위한 표시 이 단계를 최대화하면 부팅 화면 종료 시 즉시 홈페이지가 표시될 수 있으며, 저사양 기기에서의 지연이 크게 개선됩니다 .
홈페이지 렌더링은 화면 광고 열기에도 일정한 영향을 미칩니다. 광고 카운트다운 표시가 불안정하고 일부 광고 유형의 효과가 원활하지 않습니다. 홈 페이지 로딩은 광고 콜백 트리거 문제를 해결하기 위해 여러 단계로 나누어집니다. 카운트다운 디스플레이는 안정성을 보장하기 위해 SurfaceView 렌더링을 사용합니다.


작업 일정 최적화

시작 유형에 따라 시작 단계의 작업 실행 순서를 진행, 지연 또는 실행하지 않도록 배열하여 사용자가 가능한 한 빨리 대상 페이지를 볼 수 있도록 합니다. 다음은 iQiyi가 저사양 기기의 일반적인 시작 경로에서 작업을 조정한 내용입니다.


잠금 경합 해결

기본 라이브러리 로딩 잠금 경쟁: C 계층 라이브러리 로딩이 잠겨 있습니다. Java 계층은 Lib 라이브러리를 로드하기 위해 여러 스레드를 엽니다. C 계층에 도달한 후에도 로딩이 계속해서 수행되므로 Java 계층 스레드가 차단됩니다. 그리고 기다려. iQIYI는 애플리케이션 단계에서 Lib 라이브러리를 로드해야 하며 메인 스레드가 로드가 완료될 때까지 기다린 후 재생 모듈이 외부 목적을 위해 재생 페이지를 가져오는 상황에 직면하면 관련 JNI 메서드를 호출해야 합니다. 재생을 미리 로드해야 합니다. 관련 Lib 라이브러리가 필요하며 이로 인해 메인 스레드가 대기 상태로 전환됩니다. 시작 단계에서 대상 랜딩 페이지를 식별함으로써 재생 관련 Lib 라이브러리 사전 로딩을 수행할지 여부를 결정할 수 있으며, 이를 통해 일반적으로 홈 페이지로 시작하는 대부분의 사용자의 지연을 피할 수 있습니다. (테스트 머신 Redmi K40, Android12 시스템)

리소스 잠금 경쟁: iQiyi 홈페이지가 표시되기 전에 다른 모듈이 하위 스레드에 레이아웃 파일을 미리 로드하므로 LayoutInfalter / ResourceManager / AssertsManager 레이어 잠금을 놓고 치열한 경쟁이 벌어집니다. 홈페이지가 표시된 후 실행될 레이아웃을 미리 로드하는 작업을 예약하고, 미리 로드된 레이아웃이 동일한 하위 스레드에서 실행되도록 제한합니다. 개선 후 잠금 충돌 횟수가 크게 줄어드는 것을 볼 수 있습니다. 홈페이지가 더 빨리 표시됩니다.


기본 프로필

기준 프로필: Google은 2022년에 기준 프로필을 출시할 예정입니다. 이를 통해 개발자는 맞춤형 핫스팟 코드 기준 프로필을 APK에 구축할 수 있습니다. APP 설치 중에 시스템은 구성 파일을 통해 핫스팟 코드를 미리 컴파일합니다. 런타임에 포함된 코드 경로의 해석 및 JIT(Just-In-Time) 컴파일 단계를 건너뛰어 첫 번째 시작 코드 실행 속도를 향상시킬 수 있습니다.
시작 프로필: 시작 프로필은 위에서 언급한 기준 프로필의 하위 집합입니다. 시작 프로필을 사용하면 APK DEX 파일의 코드 레이아웃이 개선되어 포함된 클래스와 메서드가 더욱 최적화될 수 있습니다. iQiyi 앱은 시작 구성 파일을 통해 시작 단계 코드를 동일한 DEX 파일에 구축합니다. 위의 두 가지 전략을 사용하면 일부 모델에서 iQiyi 앱의 첫 실행 속도가 약 10% 증가합니다.



외부 링크 실행 최적화

외부 링크를 끌어오는 것도 중요한 시작 방법입니다. 일반적으로 H5, 공유, 타사 앱 등에 의해 시작됩니다. 일반적인 콜드 스타트와의 차이점은 외부 링크가 홈페이지가 아닌 특정 대상인 경우가 많습니다. 페이지. iQiyi의 가장 일반적인 시나리오는 랜딩 페이지를 미리 식별하면(애플리케이션 단계) 외부 링크가 플레이 페이지를 불러올 때 랜딩 페이지의 작업 우선순위를 조정할 수 있습니다. 플레이 페이지를 미리 식별하고 플레이어와 연결합니다. 작업이 미리 초기화됩니다. 이 전략을 통해 저가형 온보드 외부 링크는 약 1.5초 정도 방송 속도를 높일 수 있습니다.


03

   유창성 최적화

관련 소개
iQiyi 앱의 대부분의 페이지는 자체 개발한 카드 프레임워크를 기반으로 개발되었습니다. 카드 프레임워크는 기본 UI 레이아웃과 비즈니스 로직을 구현하기 위해 네이티브 코드를 사용하는 기반으로 백엔드에서 실행되는 CSS 제어를 통해 기본 컨테이너 스타일을 제어하여 페이지 블록과 동적 기능을 전체적으로 재사용합니다. 콘텐츠 스타일을 미세 조정합니다. 이는 전체 페이지 재사용과 양쪽 끝(Android 및 IOS)에서 로컬 미세 조정을 달성하기 위한 솔루션입니다. 이 프레임워크를 기반으로 앱 페이지의 부드러움이 최적화됩니다. 카드 프레임워크에는 다음과 같은 기능이 있습니다.
  • 높은 재사용성: 콘텐츠 블록(블록)은 컨트롤로 구성되고, 행은 여러 블록으로 구성되며, 카드는 여러 행으로 구성되며, 전체 목록 페이지는 여러 카드로 구성됩니다. 재사용 가능한 가장 작은 비즈니스 단위는 블록입니다.
  • 매우 동적: 백그라운드에서 CSS 파일 구성을 지원하고 특정 UI의 스타일(텍스트 크기, 색상, 둥근 모서리 등)을 동적으로 수정합니다.

최적화 실습

스타일 네이티브

카드 페이지의 역동성과 재사용성으로 인해 UI 레이아웃이 복잡해졌습니다. 블록 유형은 여러 스타일과 호환되어야 합니다. 예를 들어 그림의 네 모서리에는 다양한 유형의 아래 첨자 논리가 포함되어야 합니다. 아래 첨자 유형에는 순수 그림, 일반 텍스트, 그림 + 텍스트 및 선택 사항이 포함됩니다. 중간 형태. 다양한 스타일을 구현하면 보기 수가 많아지고 중첩 수준이 깊어져 일부 페이지가 저가형 컴퓨터에서 미끄러질 만큼 매끄럽지 않게 됩니다.
이러한 상황을 최적화하기 위해 안정적인 비즈니스 형태를 갖춘 일부 카드를 선택하고 이러한 카드의 스타일을 강화했으며 레이아웃을 대폭 간소화했습니다. 이로 인해 위아래로 슬라이드할 때 프레임 속도가 크게 증가합니다. 예를 들어, 워터폴 플로우 카드에서는 구현된 뷰 수를 40개 이상에서 17개로 줄이고, 다양한 저가형 시스템에서 레이아웃 수준을 6개에서 2개 레이어로 줄였습니다. 이로 인해 약 10%~20%의 슬라이딩 프레임이 발생했습니다. 비율이 증가했습니다 .

병합 도면 보기
위의 레이아웃 단순화 전략이 가져온 개선 효과는 분명하지만, 사업 형태의 다양화로 인해 일부 필요한 관점을 삭제할 수 없습니다. 뷰의 수와 수준을 더욱 줄이기 위해 일반적으로 사용되는 블록 레이아웃의 여러 뷰를 사용자 정의 뷰로 병합하고 뷰의 캔버스를 사용하여 텍스트, 그림, 버튼 및 기타 스타일 정보를 그립니다. 이 방법을 사용하면 뷰 수와 중첩 수준을 효과적으로 줄일 수 있지만 여전히 각 요소의 클릭 이벤트와 누르기 효과를 처리해야 합니다. 저사양 컴퓨터 에서는 이 전략을 사용하면 약 1~2fps 의 슬라이딩 프레임 속도 증가를 가져올 수 있습니다 .


사전 생성 및 비동기 로딩

레이아웃 사전 생성: 위 그림에 소개된 세 가지 스타일의 카드 중 동일한 블록 유형이 사용됩니다(위 및 아래 그림). 우리는 일반적으로 사용되며 재사용 가능성이 높은 이러한 블록 레이아웃을 시작 단계에서 캐시 풀에 미리 로드하므로 미리 생성된 레이아웃을 목록 슬라이딩에서 직접 사용할 수 있으므로 UI ​​그리기의 팽창 시간이 줄어듭니다.
레이아웃 비동기 생성 : 사전 생성은 일반적으로 사용되는 레이아웃에 좋은 영향을 미치지만 일반적이지 않은 레이아웃이 여전히 대부분을 차지합니다. 이 유형의 레이아웃은 AsyncLayoutInflater를 사용하여 스크롤 프로세스 중에 표시되는 레이아웃을 비동기적으로 생성하므로 레이아웃 생성 시간이 단축됩니다. 동시에 UI 스레드의 스크롤 레이아웃은 RecyclerView 프리패치의 효율성을 향상시킬 수도 있습니다.
RecyclerView 프리페칭: 많은 iQiyi 앱 페이지는 중첩된 RecyclerView를 사용하여 가로 스크롤 제품 양식을 생성합니다. 이 양식의 대부분의 카드는 한 화면에 3~5개의 항목을 표시합니다. 카운팅(setInitialPrefetchItemCount, 기본값은 2)에 따라 다릅니다. 이러한 유형의 카드가 노출될 때 지연을 줄일 수 있습니다.
메인 스레드는 UI가 아닌 작업 의 실행을 줄입니다 . 스크롤 프로세스 중에 메인 스레드를 감지하는 데 시간이 걸립니다. UI 스레드는 JSON을 구문 분석하고 데이터베이스 링크를 설정하는 일부 비 그리기 작업이 실행되는 것으로 나타났습니다. 등을 실행을 위해 비동기 작업에 넣습니다.


콜드 스타트 ​​UI 메시지 예약

저사양 컴퓨터의 콜드 스타트 ​​프로세스 동안 리소스 소비는 점차 최대 상태에 도달합니다. UI 메시지(UI 스레드에서 실행해야 함)와 실행해야 하는 기타 백그라운드 작업이 있습니다. 차단 및 매장지 분석을 통해 이 단계에서는 UI 스레드에서 4,000개 이상의 메시지(15초 이내)를 실행해야 합니다. 이러한 메시지의 실행 시간은 저사양 컴퓨터에서 1ms에서 150ms 사이입니다. 이러한 메시지가 실행되면 시스템의 UI 렌더링 메시지가 지연됩니다. 저사양 컴퓨터에서는 앱이 처음 시작될 때 슬라이딩 지연 및 느린 클릭 응답과 같은 문제가 발생합니다.
이 문제를 해결하기 위해 우리의 솔루션은 UI 스레드로 전송된 모든 메시지를 가로채서 사용자 정의 메시지 대기열에 추가한 다음 시스템 UI 메시지 대기열이 유휴 상태인지 모니터링하고 유휴 상태일 때 사용자 정의 대기열에서 메시지를 꺼내 리디렉션하는 것입니다. 시스템 UI 메시지 대기열 실행에 추가되며 일부 고품질 메시지를 공개하기 위해 화이트리스트 메커니즘이 추가되었습니다. 예외 처리를 위한 대체 메커니즘이 있습니다.
UI 메시지를 예약함으로써 콜드 스타트 ​​단계에서 저사양 컴퓨터의 지연이 크게 개선되었으며, 온라인 빅 데이터 모니터링을 통해 정지된 프레임 및 삭제된 프레임 수가 크게 줄었습니다. 콜드 스타트 ​​단계에서는 프레임 속도가 약 8fps만큼 증가합니다 .


성능 저하 전략

저사양 기기에서는 일부 효과를 다운그레이드하면 특정 시나리오에서 지연을 효과적으로 줄일 수 있습니다. iQiyi 앱은 다음과 같은 다운그레이드 전략을 구현했습니다.
모션 효과 다운그레이드: 상단 및 하단 탐색 모션 효과가 정적 이미지로 다운그레이드되고, 재생 제어 모션 효과가 꺼지고, 일부 제품 기능에 대해 모션 효과가 단순화되었습니다.
재생 다운그레이드: 롤링 지연 재생 및 일부 장면을 시작하지 않는 등의 전략입니다.
ViewPager 사전 로드 다운그레이드: 왼쪽 및 오른쪽 탭의 사전 로드를 비활성화하여 뷰 그리기 시간과 메모리 오버헤드를 줄입니다.
이미지 다운그레이드: 일부 페이지 애니메이션이 재생되지 않으며 이미지가 565픽셀 형식을 사용합니다.


04

   로딩 속도 최적화

관련 소개
앞서 언급한 시작 최적화 외에도 우리는 일부 중요한 페이지를 최적화하는 데 중점을 두고 있습니다. 왜냐하면 이러한 페이지는 사용자가 매우 자주 방문하고 해당 페이지의 최적화를 통해 사용자 경험을 크게 향상시킬 수 있기 때문입니다. 예를 들어 검색은 사용자가 자주 사용하는 기능 중 하나이므로 검색 동작을 주의 깊게 분석하고 검색의 각 단계를 최적화했습니다.

최적화 실습

사전 요청

일반적으로 페이지 렌더링 프로세스는 일반적으로 Activity의 onCreate 메서드에서 시작됩니다. 그런 다음 필요한 데이터를 얻기 위해 네트워크 요청을 합니다. 특정 데이터를 얻은 후 페이지가 렌더링됩니다. 이전 검색 시나리오에서도 이 프로세스를 따랐습니다.
필요한 데이터를 미리 얻을 수 있나요?
실제로 사용자가 홈페이지의 검색창을 클릭하면 이미 네트워크 요청에 필요한 매개변수가 있습니다. 그러면 클릭 시 미리 네트워크 요청을 시작할 수 있습니다. 네트워크 요청과 페이지 이동이 동시에 수행되므로 네트워크 요청 시간이 단축됩니다. 시스템 성능이 나쁠 경우 페이지에서 onCreate 메소드를 클릭하는 데 시간이 더 오래 걸리고 최적화하는 데 더 많은 시간이 걸립니다. 저사양 머신의 검증 시간은 약 200ms 단축됩니다.


일괄 발행

사용자가 페이지에 진입하면 첫 번째 화면 데이터만 표시되고, 페이지 하단의 데이터는 사용자가 슬라이딩 작업을 수행할 때까지 표시되지 않습니다. 따라서 첫 번째 화면 데이터 표시를 보장하는 데 우선순위를 두고 첫 번째 데이터 전달 크기를 줄여 데이터 수집, 데이터 전송 및 데이터 분석에 필요한 시간을 줄입니다. 첫 번째 화면 데이터 렌더링이 완료된 후 사용자가 슬라이딩 작업을 수행할 때 후속 데이터가 즉시 표시될 수 있도록 인터페이스 요청을 다시 시작합니다. 이 솔루션은 홈 페이지, 하프 플레이 페이지, 검색 등 여러 핵심 페이지의 최적화에 사용됩니다. 예를 들어 검색 시나리오에서 이 솔루션을 사용하면 확인 시간이 약 200ms 단축됩니다.


미리 생성된

레이아웃 사전 생성: 검색 중간 페이지가 유휴 상태일 때 재사용 가능성이 높은 레이아웃을 미리 캐시에 생성합니다. 페이지가 실제로 렌더링될 때 미리 생성된 레이아웃을 직접 사용하여 뷰를 확장합니다.
조각 사전 생성: 검색 중간 페이지가 유휴 상태인 경우 결과 페이지가 표시될 때 해당 컨테이너를 미리 생성할 필요가 없으므로 컨테이너 생성에 소요되는 시간이 줄어듭니다.



메인 스레드 최적화

페이지가 로드되면 페이지와 관련된 기본 스레드 작업이 최대한 먼저 실행되기를 바랍니다 . 중요한 작업 스케줄링이 선점되면 페이지 렌더링 효과에 영향을 미치게 됩니다. 메인 스레드의 Looper.loop()를 대신하는 내부 자체 개발 Tracepeed 도구를 통해 메인 스레드에서 시간이 많이 걸리는 작업을 발견할 수 있습니다. 시간이 오래 걸리는 우선순위가 낮은 작업이 먼저 실행되는 경우 중요한 작업이 먼저 실행되도록 작업 일정을 조정할 수 있습니다.
예를 들어, 검색결과 페이지 로딩 과정에서 이미지 로딩은 중요한 작업입니다. 그러나 저사양 컴퓨터에서는 경우에 따라 다른 작업이 메인 스레드를 선점하여 이미지 로딩 시간이 최대 1초까지 걸리는 경우도 있습니다. 이 시나리오에서는 이미지 로드 작업이 먼저 실행되고 시간 소비가 100+ms로 안정화되도록 작업 예약을 조정합니다.

비즈니스 로직 최적화

다양한 비즈니스에 대해 특정 비즈니스 로직을 분석하고 관련 로직을 최적화했습니다.
  • 빈 이미지 최적화: 선택 항목이 로드되면 일부 시나리오에서는 백엔드가 빈 이미지를 전달하고 이 빈 이미지도 로드되므로 페이지 로드 시간이 늘어납니다. 따라서 빈 이미지 로드를 제한합니다.
  • 고주파수 로직 최적화: 최적화 시 집중해야 할 포인트는 고주파수 방법입니다. 일반적으로 사용되는 일부 고주파수 방법을 최적화하면 각 페이지의 시간 소모를 최적화할 수 있습니다. 예를 들어, 기본 컨트롤의 초기화에서는 불필요한 메소드의 실행을 방지하고 빈도가 높은 메소드의 시간 소모를 줄입니다.
  • 시간이 많이 걸리는 방법의 비동기 실행: 페이지 로딩 프로세스 중에 우선순위가 낮은 일부 비즈니스 로직도 있습니다. 이러한 로직이 발견되면 비동기 프레임워크를 통해 실행될 수 있으므로 페이지 로딩 시간이 단축됩니다.


열화 방지

지속적인 최적화 후 페이지 로딩 시간이 안정적인 수준에 도달했습니다. 그러나 지속적인 개발 반복 중에 시간 소모가 약간 증가한 것을 발견했습니다. 이런 종류의 악화가 발생하는 것을 효과적으로 방지하는 방법은 무엇입니까?
코드에 주요 메소드를 삽입함으로써 파이프라인 작업이 매일 정기적으로 실행되고 여러 번 실행된 후 평균값이 계산됩니다. 페이지 로딩의 변동을 감지하려면 시각적인 방법을 사용하세요. 열화가 있는 경우, 작업 비교를 통해 두 작업 간 시간 소모의 차이를 직관적으로 찾아내고, 시간 소모의 차이를 분석, 최적화할 수 있습니다.


05

  요약 및 전망

저가형 기계 최적화에는 여러 가지 핵심 비즈니스 시나리오에서 소개된 최적화 방법 중 일부가 주요 성능 문제를 우선시하고 저가형 기계의 운영 성능을 효과적으로 향상시킵니다. 그 중 도구 분석, 온라인 모니터링 및 측정 표준이 있습니다. 필수입니다. 여기서는 언급하지 않았지만 성능 최적화를 위한 중요한 도구이기도 합니다. Android는 심각하게 파편화되어 있으며 저가형 휴대폰을 최적화하려면 갈 길이 멀습니다. 앞으로도 우리는 최적화를 위한 새로운 돌파구를 지속적으로 개선하고 찾아내고 기술 혁신을 통해 사용자에게 안정적이고 원활한 사용자 경험을 제공하며 고품질 성장을 촉진할 것입니다.


이 기사는 WeChat 공개 계정인 iQIYI 기술 제품 팀(iQIYI-TP)에서 공유되었습니다.
침해가 있는 경우 [email protected]에 연락하여 삭제를 요청하세요. 이 글은 " OSC 소스 생성 계획
" 에 참여하고 있습니다 . 이 글을 읽고 계신 여러분의 많은 참여와 공유 부탁드립니다.

동료 치킨 "오픈 소스" deepin-IDE 및 마침내 부트스트랩을 달성했습니다! 좋은 친구, Tencent는 Switch를 "생각하는 학습 기계"로 전환했습니다. Tencent Cloud의 4월 8일 실패 검토 및 상황 설명 RustDesk 원격 데스크톱 시작 재구성 웹 클라이언트 WeChat의 SQLite 기반 오픈 소스 터미널 데이터베이스 WCDB의 주요 업그레이드 TIOBE 4월 목록: PHP 사상 최저치로 떨어졌고 FFmpeg의 아버지인 Fabrice Bellard는 오디오 압축 도구인 TSAC를 출시했으며 Google은 대규모 코드 모델인 CodeGemma를 출시했습니다 . 오픈소스라서 너무 좋아요 - 오픈소스 사진 및 포스터 편집기 도구
{{o.이름}}
{{이름}}

추천

출처my.oschina.net/u/4484233/blog/11052737