Knex로 테스트를 10배 더 빠르게 만든 방법
5971 단어 mochajavascriptprofilingchai
나는 그것을 통해 걷는 게시물을 작성한다고 생각했습니다. 다른 사람에게 도움이된다면 적어도 유용한 것이 나올 수 있습니다.
배경
지난 며칠 동안 테스트 속도를 개선하기 위해 노력했습니다. 처음에는 괜찮았지만 더 많은 테스트를 추가할수록 실행 시간이 더 오래 걸렸습니다. 일부 섹션에서 각 테스트가 600-1300ms가 걸리는 지점에 도달했을 때 나는 그것에 대해 뭔가를 할 수 있을 만큼 지쳤습니다.
출발점
나는 그것이 아마도 데이터베이스 일 것이라고 생각했지만 도움이 될 스모킹 건이 있는지 알아보기 위해 먼저 일부basic Node profiling를 시도하는 것이 좋겠다고 생각했습니다.
해당 페이지의 지침에는
--prof
가 노드 프로파일링을 활성화한다고 나와 있습니다. Node를 "그냥"실행하는 것이 아니라 Mocha를 실행하여 프로필 결과를 얻고 싶었습니다. 플래그를 --v8-prof
로 추가하면 Mocha가 플래그를 노드로 전달합니다.$ NODE_ENV=test mocha --v8-prof --require test/fixtures.js
$ node --prof-process isolate-0x102d57000-8614-v8.log > processed.txt
불행하게도 거기에는 분명한 것이 나타나지 않았지만 C++ 진입점은 데이터베이스 이론을 확고히 했습니다.
[C++ entry points]:
ticks cpp total name
3497 72.1% 58.8% T __ZN2v88internal21Builtin_HandleApiCallEiPmPNS0_7IsolateE
1290 26.6% 21.7% T
HandleApiCall
에서 72% - 우리가 만들고 있는 유일한 API 호출은 데이터베이스에 대한 것이므로 시작하기에 좋은 곳으로 보입니다.기러기 추적
불행히도 이것은 내가 엉망인 곳입니다. 문제가 실제로 무엇인지 식별하는 것을 잊고 문제를 해결하기 시작했습니다.
knex("table").del()
를 사용하여 개체를 개별적으로 삭제하는 것으로 변경 사항을 테스트하는 데 시간을 낭비했습니다. 거위를 쫓는 것을 멈췄다
결국 나는 문제가 실제로 어디에 있는지 확인하기 위해 측정하는 것을 기억했습니다. 테스트가 아니라고 가정하면
clean
및 seed
두 단계가 있습니다. 어느 것이 문제인지 식별해 봅시다.exports.dbCleanAndSeed = async function () {
let cleanFinishedMs, seedFinishedMs, startMs;
const options = { ignoreTables: ["knex_migrations", "knex_migrations_lock"] };
startMs = Date.now()
await knexCleaner.clean(database, options);
cleanFinishedMs = Date.now();
await database.seed.run();
seedFinishedMs = Date.now();
console.log("Clean took: %i; seed took %i", cleanFinishedMs - startMs, seedFinishedMs - cleanFinishedMs);
}
트릭을 수행하고 내가 찾아야 할 곳을 알려주었습니다.
site tests
Clean took: 28; seed took 675
✓ can get the sites page (732ms)
Clean took: 28; seed took 743
✓ get the 'add a new site page' (776ms)
Clean took: 29; seed took 592
✓ add a new site (630ms)
Clean took: 26; seed took 594
✓ add a site and see it on the sites page (628ms)
Clean took: 29; seed took 748
✓ can't add a new site with no creds (779ms)
Clean took: 27; seed took 652
✓ gets 404 for a site that doesn't exist (684ms)
Clean took: 30; seed took 732
✓ can't add a new site with no domain (769ms)
Clean took: 26; seed took 609
✓ can't add a new site with no active value (640ms)
괜찮아. 따라서 청소는 확실히 문제가 아닙니다!
그래도 5개의 시드 파일이 있습니다. 특히 어떤 파일이 문제인지 궁금하십니까? knex에 대한 소스 코드가 있으므로 시드 로딩 비트를 찾고 계측하기 쉬운지 확인하겠습니다.
_waterfallBatch()
의 knex/lib/seed/Seeder.js
가 실제로 시드를 로드하는 기능인 것처럼 보이므로 거기에서 타임 스탬프를 수행해 보겠습니다. async _waterfallBatch(seeds) {
const { knex } = this;
const log = [];
for (const seedPath of seeds) {
const importFile = require('../util/import-file'); // late import
const seed = await importFile(seedPath);
try {
const startMs = Date.now()
await seed.seed(knex);
const endMs = Date.now()
console.log(`${seedPath} took ${endMs - startMs} ms`);
[...]
실행…
seeds/01_user_seed.js took 147 ms
seeds/02_site_seed.js took 6 ms
seeds/03_review_seed.js took 3 ms
seeds/04_campaign_seed.js took 5 ms
seeds/05_redirect_seed.js took 461 ms
… 오. 예, 꽤 결정적입니다.
리디렉션 파일을 보면 유력한 범인이 보입니다.
05_redirect_seed.js
: const geoIpData = await iplocate(remoteIp);
로드된 모든 단일 시드에 대한 Ageo IP lookup. 그렇게 할 것입니다.
01_user_seed.js
: return knex('users').insert([
{email: '[email protected]',
passwordHash: Bcrypt.hashSync("Sherlock",
parseInt(process.env.BCRYPT_SALT_ROUNDS))
}])
그리고 삽입된 모든 사용자에 대한 bcrypt 해시. 그것은 그것을 설명할 것입니다.
결론
사용자 시드의 경우 Bcrypt 솔트 라운드를 1로 줄였습니다. 로컬 테스트이므로 공격에 저항할 필요가 없습니다.
리디렉션을 위해 시드 파일에 사용된 IP에 대한 조회 테이블을 구현했습니다. 결과는 즉시 볼 수 있습니다.
seeds/01_user_seed.js took 9 ms
seeds/02_site_seed.js took 5 ms
seeds/03_review_seed.js took 5 ms
seeds/04_campaign_seed.js took 5 ms
seeds/05_redirect_seed.js took 8 ms
그게 끝입니다. 다른 사람을 돕는 희망!
Reference
이 문제에 관하여(Knex로 테스트를 10배 더 빠르게 만든 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/arafel/how-i-made-my-tests-faster-3eef텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)