- 投稿日:
気がついたら今のブログが200投稿に達していたのでその思いを書いてみます。この記事は201記事目です。
まずこのブログというか、サイトの成り立ちから書いていこうと思います。当サイトは2002-07-03 23:21に開設された、まぁまぁ運営期間の長いサイトですが紆余曲折あり当時のコンテンツはカウンターの数値くらいしか残っていません。カウンターの数値だけはずっと継承しています。
コンテンツとしては雑記や日記がメインで、取り留めもない思ったことをつらつらと書いていますが、最近は情報技術関係の記事が多めです。かつてはMMORPGの記事が多かった時代もありました。
サイト全体の系譜図としてはこんな感じで、結構URL変更やホスティングサービスの移動、サイトの統廃合なども行っています。lycolia.info以前のURLは黒歴史なので書いていませんが記録はしています。
というわけで、なんやかんやあり2022-06-21に現在の場所に移転してきました。移転前の記事数は120記事だったということで、移転してから80記事書いたということになります。参考までにこの集計は次のクエリで行いました。
SELECT
COUNT(*)
FROM
wp_posts
WHERE
post_date < '2022-06-21'
AND post_status = 'publish'
AND post_type = 'post';
移転してきたばかりの頃は検索エンジンにインデックスされずアクセスが低迷していましたが、二年ほど経った今はだいぶ安定してきました。移転前ははてなブログを使っており、その前はWordPressを使っていて、今もWordPressなので、WordPress→はてなブログ→WordPressという感じで移転してきているのですが、ドメインの変更やURL構造の破壊的変更、リダイレクトが効かないなど様々な障害があり、サイト移転に完全に失敗しています。また、はてなブログに移転するときや、はてなブログからの移転で記事の移行が上手く行かず、結構な数な記事をロストしています。
はてなブログに移転した理由はMarkdownで執筆できるモダンな環境で、結構流行っていたからというところがあるのですが、実際に使ってみるとエディタは使いづらく、記事のタグも自分のサイト内だけを検索できる機能ではなく、何よりSEOが非常に悪く、まともに検索に引っかからないという、なんのためにやってるのかよくわからない状態だったのもあります。
あとはカスタマイズ機能がCSSとJSで魔改造する前提で、まともなセマンティクスやアクセシビリティの提供が極めて困難だったので、これがはてなブログを離れた理由でもあります。因みにはてなブログ時代はPVが多くて5/daysくらいという、サイトの歴史全体を通してみても致命的にアクセスがなかった時代でした。正直Pro契約で安くない料金を払っているのにこれはないなというので引き払いを決意し、WordPress向けのMarkdown執筆環境の構築に腐心し、今はWordPress上にそれなりの環境を作れています。
取り敢えずはてなブログから移転してきて80記事くらい書いたところでMAX 5PV/daysがAvrage 50PV/daysになったのは大分良くなったなという感じでした。はてなブログに行く前は1000PV位ありましたが、ラグマスブームの頃にヒット記事を書いてた影響なので過去を見ても仕方がないです。
過去のサイトも含めて書いてきた記事数は不明ですが、多分累計で4桁は書いてるんじゃないかなとは思います。特にROやってた時はクソほど書いてたので。最近はMMOも廃れそこまで日々熱意を持って取り組めることもないので、その時ほどは難しいですが、これからもぼちぼち書いていければなと思っています。技術記事以外の雑記とか、その辺りも増やして行って、SNSから離れて古くゆかしきインターネットに帰っていきたい思いもあります。
しかしまぁ、昔と違って常連さん的なのを作るのは難しいだろうなぁ…wなにせ特定の事柄を書かなくなってしまったのもあり、定期購読する価値が薄いサイトになってしまったというところが割とある気はしていますので…w
- 投稿日:
確認環境
Env | Ver |
---|---|
OS | Ubuntu 20.04.4 LTS |
PHP | 8.0.29 |
nginx | 1.18.0 |
手順
php-fpmの導入
sudo apt install php8.0-fpm
sudo sed -i -e 's/;listen.mode = 0660/listen.mode = 0666/' /etc/php/8.0/fpm/pool.d/www.conf
sudo service php8.0-fpm start
nginxの設定
設定ファイルを開きPHPを動かす設定を書く
location ~ ^/.*$ {
root /path/to/www;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
- 投稿日:
undefinedの判定方法が複数あるということでundefined判定の処理速度比較をしてみたのでその結果。
端的に言うと、hoge === undefined
とtypeof hoge === 'undefined'
の二方式がある。後者は原則考慮不要だが、言語仕様上存在しているので比較したが、現実的に見た場合、どちらで記述した場合でも処理速度に有意な差はないように感じた。
確認環境
Env | Ver |
---|---|
Node.js | 20.1.0 |
TypeScript | 4.9.5 |
@swc/core | 1.3.8 |
比較結果
hoge === undefined
の方が早く見えるが実行するタイミングで変わるので誤差の範疇だと思う。
方式 | ms |
---|---|
hoge === undefined |
4,514 |
typeof hoge === 'undefined' |
4,515 |
確認コード
const tyof = (param?: string) => {
return typeof param === 'undefined';
};
const undef = (param?: string) => {
return param === undefined;
};
const tyStart = +new Date();
for (let i = 0; i < 10000000000; i++) {
tyof();
}
console.log('typeof', +new Date() - tyStart);
const unStart = +new Date();
for (let i = 0; i < 10000000000; i++) {
undef();
}
console.log('undefined', +new Date() - unStart);
TSから生成されたJS
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const tyof = (param)=>{
return typeof param === 'undefined';
};
const undef = (param)=>{
return param === undefined;
};
const tyStart = +new Date();
for(let i = 0; i < 10000000000; i++){
tyof();
}
console.log('typeof', +new Date() - tyStart);
const unStart = +new Date();
for(let i = 0; i < 10000000000; i++){
undef();
}
console.log('undefined', +new Date() - unStart);
あとがき
MDNを読む限りtypeof hoge === 'undefined'
は該当変数が存在しない場合に有用なようであるが、TypeScriptで書いている場合、通常このようなコードが生まれることがなく、仮に起きるとした場合、次のようなコードになるため現実的に考慮する必要はない。なおMDNにも「こんなことはしないこと」と書いてあるので、一般的なコードでないことは客観的にも伺えるだろう。
(() => {
const undefined = 123;
const hoge = undefined;
if (typeof hoge === 'undefined') {
console.log('hoge is undefined');
} else {
console.log('hoge is not undefined');
}
})();
上記コードの実行結果としてはhoge is not undefined
が出力される。
このコードの主な問題点
const undefined = 123;
というコードは予約語を変数名にしているため、混乱を招くコードであり、書かないことが好ましい- MDNには予約語ではないとあるが、一般的には予約語の一つとして解釈して支障ないと考える
- このコードはESLintのeslint:recommendedで検知されるため、通常であれば書かれることはない
なお、このコードは例示のために即時実行関数形式で記述しているが、必要がない限りこの形式での実装は避けたほうが問題が少なくなると思う。これは不必要なネストが生まれたり、スコープの混乱を生むためである。
- 投稿日:
- 投稿日:
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
https://github.com/jestjs/jest/issues/11956
@side/jest-runtimeが出来る元になったPR
https://github.com/jestjs/jest/pull/12205