etc2018. 11. 8. 09:43
  • Facebook은 Getafix라는 도구를 구축하여 버그 수정 프로그램을 자동으로 찾아 엔지니어에게 승인 할 것을 제안합니다. 이를 통해 엔지니어는보다 효과적으로 작업 할 수 있으며 전반적인 코드 품질을 향상시킬 수 있습니다.
  • 우리는 Getafix가 수천만 명이 사용하는 앱의 안정성과 성능에 기여하는 Facebook 규모의 프로덕션 환경에 최초로 도입되는 도구라고 생각합니다.
  • Getapix는 Sapienz 테스트 도구가 발견 한 버그에 대한 수정을 제안하는 Sapfix를 제공합니다. Getafix는 또한 정적 테스트 도구 인 Infer에서 발견 된 버그에 대한 수정을 제공합니다.
  • Getafix는 엔지니어의 과거 코드 수정 사항에 대해 배우기 때문에 엔지니어의 권장 사항은 직관적입니다.
  • Getafix는 이전 코드 변경 사항에서 수정 패턴을 학습하는보다 강력한 기술을 사용하여 이전 자동 수정 기술을 향상시킵니다. Getafix는보다 강력한 클러스터링 알고리즘을 사용하고 문제가있는 코드의 특정 줄 주변의 컨텍스트를 분석하여보다 적절한 수정을 찾습니다.

현대적인 생산 코드베이스는 매우 복잡하며 끊임없이 업데이트됩니다. 엔지니어의 도움없이 버그 수정을 자동으로 찾을 수있는 시스템을 만들기 위해 우리는 엔지니어가 코드베이스를 이전에 변경 한 내용을 바탕으로 도구를 만들었습니다. 숨겨진 패턴을 찾아서 새로운 버그에 대한 가장 가능성있는 수정 방법을 식별합니다.

Getafix라고 불리는이 도구는 수십억 명의 사람들이 사용하는 응용 프로그램의 안정성에 기여하는 Facebook에서 프로덕션에 배포되었습니다. Getafix는 두 가지 다른 Facebook 도구와 함께 작동하지만 모든 소스의 코드 문제를 해결하는 데이 기술을 사용할 수 있습니다. 현재 Inform 은 Android 및 Java 코드에서 null 포인터 예외와 같은 문제를 식별하는 정적 분석 도구 인 Infer 에서 발견 된 버그에 대한 수정을 제안 합니다. 를 통해 - 또한 수정 제안 SapFix - 감지 버그 Sapienz을, 우리의 애플 리케이션을위한 지능형 자동화 된 테스트 시스템. 이전에 SapFix 및 Sapienz에 대한 개요를 제공 했으므로 Getafix가 버그를 수정하는 방법 (응용 프로그램을 중단시킬 수있는 문제가 아니라 모든 코드 문제를 광범위하게 사용하는 방법)에 대해 자세히 알아 봅니다.

Getafix의 목표는 버그가 복잡하고 비 루틴적인 교정을 필요로 할 때를 결정해야하는 인간의 주시하에 컴퓨터가 일상적인 작업을 처리하도록하는 것입니다. 이 도구는 인간 엔지니어가 만든 수천 개의 과거 코드 변경 사항에 계층 적 클러스터링의 새로운 방법을 적용하여 변경 자체와 코드 변경에 대한 컨텍스트를 모두 조사하여 작동합니다. 이 방법을 사용하면 버그의 기본 패턴과 이전의 자동 수정 도구로는 찾을 수 없었던 해당 수정 사항을 감지 할 수 있습니다.

또한 Getafix는 버그 수정을 찾기 위해 검색해야 할 가능한 프로그램 변경 공간을 좁힐 수 있기 때문에 무작위 적 및 논리 기반 기술에 필요한 높은 계산 시간없이보다 신속하게 적절한 패치를 선택할 수 있습니다. 이보다 효율적인 접근 방식을 통해 Getafix를 프로덕션 환경에 배포 할 수 있습니다. 동시에 Getafix는 과거 코드 변경 사항을 인식하므로 사람 엔지니어가 쉽게 이해할 수있는 수정 사항을 제공합니다.

