お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。

TypeScript + SWCと組み合わせてJestを回してるとテストケースの増加に伴いメモリリークが発生する現象が起きます。メモリに余裕があれば問題にはならないですが、開発機のメモリが足りないとかCIで使ってるECSのメモリが足りないとか、引っかかるケースもあると思います。

今回はこの問題に対する対処法を書いていきます。完全には改善されませんが、かなりマシになります。参考までに今回の検証では283MB使ってたのが67MBまで減りました。

この現象はNode.js 16.11.0以降で発生するらしいので、それ以前の環境では起きないかもしれません。

確認環境

Node.js v20.0.0

module version
@swc/cli 0.1.62
@swc/core 1.3.59
@swc/jest 0.2.26
@types/jest 29.5.1
@types/node 20.2.3
jest 29.5.0
jest-watch-typeahead 2.2.2
typescript 5.0.4

確認用のテストコード

以下のテストコードを書いたファイルを100ファイル作り、それを流して確認しています。

describe('example1', () => {
  it('1', () => {
    expect(1).toBe(1);
  });
  it('2', () => {
    expect(2).toBe(2);
  });
  it('3', () => {
    expect(3).toBe(3);
  });
  it('4', () => {
    expect(4).toBe(4);
  });
  it('5', () => {
    expect(5).toBe(5);
  });
});

describe('example2', () => {
  it('1', () => {
    expect(1).toBe(1);
  });
  it('2', () => {
    expect(2).toBe(2);
  });
  it('3', () => {
    expect(3).toBe(3);
  });
  it('4', () => {
    expect(4).toBe(4);
  });
  it('5', () => {
    expect(5).toBe(5);
  });
});

確認環境一式

以下のリポジトリに確認したソースコードを一式格納しています。

