소프트웨어 성능 - 유틸리티 가이드
11888 단어 codequalityperformanceproductivity
코드 예:
let i = 0;
const stopAt = Date.now() + 1000;
while (Date.now() < stopAt) {
i++;
}
console.log(i); // ~8,312,450
내 기계에서 위의 스크립트를 실행해서 약 800만 개의 숫자를 출력했다.이것은 내 기계가 현재 날짜를 계산하여 시간과 비교하고 1초 안에 800만 번의 변수를 증가시킬 수 있다는 것을 의미한다.
애플리케이션 성능 문제 해결 방법
우리는 개발자들이 그들의 코드를 최적화하여 가능한 마지막 성능을 얻는 데 무수한 시간을 들이는 것을 보았고 개발자들은 코드가 정상적으로 작동하기만 하면 성능에 전혀 관심이 없다는 것을 보았다.
성능 문제를 해결하는 가장 좋은 방법이 무엇인지 이해하기 위해서는 왜 소프트웨어를 작성해야 하는지 먼저 이해해야 한다.
우리는 소프트웨어를 짜서 사람들을 돕는다.
우리가 작성한 소프트웨어가 많을수록 소개하는 도구, 기술과 방법이 많을수록 우리가 개발한 소프트웨어의 유일한 목적인 사람들을 돕는 것을 잊기 쉽다.
이러한 점을 감안하여 소프트웨어에 대한 모든 변경은 다음과 같은 두 가지 목표 중 하나를 실현해야 한다.
그래서 우리는 속도와 유지보수성 사이의 균형을 찾아야 한다.이런 균형은 우리의 응용 프로그램, 서비스 대상, 코드가 실행되어야 하는 속도, 그리고 내가 보기에 가장 중요한 것은 코드가 실행되는 주파수에 달려 있다.
예를 들어 개발자가 구글에서 성능을 처리하는 방식은 우리가 초창기 회사에서 MVP 성능을 처리하는 방식과 완전히 다르다.
중요한 부분에 최적화:
과거에 개발자들은 자주 다음과 같은 문제에 대해 논쟁을 멈추지 않았다.
let i = 0;
// Which one is faster? i++? ++i?
i++;
++i;
어느 것이 더 빠릅니까?i++++나?답은:이것은 중요하지 않다.
우리는 이미 마이크로초 안에 실행된 코드를 최적화하기 위해 주의력을 잃기 쉽다.전형적인 기계 한 대가 백만분의 1초도 안 되는 시간 안에 몇 십 번의 이런 조작을 완성할 것이다.
따라서 이러한 비트의 성능을 최적화하기 위해 코드를 변경하면 코드 변경의 두 주요 목표 중 하나와 충돌할 수 있다. 코드를 더욱 쉽게 사용할 수 있고 차이는 최대 몇 초 밖에 안 된다.
일반적인 프로그램은 입출력에 대부분의 불러오는 시간을 소비하기 때문에 2마이크로초의 순환을 최적화하려고 시도하기보다는 1마이크로초가 걸린다. 데이터베이스 조회를 최적화하거나 HTTP 요청을 그룹으로 나누려고 시도하는 것이 가장 좋다.
한마음 한뜻으로 협력하다동등한 보수
다음 JavaScript 코드에서 두 개의 데이터베이스 질의를 호출할 수 있습니다. 두 번째 질의는 두 번째 질의가 종속 관계가 없는 경우에만 첫 번째 질의가 완료된 후에 초기화됩니다.
const user = await User.findOne({ id: 1 });
const orders = await Order.find({ userId: 1 });
첫 번째 질의가 완료될 때까지 기다리지 않고 두 번째 질의를 실행하면 약 100ms를 절약할 수 있습니다.const [user, orders] = await Promise.all([
User.findOne({ id: 1 }),
Order.find({ userId: 1 })
]);
코드 몇 줄만 있으면 우리는 100밀리초를 절약할 수 있다.코드를 몇 줄 수정할 때 같은 노력을 했지만 첫 번째 변경에서 몇 초 절약했고 두 번째 변경에서 100밀리초(첫 번째 변경의 10만 배)를 절약했다.
또 다른 예는 for 순환에서 데이터베이스 조회를 실행하는 것입니다.
const usersIds = [1, 2, 3, 4, 5, 6, 7];
for (const userId of usersIds) {
const user = await User.findOne({ id: userId });
// do something with the user
}
이 코드는 사용자 id를 가져옵니다. 모든 id에 대해 데이터베이스를 조회하여 이 사용자를 가져옵니다. 우리의 예시에서 이 사용자는 7개의 호출을 보내서 7번의 네트워크 왕복을 초래합니다. 이것은 매우 비싸습니다.만약 우리가 코드를 바꾸면, 하나의 조회로 모든 사용자를 찾은 다음, 메모리에서 일치하는 id를 찾으면, 우리는 6번의 네트워크 왕복만 절약할 수 있다. 아마도 600밀리초일 것이다.
const usersIds = [1, 2, 3, 4, 5, 6, 7];
const users = await User.find({ id: { $in: usersIds } });
for (const userId of usersIds) {
const user = users.find(user => user.id === userId);
// do something with the user
}
현재, 이 코드를 볼 때, 우리는 최고급 순환에서 수조를 다시 순환시켜 시간 복잡도를 O (n^2) 로 만들었다는 것을 알 수 있다. 우리는 이를 해시맵으로 변환하고 사용해서 최고급 순환의 시간 복잡도를 O (n) 로 바꾸기를 희망한다.const usersIds = [1, 2, 3, 4, 5, 6, 7];
const users = await User.find({ id: { $in: usersIds } });
const usersMap = {};
for (const user of users) {
usersMap[user.id] = user;
}
for (const userId of usersIds) {
const user = usersMap[user.id];
// do something with the user
}
그러나 우리가 실시간으로 볼 때 하나의 항목을 순환하는 데 1마이크로초(백만분의 1초)가 필요하기 때문에 내 usersIds
의 항목이 평균 10개가 있다면 O(n^2)는 0.1밀리초가 걸릴 것이다.아직 개선할 여지가 있지만, 나는 차라리 개선할 만한 곳에 시간을 쓸지언정, 우리가 어떻게 더 많은 코드를 작성해서 기계의 성능의 마지막 부분을 압축하는지 주의해야 한다. 이것은 개발자로 하여금 이 코드들을 이해하기 어렵게 하고, 우리의 비싼 시간을 소모하게 할 것이다.이것은 가치가 없다. 심지어는 코드를 폄하하는 것이라고 말할 수도 있다.
결론
아래의 평론에서 당신의 생각을 저에게 알려 주세요.
나에 관하여
나는 소프트웨어 엔지니어로 기술을 통해 자동화를 실현하고 사람들을 돕는 데 열중한다.
Reference
이 문제에 관하여(소프트웨어 성능 - 유틸리티 가이드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hafez/software-performance-a-pragmatic-guide-5cp8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)