Getapix는 Facebook에 배포되어 Infer가보고하는 null 참조 해제 버그에 대한 수정 사항을 자동으로 제안하고 Sapienz가 플래그하는 null 참조 해제 관련 오류 오류에 대한 수정을 제안합니다. 또한 새로운 버전의 Infer로 기존 코드를 다시 방문 할 때 발견되는 코드 품질 문제를 해결하는 데 사용됩니다.

Getafix가 간단한 자동 수정 도구와 다른 점

현재의 산업 관행에서 자동 수정은 기본적으로 기본적인 문제에 사용되지만 코드 수정은 간단합니다. 예를 들어, 분석기가 "dead exception"에 대해 경고 할 수 있습니다.이 경우 개발자는 throw이전 에 추가하지 않았을 가능성이 큽니다 new Exception(...)변경을위한 자동 수정은 적용되는 특정 컨텍스트를 알지 못하는 채 린트 규칙의 작성자가 직접 정의 할 수 있습니다.

Getafix는 훨씬 더 일반적인 기능을 제공하므로 수정 내용이 상황에 따라 달라지는 경우 문제를 해결합니다 이 샘플 코드 예제에서 Getafix는 22 행의 Infer 버그에 대한 응답으로 다음 수정을 제공합니다.

Getafix에서 생성 된 수정 사항과 함께 코드 검토 포털에보고 된 샘플 버그.

이 수정은 변수 ctx뿐만 아니라 메서드의 반환 형식에 따라 달라집니다 간단한 보풀 교정과는 달리, 이러한 종류의 수정은 유추 자체로 구워 질 수 없습니다.

아래 그림에는 Getafix가 Infer 버그에 제공하는 수정 사항의 추가 예제가 있습니다. Infer의 버그가 동일하더라도 ( NullPointerException이 Throw되는 위험을 나타내는 null 메소드 호출 ) 각 수정 사항은 고유합니다. 수정 프로그램은 개발자가 일반적으로 만드는 것과 구별 할 수 없습니다.

핵심 기술 세부 사항으로 심층적으로 뛰어 들다.

Getafix는 아래 다이어그램에 표시된 도구 모음으로 구성됩니다. 이 섹션에서는 세 가지 주요 구성 요소 각각의 기능과 문제점에 대해 설명합니다.

트리 구분자는 트리 수준에서 변경 사항을 식별합니다.

추상 구문 트리 기반 차이 판별 기는 먼저 동일한 파일의 연속적인 개정과 같은 한 쌍의 원본 파일간에 만들어진 구체적인 편집을 식별하는 데 사용됩니다. 예를 들어, 주석을 if추가 @Nullable하거나, 주석을 추가 하거나 importreturn기존의 메소드 본문에 조기 에 조건을 추가하는 등과 같은 세분화 된 편집을 감지 합니다. 아래 예제에서 조건부 조기 반환 인 if dogis null, rename of publicto private및 메서드 이동이 콘크리트 편집으로 감지되었습니다. 라인 기반 diffing 도구는 두 방법 중 하나를 완전히 제거하고 삽입 한 것으로 표시하지만 트리 감별자는 이동을 감지하므로 이동 된 메서드  에서 삽입을 콘크리트 편집으로 감지 할 수도 있습니다 .

트리 구분자의 과제는 "이전"및 "이후"트리의 일부를 효율적이고 정확하게 정렬하기 때문에 올바른 구체적인 편집과 이전 트리에서 이후 트리로의 매핑이 발견됩니다.

수정 패턴을 마이닝하는 새로운 방법

Getafix는 새로운 상징적 인 표현들 사이에서 일반화하는 기존의 반 통일과 함께 새로운 계층 적 클러스터링 기법 을 사용하여 패턴 마이닝을 수행합니다 그런 다음 관련 트리 차이점의 모음을 만들고 해당 모음에서 가장 일반적인 프로그램 변환을 나타내는 수정 패턴을 사용합니다. 이 패턴은 추상적 일 수 있으며 프로그램 변환이 다른 "구멍"을 포함합니다.