[blogcard https://github.com/Lycolia/jest-memory-leak-example]

メモリリークしていく様子

(41 MB heap size)
(42 MB heap size)
(52 MB heap size)
(51 MB heap size)
(37 MB heap size)
(47 MB heap size)
(47 MB heap size)
(50 MB heap size)
(60 MB heap size)
(60 MB heap size)
(62 MB heap size)
(71 MB heap size)
(73 MB heap size)
(74 MB heap size)
(84 MB heap size)
(85 MB heap size)
(86 MB heap size)
(96 MB heap size)
(97 MB heap size)
(99 MB heap size)
(108 MB heap size)
(110 MB heap size)
(111 MB heap size)
(120 MB heap size)
(122 MB heap size)
(124 MB heap size)
(75 MB heap size)
(83 MB heap size)
(84 MB heap size)
(86 MB heap size)
(96 MB heap size)
(96 MB heap size)
(97 MB heap size)
(107 MB heap size)
(108 MB heap size)
(109 MB heap size)
(118 MB heap size)
(120 MB heap size)
(121 MB heap size)
(130 MB heap size)
(132 MB heap size)
(133 MB heap size)
(143 MB heap size)
(144 MB heap size)
(145 MB heap size)
(154 MB heap size)
(156 MB heap size)
(157 MB heap size)
(166 MB heap size)
(168 MB heap size)
(169 MB heap size)
(179 MB heap size)
(181 MB heap size)
(182 MB heap size)
(191 MB heap size)
(193 MB heap size)
(194 MB heap size)
(203 MB heap size)
(205 MB heap size)
(207 MB heap size)
(216 MB heap size)
(217 MB heap size)
(219 MB heap size)
(228 MB heap size)
(230 MB heap size)
(231 MB heap size)
(240 MB heap size)
(242 MB heap size)
(243 MB heap size)
(252 MB heap size)
(254 MB heap size)
(255 MB heap size)
(264 MB heap size)
(266 MB heap size)
(267 MB heap size)
(277 MB heap size)
(278 MB heap size)
(280 MB heap size)
(195 MB heap size)
(204 MB heap size)
(203 MB heap size)
(212 MB heap size)
(213 MB heap size)
(214 MB heap size)
(223 MB heap size)
(224 MB heap size)
(226 MB heap size)
(235 MB heap size)
(237 MB heap size)
(238 MB heap size)
(247 MB heap size)
(249 MB heap size)
(250 MB heap size)
(259 MB heap size)
(261 MB heap size)
(262 MB heap size)
(271 MB heap size)
(273 MB heap size)
(274 MB heap size)
(283 MB heap size)

Test Suites: 100 passed, 100 total
Tests:       1000 passed, 1000 total
Snapshots:   0 total
Time:        11.347 s, estimated 12 s

解消方法

npm i -D @side/jest-runtime などで@side/jest-runtimeを導入し、jest.config.jsに以下の行を追加することで改善します。

  runtime: '@side/jest-runtime',

このコードで何か既存の実装やテストに影響が発生するかどうかは確認していませんが、後述する@side/jest-runtimeが生まれる切欠になったPRの様子を見る限り大丈夫なんじゃないかなとなんとなく思っています。

メモリリークが改善したあとの様子

(39 MB heap size)
(39 MB heap size)
(47 MB heap size)
(47 MB heap size)
(34 MB heap size)
(42 MB heap size)
(41 MB heap size)
(49 MB heap size)
(51 MB heap size)
(59 MB heap size)
(59 MB heap size)
(60 MB heap size)
(68 MB heap size)
(69 MB heap size)
(77 MB heap size)
(77 MB heap size)
(85 MB heap size)
(86 MB heap size)
(95 MB heap size)
(95 MB heap size)
(95 MB heap size)
(103 MB heap size)
(104 MB heap size)
(112 MB heap size)
(112 MB heap size)
(120 MB heap size)
(121 MB heap size)
(31 MB heap size)
(38 MB heap size)
(37 MB heap size)
(44 MB heap size)
(46 MB heap size)
(54 MB heap size)
(54 MB heap size)
(54 MB heap size)
(62 MB heap size)
(62 MB heap size)
(70 MB heap size)
(71 MB heap size)
(79 MB heap size)
(79 MB heap size)
(87 MB heap size)
(88 MB heap size)
(96 MB heap size)
(96 MB heap size)
(97 MB heap size)
(105 MB heap size)
(105 MB heap size)
(31 MB heap size)
(39 MB heap size)
(37 MB heap size)
(44 MB heap size)
(46 MB heap size)
(54 MB heap size)
(54 MB heap size)
(54 MB heap size)
(62 MB heap size)
(62 MB heap size)
(70 MB heap size)
(70 MB heap size)
(78 MB heap size)
(79 MB heap size)
(87 MB heap size)
(88 MB heap size)
(96 MB heap size)
(96 MB heap size)
(96 MB heap size)
(104 MB heap size)
(105 MB heap size)
(31 MB heap size)
(39 MB heap size)
(37 MB heap size)
(45 MB heap size)
(46 MB heap size)
(54 MB heap size)
(54 MB heap size)
(54 MB heap size)
(62 MB heap size)
(63 MB heap size)
(70 MB heap size)
(71 MB heap size)
(78 MB heap size)
(79 MB heap size)
(87 MB heap size)
(88 MB heap size)
(96 MB heap size)
(96 MB heap size)
(97 MB heap size)
(105 MB heap size)
(105 MB heap size)
(30 MB heap size)
(37 MB heap size)
(45 MB heap size)
(43 MB heap size)
(44 MB heap size)
(51 MB heap size)
(51 MB heap size)
(59 MB heap size)
(59 MB heap size)
(67 MB heap size)

Test Suites: 100 passed, 100 total
Tests:       1000 passed, 1000 total
Snapshots:   0 total
Time:        9.071 s, estimated 11 s

参考記事

メモリリークバグに関するIssue
[blogcard https://github.com/jestjs/jest/issues/11956]

@side/jest-runtimeが出来る元になったPR
[blogcard https://github.com/jestjs/jest/pull/12205]

ASUS TUF GAMING Z790-PLUS D4を導入した際に起きたトラブルの解消法メモ

インターネットに繋がらない

  1. デバイスマネージャーを開く
  2. 不明なデバイス(ネットワークアダプタ)を探す
  3. ASUSのドライバディスクを指定してドライバをインストールする

ASUSのインストールユーティリティを使っても上手く入らない

スリープ状態から勝手に復帰する

原因確認
  1. イベントビューワを開く
  2. Windowsログ>システムを開き、ソースがPower-Troubleshooterとなっているものを探す
  3. スリープ状態の解除元: デバイス -Intel(R) Ethernet Controller I226-Vとなっていたら解消法の内容で解消できる
    イベントビューワのPower-Troubleshooterのログでソースを確認する
解消法
  1. デバイスマネージャーを開く
  2. ネットワークアダプタ>Intel(R) Ethernet Controller I226-V
  3. このデバイスでコンピューターのスタンバイ状態を解除できるようにするのチェックを外す
    「このデバイスでコンピューターのスタンバイ状態を解除できるようにする」のチェックを外す

ネットワーク速度が極端に遅くなったり、接続が不安定になる

発生した症状

他の端末では起きないことは確認

  • fast.comのスコアで450Mbpsが20~200Mbpsまで低下
  • 回線速度が乱高下を繰り返し安定しない
  • 頻繁にネットワークが切断される
解消法
  1. デバイスマネージャーを開く
  2. ネットワークアダプタ>Intel(R) Ethernet Controller I226-V
  3. 速度とデュプレックス2.5Gbps 全二重通信に変更(既定値はオートネゴシエーション
  4. 省電力イーサーネットオフに変更(既定値はオン (システムが S0、S0ix、Sx 状態の場合)
    • 「省電力イーサーネット」を「オフ」に変更
  5. Windowsを再起動
  6. fast.comで速度が正常化していることを確認
参考情報

[blogcard https://www.null3-blog.com/entry/I226-V_fix]
[blogcard https://bbs.kakaku.com/bbs/K0001481981/SortID=25111393/#tab]

はてブ数
投稿日:
ゲーム::COM3D2ジャンル::エロゲ

image-1684671732672.png

Ver 1.471から2.29.4にアップデートしたときに起きたトラブルとその解消方法のメモ。ググってもまともに出てこなかったので久々にアプデする人の助けになれば。

メイドエディット画面で「無限色IDがありません。MATSUGE_UP」とエラーが出る

Ver 1.471から2.29.4にアップデートすることで解消。
ModLoaderを使っている場合、COM3D2.ModLoader_1.7.2にアップデートすると良いかも?

COM3D2.AddYotogiSliderが動かなくなる

  1. BepInEx 5.4.19をダウンロードし、COM3D2.exeがあるフォルダに展開する
  2. COM3D2.AddYotogiSliderSE2.Plugin.zipをダウンロードしBepinExフォルダごと上書きする

多分しばりすのやつはもう動きません。
次のようなエラーが出ている場合無理です。多分プラグインロード時にエラー吐いてて、上手くロードできてません。

  • YotogiStageSelectManager.SelectedStageRefDayTim
  • YotogiStageSelectManager.SelectedStage
はてブ数
投稿日:
言語::JavaScriptジャンル::調査

関数の仮引数の書き方でオブジェクトの参照がどう変わるか気になったので試したメモ。別に仮引数でなくても分割代入なら何でも結果は同じになると思う。

これはプロジェクトのコーディング規約に定めがなく、無秩序な状態になっていると不具合を引き起こす因子になると思うので、どの方法を取るのか決めたほうが品質に寄与すると考える。個人的には引数由来であることが明示的であり、必ず参照を引きずるオブジェクト代入方式(後述)が好みだ。

結果

分割代入した結果プリミティブになると元オブジェクトとの参照が切れる

仮引数方式 参照
分割代入
スプレッド代入
オブジェクト代入

分割代入した結果、オブジェクトのままだと元オブジェクトとの参照が残る(Shallow copy)
再代入は参照が切れるので影響しない(再代入で参照アドレスが変わるためと思われる)

仮引数方式 参照
オブジェクト再代入
オブジェクト書き換え

確認コード

// 分割代入
const foo = ({ id, name }) => {
  id = 2;
  name = 'aaaa';
  console.log(id, name);
};

// スプレッド代入
const bar = ({ ...props }) => {
  props.id = 2;
  props.name = 'aaaa';
  console.log(props.id, props.name);
};

// オブジェクト代入
const baz = (props) => {
  props.id = 2;
  props.name = 'aaaa';
  console.log(props.id, props.name);
};

// オブジェクト再代入
const hoge = ({ id, name, dat }) => {
  id = 2;
  name = 'aaaa';
  dat = {
    value: 3,
  };
  console.log(id, name, dat);
};

// オブジェクト書き換え
const piyo = ({ id, name, dat }) => {
  id = 2;
  name = 'aaaa';
  dat.value = 3;
  console.log(id, name, dat);
};


const test1 = { id: 1, name: 'test' };
const test2 = { id: 1, name: 'test' };
const test3 = { id: 1, name: 'test' };
const test4 = { id: 1, name: 'test', dat: { value: 1 } };
const test5 = { id: 1, name: 'test', dat: { value: 1 } };


foo(test1);
console.log(test1);

bar(test2);
console.log(test2);

baz(test3);
console.log(test3);

hoge(test4);
console.log(test4);

piyo(test5);
console.log(test5);

結果

// 分割代入では呼び出し元が影響を受けていない
2 'aaaa'
{id: 1, name: 'test'}

// スプレッド代入では呼び出し元が影響を受けていない
2 'aaaa'
{id: 1, name: 'test'}

// オブジェクト代入では呼び出し元が影響を受ける
2 'aaaa'
{id: 2, name: 'aaaa'}

// オブジェクト再代入では呼び出し元が影響を受けていない
2 'aaaa' {value: 3}
{id: 1, name: 'test', dat: { value: 1}}

// オブジェクト書き換えでは呼び出し元が影響を受ける
2 'aaaa' {value: 3}
{id: 1, name: 'test', dat: { value: 3}}

先日、StableDiffusionを快適に動かすためにグラボをRTX2060から4070Tiに更新しましたが、Core i7 13700F + RTX3060とレンダリング速度が変わらないということが解り、今回更に構成のアップデートすることにしました。

CPUの世代が古く、前々から構成をアップデートしたかったのもありエイヤで以下の内容を更新しました。メモリ代をケチるためにDDR4を維持できる構成にしてあるのがポイントです。

device before after
CPU Intel Core i9 9900 Intel Core i7 13700
M/B ASUS ROG STRIX Z390-F GAMING ASUS TUF GAMING Z790-PLUS D4

今回CPUソケットが変わり、CPUクーラーをどうするか悩んでいたのですがNoctuaが互換ブラケットを出していてくれたので助かりました。ハイエンド空冷は高いですからね…。

開封の儀

今回の品はCPUとマザボ、CPUクーラーの互換ブラケットです。

今回の品はCPUとマザボ、CPUクーラーの互換ブラケット

まずはマザボから。ROGからTUFにグレードダウンして何とも言えない気持ちですが、ROGもTUFもPRIMEも大差ない状態なので敢えて選ぶ必要がないので外しました。PRIMEでなく、TUFを選んだのはEthernet AdapterがIntel製だったからです。取り敢えずマザボ本体は以前使っていたROGと比べるとダサい感じになってしまったなと思うものの、マザボの見た目を気にしても仕方ないので考えないことに…。参考程度に箱で比較。

マザボの外箱
ROGと比べるとダサくなったなとか

箱を開けて付属品はこんな感じ。シール、取説、SATAコネクタx1、M2スペーサー x3、ドライバーディスクなどが入ってる感じです。取説を見るとM2ネジも入ってるらしいですが確認してません(後述の理由で必要になるケース少ないと思います)

どうでもいいんですがマザボのシール使う人いるんですかね?バッテリーシールはまだしも、バックパネル側面のシールとか貼るとデザイン性が劣化すると思うんですが…。

マザボの付属品、シール、取説、SATAコネクタx1、M2スペーサーx3、ドライバーディスクなど

CPU電源は今までに見たことがない12ピンでしたが8ピンで動きます。4ピンはおまけみたいなもん。K付きCPUとかOCする人は使うのかな?

マザボの取説

そういえばASUS ROG STRIX Z390-F GAMINGのM2SSDヒートシンクを剥がそうとしたらSSD側にサーマルパッドが固着して剥がれないという無惨な現象に遭遇しました。以前は綺麗に取れたのですが、今回のSSDは表のシール剥がしたからこうなってしまった気がします。多分SSDに貼ってあるシール剥がさないほうがいいですね…。(嗚呼…マザボの中古売却価格が無駄に下がってしまう…)

SSDに固着してしまったサーマルパッド
ヒートシンクのサーマルパッドが千切れてしまったので中古買取価格が下がってしまう…

気を取り直してCPUを開けていきます。13thは今時のフラットデザインという感じで、なかなか悪くないパッケージです。バーコードにある通りドスパラのなんば店で買ってきました。比較用に9thの箱もおいておきます。今見るとなんかダサい感じがしますね。

フラットデザインでカッコいい13thの箱
9thの箱、当時はカッコよかった気がするけど今見ると色褪せて見える気も…

CPU本体はLGA1700になってLGA1151より大きくなってます。多分今後も大きくなっていくんでしょうねこれ。

LGA1151と比べて縦に長くなったLGA1700

次はNoctua NH-U12AをLGA1700に対応させるための純正ブラケットです。取り敢えず必要最低限のパーツだけが入ってる感じ。無料でも入手できますが、レシートとか持ってないのと、オーストラリアからの発送は時間かかるだろうなというので諦めました。

但し実際にはサイズから数日で届くらしいです。

黒いのが好きなのでCHROMAXを買いました
純正ブラケットの中身

取り敢えずCPUソケットにCPUを入れましたが、なんか今回はレバーがきつかった気がします。

9thの時よりCPUカバーがなんか強そう

あとはNoctuaのグリスを塗ってあげて。

Nocutuaのグリス、容量あっていいですよね

気合でクーラーを装着します。これ左右どっちかにちょっとでも寄ってると上手くブラケットにリテンションキットがはまらないので中々苦労します。取り付けるとき素手でやってるからか微妙に錆びてる気もしますが気にしない方向で…。

CPUクーラーは気合で取り付ける

さて最後にM2SSDですが、ネジがいらないと書きましたがプラスチック製のラッチがついていて、これでM2SSDを固定できるようになっています。M2SSDのネジ止めは地味に面倒なのでこれは助かります。このラッチは取り外せるので、外せばネジ止めも恐らく出来ると思います。(ネジ穴自体はあるようにみえるので)

M2SSDの取り付けに便利なラッチがついている

ASUSマザーからASUSマザーへの更新だったのでユーティリティやその設定も使い回せて楽ができたのは良かったです。BIOSの設定を最低限変えるだけ(前のマザボと同じ設定にしただけ)で更新できたのでとても楽でした。

ひとまずこんだけあればあと三年は持つと思うので、しばらくは安泰そうです。前回のアップデートも3-4年くらい前でしたし、ぼちぼちなペースです。(前回はかなりアップデートが分散してたなぁ…とか思い返したり)

組み上げ後写真

光るパーツとしてはマザボくらいしかないのですが、そもそも前回写真取ってなかったなということで後で見返すために残しておきく。グラボがROGからZOTACになった影響で見栄えがイマイチ…。

新構成 - 前景
新構成 - 斜め上から
新構成 - マザボ拡大。右端のほうがほのかに光ってるのがわかる

参考程度に以前の構成(グラボ換装前)はこんな感じ。この時はマザボが光る箇所を撮影できてなかったのでアレ(CPUクーラーの死角になってしまっている)

旧構成 - 前景
旧構成 - 斜め上から
旧構成 - マザボ拡大

今回買ったもの

このマザーはM2SSDの取り付けが楽なのと、地味ですが一応ほのかに光ってくれるのでそこそこオススメです。

そして肝心のStableDiffusionの結果については、こっちの話に繋がります。

[blogcard url='colab-pro%e3%81%a8rtx4070ti%e3%81%a7stablediffusion%e3%82%92%e3%83%99%e3%83%b3%e3%83%81%e3%83%9e%e3%83%bc%e3%82%af%e3%81%97%e3%81%a6%e3%81%bf%e3%81%9f/']

トラブルシューティング

今のところネットワークアダプタ周りのトラブルが多い

[blogcard asus-tuf-gaming-z790-plus-d4%e3%83%88%e3%83%a9%e3%83%96%e3%83%ab%e3%82%b7%e3%83%a5%e3%83%bc%e3%83%86%e3%82%a3%e3%83%b3%e3%82%b0%e3%83%a1%e3%83%a2/]

おまけ

特に意味は無いですが、前にStableDiffusionで生成した美少女を供養がてら置いておきます。

前にStableDiffusionで生成した美少女