다음 예제 이미지는 일련의 편집 결과로 나온 멘 드로 그램 (dendrogram)이라고하는 계층 적 구조를 보여줍니다. (위의 예에서 편집 한 것을 보여줍니다.) 각 행은 보라색의 "이전"과 파란색의 "후"- 일부 메타 데이터와 함께 편집 패턴을 보여줍니다. 각각의 수직 검은 색 막대는 계층 구조의 한 수준에 해당합니다. 여기서 검은 막대의 맨 위에있는 편집 패턴은 계층의 해당 수준에 속한 다른 모든 편집 내용의 반 통합으로 얻은 패턴입니다. 다른 편집 내용은 작고가는 검은 선으로 연결됩니다. 반 통일은 이전 견본의 편집이 개가 마시는 것과 유일한 차이점이있는 다른 편집과 함께 "개가 null이면 조기 회신"을 결합합니다. 결과는 공통점을 나타내는 추상 수정 패턴입니다. 상징물h0반 통일에 의해 도입 된 것으로, 문맥을 기반으로 인스턴스화 할 수있는 "구멍"을 나타냅니다.

그런 다음이 편집 패턴을 변수 이름에 더 많은 변형이 있지만 여전히 전체 구조가 동일한 다른 편집 패턴과 결합 할 수 있습니다. 이 프로세스는 우리가 트리를 올라갈 때 점점 더 추상적 인 편집 패턴을 생성합니다. 예를 들어,이 편집을 고양이 관련 편집과 결합하여 다이어그램의 상단 부근에 표시된 추상 편집을 얻을 수 있습니다.

그러나 더 심각하게도이 계층 적 매칭 프로세스는 Getafix가 코드 변경시 재사용 가능한 패턴을 발견 할 수있는 강력한 프레임 워크를 제공합니다. 아래의 그림은 일정 시간 동안 우리 코드베이스에서 Infer가보고 한 고정 된 null 포인터 오류가 수정 된 2,288 개의 모든 편집 결과를 결합하여 얻은 (깔끔하게 배치 된) 소형 dendrogram을 보여줍니다. 우리가 추구하는 수정 패턴은이 멍멍에 숨겨져 있습니다.

통합을 기반으로하지 않는 패턴 마이닝 개념은 새로운 것은 아니지만 새로운 버그에 대한 수정 사항을 비교적 적게 생성하고 순위를 매기는 데 사용할 수있는 패턴을 향상시키는 데 필요한 몇 가지 개선 사항이 필요했습니다.

이러한 변경 사항 중 하나 는 편집 결과로 변경 되지 않는 주변 코드의 일부를 포함 하는 것입니다. 이 변화는 사람들이 만드는 변화의 패턴뿐만 아니라 변화가 적용되는 맥락에서 패턴을 발견 할 수있게합니다. 예를 들어, 위의 첫 번째 dendrogram에서 if (dog == null) return;이전에 추가 된 두 가지 별개의 편집이 있음을 알 수 있습니다 dog.drink(...);dog.drink(...);변경되지 않았 더라도 패턴의 "앞"과 "뒤"부분에이 픽스를 적용 할 위치를 알려주는 문맥으로 포함됩니다. 편집 계층의 상위 레벨에서 dog.drink() 컨텍스트는 다른 컨텍스트와 병합되어 h0.h1()패턴이 적용될 수있는 장소를 제한하는 추상 컨텍스트 가됩니다. 보다 현실적인 예가 다음 절에서 설명됩니다.

과거의 자동 수정 도구에 관한 글에서 제시 한 그리 디 클러스터링 알고리즘은이 문맥을 배우기 쉽지 않습니다. 이것은 그리 디 클러스터링 알고리즘이 각 클러스터의 단일 표현을 유지하기 때 문에, 이는 학습 데이터의 모든 편집에 존재하지 않는 추가 컨텍스트를 포함하지 않기 때문입니다 예를 들어 위 의 예제 와 병합 if (list != null) return;하기 전에 삽입 편집을하면 욕심 클러스터링은 조기 반환을 삽입 할 위치에 대한 모든 내용을 잃게됩니다. Getafix의 계층 적 클러스터링 접근법은 각 레벨에서 가능한 한 많은 문맥을 유지하며 구조에서 더 일반적으로 높아집니다. 특정 수준에서, 우리가 배우기를 희망하는 일반적인 상황조차도 사라지 겠지만, 여전히 구조의 더 낮은 수준에 존재할 것입니다.do(list.get());dog.drink()

주변 코드 외에도 편집을 Infer 버그 리포트와 연관시켜 처음에 알려주는 Infer 버그 리포트를 사용하여 편집 패턴이 해당 버그 리포트와 어떻게 관련되는지를 배울 수 있습니다. 버그 리포트의 Infer blame 변수는 위의 첫 번째 dendrogram 그림에서 "errorVar"로 표시되고 반 통일에 참여하여 구멍으로 끝납니다 h0이렇게하면 나중에 h0추측 된 변수를 새로운 Infer 버그 보고서 로 대체 하여 수정 패턴을보다 구체적으로 만들 수 있습니다.

Getafix가 패치를 만드는 방법

마지막 단계는 버그 마이닝 소스 코드를 취해 패턴 마이닝 단계에서 패턴을 수정하고 패치 된 버전의 소스 코드를 생성합니다. 일반적으로 선택할 수있는 수정 패턴이 많이 있습니다 (위의 dendrogram에서 볼 수 있듯이). 따라서이 단계에서 해결해야 할 과제는 특정 버그를 수정하기위한 올바른 패턴을 선택하는 것 입니다. 패턴이 여러 위치에 적용되는 경우 Getafix는 올바른 일치 항목 도 선택해야합니다 다음 예는 우리의 일반적인 접근 방식과 Getafix에서이 문제를 해결하는 방법을 설명합니다.

예 1. 위에서 채취 한 패턴을 고려하십시오. h0.h1();if (h0 == null) return; h0.h1();

이전에 보이지 않는 코드에서 다음 패치를 생성하는 단계를 간략하게 설명합니다.


Getafix는 다음 단계를 사용하여 패치를 만듭니다.

  1. 이전 부분과 일치하는 하위 AST 찾기 : mListView.clearListeners();
  2. 구멍을 인스턴스화 h0하고h1
  3. 부분 AST를 부분 후에 인스턴스화 된 것으로 바꾸십시오.

참고 h0부분 때문에 변성 컨텍스트의 개재물 바인딩 된 이후에 h0.h1();유용하게 적용되는 패턴에 대한 수를 제한한다. 수정되지 않은 문맥이 없었다면 그 패턴은 그대로 였을 것 <nothing> → if (h0 == null) return;입니다. 이 패턴은 의도하지 않은 장소 (예 : after mListView.clearListeners(); 또는 after)에 적용됩니다 mListView = null;.

삽입 전용 패턴은 실제로 문맥 h0.h1();이있는 패턴이 다른 명령문 앞에 리턴을 삽입하는 패턴으로 반 통합 되는 덤 드로 그램 (dendrogram)에서 더 높게 나타납니다 다음 예는 Getafix가 너무 많은 곳에서 적용되는 패턴을 다루는 방법을 보여줍니다.

예 2. 다음 패턴을 고려하십시오. h0.h1()h0!=null && h0.h1()

일반적으로이 패치는 if조건이나 return표현식 내의 수정 사항에서 채취 되므로 해당 패치가 적용될 것으로 예상됩니다. 그러나 위의 예에 표시된 호출 문과 같은 다른 상황에서도 일치 mListView.clearListeners();합니다. Getafix의 순위 전략은 패턴이 실제로 수정이며 주어진 컨텍스트에 대해 가장 가능성이 높은 수정 가능성을 추정하려고 시도합니다 이 전략을 사용하면 나중에 검증 단계에 대한 의존도가 낮아 지므로 시간을 절약 할 수 있습니다.

위의 패턴은보다 구체적인 다른 패턴과 경쟁 if (h0.h1()) { ... }→ if (h0!=null && h0.h1()) { ... }또는 전화에만 적용 예 1의 패턴, 문장 보다는 표현 . 더 구체적인 패턴은 더 적은 위치에서 일치하므로 상황에보다 전문화 된 것으로 간주되므로 Getafix는 더 높은 순위를 매깁니다.

구현 및 성능

Getapix는 Facebook에 배포되어 정적 분석 도구 인 Infer가보고 한 null 참조 해제 버그에 대한 수정 사항을 자동으로 제안하고 Sapienz가 발견 한 null 참조 취소 관련 크래시 버그에 대한 수정 사항을 제안합니다. 과거의 뛰어난 Infer 버그를 해결하는 데에도 사용되고 있습니다.

한 실험에서는 5 줄 미만이 변경된 약 200 개의 작은 편집 데이터 집합에 대해 동일한 Infer null 메서드 호출 버그에 대한 Getafix 계산 된 수정 내용과 실제 사람이 작성한 수정 내용을 비교했습니다. 이러한 경우의 약 25 %에서 Getafix의 가장 높은 등급의 패치는 사람이 만든 패치와 정확히 일치합니다 .

또 다른 실험에서는 Instagram 코드베이스의 하위 집합을 살펴보고 약 2,000 개의 null 메소드 호출 문제를 대량 수정하려고 시도했습니다. Getafix는 약 60 %의 버그에서 패치를 시도 할 수있었습니다. 이러한 시도의 약 90 %가 자동 유효성 검사를 통과했습니다. 즉, 컴파일이 가능하고 더 이상 경고를 방출하지 않습니다. 전반적으로 GetFix는 null 메서드 호출 버그 중 1,077 건 (약 53 %)을 자동으로 패치했습니다.

소개 된 새로운 Infer 버그에 대한 수정을 제안하는 것 외에도 동일한 인프라를 사용하여 Infer 버그의 백 로그를 정리하여 과거의 코드 검토와 코드베이스를 정리했습니다. 우리는 수백 청소했습니다 Null을 허용하지 반환 완전 추론 버그와 필드하지 null 허용 이러한 노력의 일환으로 완전 추론 버그. 흥미롭게도, nullable이 아닌 return 및 no nullable 버그 옆의 자동 수정을 제안하면 수정 비율이 56 %에서 62 %로, 51 %에서 59 %로 증가했습니다. Getafix가 이러한 제안을 표시했기 때문에 전반적으로 지난 두 달 동안 몇 가지 추가 버그가 수정되었습니다.

또한 Getapix는 Sapienz가 감지 한 충돌을 해결하기 위해 SapFix에 대한 수정 사항을 생성합니다. 지난 몇 개월 동안 Getapix는 SapFix에서 사용하는 수정 후보 중 절반을 제공했으며 유효한 것으로 간주했습니다 (모든 테스트가 통과되었습니다). Getafix가 SapFix에 제공하는 모든 수정 후보자 중 약 80 %가 모든 테스트를 통과했습니다.

Getafix의 영향력 증가

Getafix는 일상적인 버그 수정 작업을 컴퓨터가 처리하도록하는 우리의 목표를 향해 나아갈 수 있도록 도와주었습니다. 테스트 및 검증 도구를 지속적으로 개선하면서 Getafix는 배포 실패의 상당 부분을 막을 수있을 것으로 기대합니다.

픽스 패턴 Getafix 광산은 Infer 관련 픽스에만 응답 할 필요는 없습니다. 실제로 수동 코드 검사에 대한 응답으로 수정 된 사항도있을 수 있습니다. 이 수정 패턴 소스를 사용하면 반복적 인 코드 검토를 자동화 할 수 있습니다. 즉, 과거에 여러 번 코드베이스를 통해 플래그 지정되고 수정 된 버그는 인간이하지 않아도 향후 코드 커밋에서 자동으로 플래그가 지정 될 수 있습니다.

Getafix는 대용량 코드 모음 및 관련 메타 데이터의 통계 분석에 의존하는 지능적인 도구를 개발하려는 우리의 전반적인 노력의 일환입니다. 이러한 도구는 코드 발견, 코드 품질 및 운영 효율성을 포함하여 소프트웨어 개발 라이프 사이클의 모든 측면을 개선 할 수 있습니다. Getafix에서 얻은 통찰력은이 공간에 추가 도구를 구축하고 배포하는 데 도움이됩니다.

출처 : https://code.fb.com/developer-tools/getafix-how-facebook-tools-learn-to-fix-bugs-automatically/

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
Posted by 프리스케이터