[{"metadata":{"id":"sakura-moyu","lang":"zh-CN","title":"推完了 さくら、もゆ","tags":["游戏屋"],"publish_time":"2026-05-31T23:55:58+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"推","components":[["M 311 -839L 137 -855L 137 -91C 137 -80 132 -74 118 -74C 96 -74 2 -80 2 -80L 2 -66C 50 -56 70 -41 85 -17C 100 7 105 42 108 92C 255 77 274 22 274 -76L 274 -810C 299 -814 309 -824 311 -839Z",[0.035,0.831]],["M 18 -376L 82 -222C 94 -226 104 -239 107 -253C 235 -351 324 -434 376 -486L 373 -495C 229 -442 76 -392 18 -376Z",[0.549,0.33]],["M 321 -698L 269 -615L 24 -615L 32 -587L 386 -587C 399 -587 409 -592 412 -603C 380 -640 321 -698 321 -698Z",[0.83,0.084]],["M 658 -803L 472 -855C 455 -719 404 -508 325 -367L 334 -359C 475 -470 570 -648 622 -781C 647 -783 655 -792 658 -803Z",[0.297,0.664]],["M 550 56L 550 -643L 564 -643L 477 -675L 417 -567L 417 94L 442 94C 510 94 550 65 550 56Z",[0.009,0.818]],["M 860 -733L 795 -643L 479 -643L 479 -615L 950 -615C 964 -615 975 -620 978 -631C 935 -672 860 -733 860 -733Z",[0.702,0.098]],["M 870 -112L 802 -18L 486 -18L 486 10L 964 10C 978 10 989 5 992 -6C 947 -49 870 -112 870 -112Z",[0.823,0.071]],["M 838 -319L 777 -231L 490 -231L 490 -203L 919 -203C 934 -203 944 -208 947 -219C 907 -259 838 -319 838 -319Z",[0.813,0.075]],["M 838 -527L 777 -439L 490 -439L 490 -411L 919 -411C 934 -411 944 -416 947 -427C 907 -467 838 -527 838 -527Z",[0.796,0.076]],["M 627 -860L 619 -856C 643 -810 659 -746 654 -686C 766 -577 920 -796 627 -860Z",[0.013,0.357]],["M 775 -643L 647 -643L 647 4L 775 4Z",[0.006,0.792]]],"bbox":{"top":-860,"bottom":94,"left":2,"right":992},"hadv":1000}],"text":"推","hadv":1000,"breakAfter":true},{"chars":[{"char":"完","components":[["M 445 -344L 289 -344C 284 -178 270 -34 23 83L 30 95C 395 20 430 -138 445 -344Z",[0.373,0.567]],["M 171 -743L 160 -743C 161 -700 116 -659 85 -643C 43 -624 14 -587 28 -537C 44 -484 110 -466 148 -491C 202 -525 226 -617 171 -743Z",[0.178,0.341]],["M 827 -437L 758 -350L 64 -350L 72 -322L 925 -322C 939 -322 950 -327 953 -338C 906 -378 827 -437 827 -437Z",[0.901,0.038]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 658 -596L 591 -512L 219 -512L 227 -484L 753 -484C 767 -484 778 -489 781 -500C 734 -540 658 -596 658 -596Z",[0.764,0.073]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 675 -345L 531 -345L 531 -48C 531 45 555 69 669 69L 763 69C 931 69 978 41 978 -16C 978 -43 970 -60 933 -75L 930 -207L 921 -207C 896 -144 879 -99 866 -81C 858 -70 852 -67 839 -66C 826 -66 803 -65 781 -65L 704 -65C 680 -65 675 -70 675 -84L 675 -309C 675 -318 675 -334 675 -345Z",[-0.31,0.237]],["M 780 -680L 791 -680C 788 -639 779 -569 769 -524L 776 -518C 829 -543 897 -588 937 -622C 958 -623 968 -626 976 -635L 852 -752Z",[0.117,0.149]]],"bbox":{"top":-871,"bottom":95,"left":14,"right":978},"hadv":1000}],"text":"完","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"さ","components":[["M 339 -466C 421 -467 528 -495 599 -522C 679 -552 764 -595 797 -629C 818 -650 819 -684 800 -704C 781 -725 746 -729 719 -728C 697 -728 661 -671 539 -624C 465 -595 369 -573 313 -572C 248 -571 203 -580 136 -637L 123 -628C 163 -512 195 -463 339 -466Z",[0.772,0.175]],["M 513 55C 673 55 728 24 728 -22C 728 -76 678 -94 627 -94C 585 -94 539 -82 472 -82C 340 -82 283 -126 283 -183C 283 -254 344 -306 445 -306C 560 -306 632 -260 679 -227C 714 -203 736 -181 771 -181C 817 -181 836 -246 836 -286C 836 -312 827 -329 804 -352C 752 -403 668 -471 614 -570C 587 -620 569 -651 544 -749C 537 -776 492 -798 424 -798C 374 -798 331 -771 301 -747L 304 -734C 362 -727 407 -714 424 -688C 446 -653 487 -582 515 -539C 560 -471 627 -389 663 -350C 674 -339 671 -336 658 -338C 623 -344 555 -356 473 -356C 306 -356 185 -264 185 -149C 185 -25 313 55 513 55Z",[0.045,0.344]]],"bbox":{"top":-798,"bottom":55,"left":123,"right":836},"hadv":1000}],"text":"さ","hadv":1000,"breakAfter":true},{"chars":[{"char":"く","components":[["M 617 77C 683 77 703 30 703 -5C 703 -42 695 -71 657 -119C 590 -203 465 -269 373 -329C 353 -342 336 -356 336 -371C 336 -384 347 -398 372 -422C 415 -464 526 -546 602 -595C 650 -626 688 -634 688 -671C 688 -712 636 -779 567 -812C 540 -825 506 -829 471 -830L 463 -817C 485 -792 512 -763 512 -739C 512 -724 506 -712 492 -693C 457 -645 315 -491 260 -424C 237 -395 229 -376 229 -354C 229 -336 240 -310 264 -290C 379 -191 460 -111 495 -53C 521 -9 533 13 546 36C 560 58 585 77 617 77Z",[-0.029,0.555]]],"bbox":{"top":-830,"bottom":77,"left":229,"right":703},"hadv":1000}],"text":"く","hadv":1000,"breakAfter":true},{"chars":[{"char":"ら","components":[["M 328 36L 330 55C 592 82 892 -1 892 -203C 892 -314 808 -430 642 -430C 489 -430 362 -332 313 -310C 305 -306 301 -308 300 -319C 298 -339 308 -374 310 -410C 312 -441 313 -459 310 -490C 307 -523 290 -546 290 -564C 290 -571 294 -580 313 -582C 338 -585 401 -588 444 -582C 489 -576 521 -562 559 -562C 598 -562 613 -582 613 -611C 613 -682 572 -732 507 -766C 464 -790 397 -802 294 -787L 292 -775C 353 -753 397 -736 423 -691C 429 -681 428 -673 418 -666C 388 -646 296 -622 257 -617C 220 -613 208 -574 208 -545C 208 -517 207 -505 206 -483C 203 -437 188 -332 181 -292C 173 -246 166 -224 166 -203C 166 -175 175 -154 196 -131C 218 -106 241 -92 264 -92C 305 -92 318 -138 349 -181C 395 -244 515 -384 627 -384C 713 -384 748 -314 748 -253C 748 -167 702 -87 536 -18C 490 1 410 23 328 36Z",[-0.147,0.203]]],"bbox":{"top":-802,"bottom":82,"left":166,"right":892},"hadv":1000}],"text":"ら","hadv":1000,"breakAfter":false},{"chars":[{"char":"、","components":[["M 239 82C 286 82 316 50 316 5C 316 -16 313 -38 297 -62C 258 -122 179 -166 37 -182L 30 -171C 120 -95 141 -15 166 36C 182 69 206 82 239 82Z",[-0.356,0.393]]],"bbox":{"top":-182,"bottom":82,"left":30,"right":316},"hadv":1000}],"text":"、","hadv":1000,"breakAfter":true},{"chars":[{"char":"も","components":[["M 493 -206C 537 -213 566 -236 566 -271C 566 -313 541 -332 497 -334C 463 -336 408 -333 350 -338C 283 -344 219 -363 219 -400C 219 -441 301 -481 368 -480C 414 -479 463 -471 506 -475C 538 -478 560 -487 560 -522C 560 -553 539 -588 476 -595C 419 -601 350 -596 273 -620C 226 -635 198 -663 176 -694L 166 -689C 172 -613 192 -584 219 -560C 239 -542 258 -533 280 -525C 216 -486 171 -430 171 -372C 171 -308 228 -245 331 -216C 381 -202 447 -199 493 -206Z",[-0.084,0.247]],["M 551 73C 770 73 849 -63 849 -171C 849 -300 750 -407 577 -465L 568 -453C 651 -388 711 -319 711 -205C 711 -101 624 -33 522 -33C 430 -33 379 -73 379 -161C 379 -275 437 -428 474 -521C 500 -587 521 -621 539 -650C 551 -669 570 -685 570 -711C 570 -750 492 -819 421 -819C 386 -819 363 -812 342 -803L 341 -791C 356 -785 370 -777 381 -769C 397 -757 410 -744 410 -722C 410 -698 396 -642 371 -540C 347 -443 312 -240 312 -148C 312 -21 383 73 551 73Z",[-0.129,0.439]]],"bbox":{"top":-819,"bottom":73,"left":166,"right":849},"hadv":1000}],"text":"も","hadv":1000,"breakAfter":true},{"chars":[{"char":"ゆ","components":[["M 286 62L 291 76C 476 32 554 -18 612 -121C 657 -201 676 -298 676 -436C 676 -702 594 -785 509 -785C 475 -785 433 -767 400 -710C 365 -650 338 -573 338 -395C 338 -202 451 -68 608 -68C 801 -68 938 -174 938 -370C 938 -558 801 -646 669 -646C 574 -646 474 -617 420 -579C 296 -492 228 -402 168 -287C 156 -294 149 -323 149 -348C 149 -408 184 -471 206 -503C 228 -540 250 -555 249 -593C 250 -624 221 -668 189 -695C 167 -713 131 -731 85 -741L 77 -733C 92 -708 118 -665 118 -616C 118 -542 70 -436 70 -329C 70 -236 93 -159 122 -123C 148 -91 171 -77 201 -77C 240 -77 257 -98 257 -131C 257 -183 241 -200 241 -251C 241 -311 300 -431 390 -504C 470 -569 553 -596 640 -596C 733 -596 821 -552 821 -404C 821 -229 714 -200 605 -200C 489 -200 396 -268 396 -475C 396 -552 400 -622 426 -682C 443 -721 466 -742 490 -742C 532 -742 557 -688 557 -436C 557 -178 509 -51 286 62Z",[-0.167,0.026]]],"bbox":{"top":-785,"bottom":76,"left":70,"right":938},"hadv":1000}],"text":"ゆ","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<style>\n.spoiler {\n  background: var(--color-fg);\n}\n.post img.sticker {\n  max-width: 150px;\n  display: block;\n  margin: auto;\n}\n</style>\n<p>皆さん、我要开骂了。</p>\n<img src=\"https://layered-assets.thu.fail/2026-05-31-fufu-mi.webp\" class=\"sticker\">\n<p>很少 feeling the spite enough that 我需要写一点东西专门说一个黄油或者一本厕纸看下来有多不爽：the opposite of love is indifference。事实上，两个月没写博客的原因是因为正在加 i18n 改了很多代码，结果樱摸鱼甚至让我突破了懒惰和 breaking the website 的恐惧，打出了 <code>git stash</code> 专门来写这篇博客，这也是它给我的“勇气”吧（笑）。</p>\n<p>不得不说我可能是对它的期待太高了。基本上所有的黄油我都是因为 osu! 先听歌才去推的，樱摸鱼也不例外，OST 的水平极高，七年前第一次听到以来，我最喜欢的曲子一直是 OP1，这几首主题曲都给人一种热烈的告白的感觉，羞涩地，带一点点寂寞的，但又充满着勇气和热情。老登的生活就缺点这个，很高兴能在几位主角的故事中（尤其是 TE 中）感到类似的温柔的情绪。</p>\n<p>CV 的演出是很神的，我一直都是夏和小的俘虏啊.jpg，十夜的演出也把她的可爱毫无保留地展示给了读者。不得不说，人设和部分角色塑造还是很到点的。这一部分很遗憾，可能只能真的去推了才能感受到了。</p>\n<p>到目前为止好上加好，怎么看都应该是我很喜欢的黄油，也是<a href=\"/post/wait-for-process-ex\">期待了很久</a>，那么为啥推到后面都到了难以下咽，甚至恶心的地步了呢？</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/2026-05-31-drug.png\">\n</figure>\n<p>剧情和写作出了无法忽视的大问题。</p>\n<h2>剧情和雪人语</h2>\n<p>对本作写作最常见的批评是雪人语，反复、冗长的表述，别扭的对白设计，让人昏昏欲睡。我感觉这个可能是电波问题，我可以接受缓慢、轻柔、慢慢传达情绪的叙事，但是如果读到最后发现传达过来的全都是刺耳噪声，那整个阅读体验就变成一种💩里淘金的感觉了。所以本质我最讨厌的，还是剧情。</p>\n<p>这个剧情里面，很多桥段的各个方面都<strong>太过轻浮</strong>了。</p>\n<p>剧情里有很多前后不一致的问题，不合逻辑，人物莫名其妙就会遇到作者抛来的全新的困难。这不是说我就喜欢小甜水剧情，我都是三秋缒的sb脑残粉了。随随便便就给人物无法翻越的困难，是一种廉价消费人物和读者情绪的行为，消解了叙事中人物能动性的意义，以及人物成长的内涵和价值，带有一种强烈的“人工”感。比如说，短短几行内就随便让人物面对需要付出生命代价才能跨越的困难，角色没有时间挣扎，没有时间准备，也没有时间成长。只能靠哀嚎（苦了 CV 了），让我有一种尝试挤出读者眼泪的感觉。</p>\n<p>然后呢？然后要不莫名其妙这个人物就硬起来了，要不就是靠一些全新的外部神力，就把它克服了。说世界观庞大，很多时候给我一种雪人写爽了现场想出来的新活的感觉。没有铺垫，后续没有呼应，虽无矛盾，但就是给人一种 Deus ex machina 的感觉。我相信可能很多时候众多设定都是提前想好的，但是一个设定只用一次，具体执行下来就让读者觉得很无趣——明显是为了追求一种诡计性叙事，但是至少在我这里达成了反效果。</p>\n<p>情感线有的时候也是这样：忽然就喜欢上了，没有理由，即使玩家刚刚推过其他三条线。最搞笑的是，紧接着表白就要设置 HS，C 的时候都要绷不住了。这个游戏的几个 HS 设置有如 Jump scare，无法预测的命运之舞台.mp4。</p>\n<p>虽然这么喷了，但是不得不说，这个故事中也是有很多亮点的，毕竟是💩里淘金，如果一点金子都没有，我也不会被骗进来坐牢 30h。有些秘密的揭晓是 Genuinely surprising and moving 的。小春线 &amp; TE 的主要剧情脉络还是一脉相承，作为本作故事和设定的主要线索（你这不是能做到吗），看着它展开还是能给人带来不少满足感。客观上来说，这应该是本作质量最高的两条线。</p>\n<p>但是我推 TE 的时候甚至有点恶心，它是我主观上体验最差的一条线，因为我实在无法接受这条线讲的这个故事，和它想表达的东西。我不带保留地爱这个故事的结局，但是我也不带保留地恨写这个故事的人展示出的恶意。</p>\n<h2>轮回</h2>\n<p><strong>接下来有一些剧透</strong>。</p>\n<hr />\n<p>TE 的 OP2 是《輪廻》，我推 TE 也有种身处轮回中的感觉。</p>\n<p>我看到，仿佛同样一个故事，在几个角色身上，反复展开。我又看到同一个故事，苦难，在同一个角色身上，反复显现。在充斥着“人工感”的情节中，透过雪人反反复复的念白，我看到角色们因为同样的东西而永恒地挣扎着。而雪人表达角色痛苦的方法，只有让其哭诉呻吟。</p>\n<p>It grows old real quick.</p>\n<p>在面临苦难时，角色意外地获得了力量，克服了困难，然后呢？在下一幕中，他又变回了之前那个因为相同的苦恼而痛苦着的人，反复着没有什么变化的呻吟。剧情上，经历了或许幸福或许孤独的一生，在重生的时候，他应该是一个久经风霜，能够平淡面临一切的灵魂了，但没有，他要继续哭诉同样的苦恼，犯下同样的错误。因为这些困难，这些经历，都是被作者轻浮的加到角色身上的，自然角色也毫无成长。</p>\n<p>到了 TE 的中段，我甚至要关闭角色语音，因为我实在听不下去这一次又一次仿佛没有变化的煎熬。从某种角度上，这是我见过表现抑郁性精神疾病最准确的作品。也正巧，这些角色们面临的苦难，正好是内心中“我不应获得幸福”的自卑。可能也是因为这，让我更无法去听这些哭号。</p>\n<p>当然你可以说设定这是合理的：“夜”里的灵魂们要直面自己的“噩梦”。That’s fair，但是我显然不在“夜”里，所以在我看来，这是一种廉价的写作，尝试将一团混淆不清的情绪，其中甚至有互相冲突的部分，在不直面它的情况下，一股脑不负责任地丢给读者。</p>\n<p>如果雪人自己也或多或少处于一个这样的“轮回”中，那么我无比的同情他，但是我个人无法接受这样的故事，也无法接受能够享受这样故事的心态。它实在是太混沌了，让人无法区分真正的感动和希望，还是自我安慰以及自怨自艾。</p>\n<p>在这团混沌中，最明亮的一点光，是小黑在 TE 线中直面自己“噩梦”的那段情节。即使<span class=\"spoiler\">雪人毫不手软就把她杀了</span>，这也是我在整个 TE 线中，看到的最坚定的勇气，也十分符合小黑的角色。可能雪人自己也不相信不靠奇迹自己战胜“噩梦”的可能性，但是无论如何，这是明确让我把小黑当成本作我最喜欢的角色的契机。</p>\n<h2>“愿你的身边永远有魔法相伴”</h2>\n<p>那么雪人为角色们最终想象的出路是什么呢？他想告诉读者什么呢？</p>\n<p>人们的身边永远有自己看不见的魔法陪伴着，保护着。这让人能度过一个又一个不眠之夜，能够活下去的勇气。</p>\n<p>更进一步地，每个人的克服苦难的故事，都能成为他人的力量和慰藉。这给人以意义。</p>\n<p>这些是好的，我很喜欢这种想法，这是一个很温柔的作品。但是很遗憾，我无法从角色本身的心态变化相信这些，所以给我的感觉是，这也是雪人想表达的那一团混淆不清的情绪中的几个线头——可能是稍微比较粗的那几条就是了。我甚至都在怀疑，雪人他自己真的相信这些吗？依靠一个角色们反复牺牲自己的故事，尝试传达“人人都可以获得幸福”这个想法，实在是有点勉强。</p>\n<img src=\"https://layered-assets.thu.fail/2026-05-31-ball.webp\" class=\"sticker\">\n<p>更何况，相信“魔法”的存在确实是困难的，而通过“他人”赋予的意义，可能也是不稳定的。与自己的情绪和解的方式，本作在共通线中有所讨论，但是到了后面却仿佛忘记一般，但这才是我觉得最重要的地方。</p>\n<p>虽说如此，我还是很希望有需要的人们能够读到樱摸鱼中的这些想法，能够或多或少相信他们，因为这些温柔可以成为当下最重要的力量，而想法可以延伸，分享，传递。至少从这个角度，我希望樱摸鱼能够做到“成为他人力量和慰藉”这件事。</p>\n<p>不过，我可能最喜欢的是第三个本作想说的事情，那就是在每个故事中，都有穿越时间，与重要之人相遇的未来，即使在轮回之后，依旧能够重逢，这样的故事，我觉得这是本作剧情中执行得最好的一部分。当然，可能是因为我一直就是很喜欢这样的故事吧。</p>\n<h2>Final thoughts</h2>\n<p>好像我和很多其他推过樱摸鱼的网友们对于本作的观点大不相同。很多人最终看到了这个温柔的故事的结尾，和雪人语和解了，我则是一开始就能接受雪人语，但是非常讨厌这个故事本身。自负一点想，这也是一种长大了所以看不见“夜”吗（笑），不过都说樱摸鱼是“大人的童话”，所以估计也不是，但我却觉得这不算给大人的童话，至少不算给我的，虽然我只能算个不大不小的中猫。可能是我的认知太僵硬了吧。</p>\n<p>无论如何，在几个月，几年之后，我估计还是会很喜欢 OST 里面的歌，听到它，我想起的会是未来和重要之人相遇的故事，给人的心情就像飘落的樱花的淡淡香气。而上面写的这些讨厌的情绪，可能早已淡忘掉了吧。到那个时候，再写一篇博客吧<sup>[1]</sup>！</p>\n<hr />\n<div class=\"footnotes\">\n<ol>\n<li>\n<p>真的要和雪人语和解了吗（笑）</p>\n</li>\n<li>\n<p>在写本文的过程中群友发了个这个，震惊：<a href=\"https://www.bilibili.com/video/BV1WzG76XEPo/\">FAVORITE社游戏可以直接从bios(UEFI)启动了_哔哩哔哩_bilibili</a></p>\n</li>\n<li>\n<p>一开始写的时候开了 Copilot，打了一个词之后把我乐死了。然后我把第一句话打完他就不补全了，看来是彻底不会了。</p>\n</li>\n</ol>\n  <details>\n    <summary>图</summary>\n    <img src=\"https://layered-assets.thu.fail/2026-05-31-completion.png\">\n  </details>\n</div>","plain":"皆さん、我要开骂了。\n很少 feeling the spite enough that 我需要写一点东西专门说一个黄油或者一本厕纸看下来有多不爽：the opposite of love is indifference。事实上，两个月没写博客的原因是因为正在加 i18n 改了很多代码，结果樱摸鱼甚至让我突破了懒惰和 breaking the website 的恐惧，打出了 git stash 专门来写这篇博客，这也是它给我的“勇气”吧（笑）。\n不得不说我可能是对它的期待太高了。基本上所有的黄油我都是因为 osu! 先听歌才去推的，樱摸鱼也不例外，OST 的水平极高，七年前第一次听到以来，我最喜欢的曲子一直是 OP1，这几首主题曲都给人一种热烈的告白的感觉，羞涩地，带一点点寂寞的，但又充满着勇气和热情。老登的生活就缺点这个，很高兴能在几位主角的故事中（尤其是 TE 中）感到类似的温柔的情绪。\nCV 的演出是很神的，我一直都是夏和小的俘虏啊.jpg，十夜的演出也把她的可爱毫无保留地展示给了读者。不得不说，人设和部分角色塑造还是很到点的。这一部分很遗憾，可能只能真的去推了才能感受到了。\n到目前为止好上加好，怎么看都应该是我很喜欢的黄油，也是期待了很久，那么为啥推到后面都到了难以下咽，甚至恶心的地步了呢？\n剧情和写作出了无法忽视的大问题。\n\n剧情和雪人语\n对本作写作最常见的批评是雪人语，反复、冗长的表述，别扭的对白设计，让人昏昏欲睡。我感觉这个可能是电波问题，我可以接受缓慢、轻柔、慢慢传达情绪的叙事，但是如果读到最后发现传达过来的全都是刺耳噪声，那整个阅读体验就变成一种💩里淘金的感觉了。所以本质我最讨厌的，还是剧情。\n这个剧情里面，很多桥段的各个方面都太过轻浮了。\n剧情里有很多前后不一致的问题，不合逻辑，人物莫名其妙就会遇到作者抛来的全新的困难。这不是说我就喜欢小甜水剧情，我都是三秋缒的sb脑残粉了。随随便便就给人物无法翻越的困难，是一种廉价消费人物和读者情绪的行为，消解了叙事中人物能动性的意义，以及人物成长的内涵和价值，带有一种强烈的“人工”感。比如说，短短几行内就随便让人物面对需要付出生命代价才能跨越的困难，角色没有时间挣扎，没有时间准备，也没有时间成长。只能靠哀嚎（苦了 CV 了），让我有一种尝试挤出读者眼泪的感觉。\n然后呢？然后要不莫名其妙这个人物就硬起来了，要不就是靠一些全新的外部神力，就把它克服了。说世界观庞大，很多时候给我一种雪人写爽了现场想出来的新活的感觉。没有铺垫，后续没有呼应，虽无矛盾，但就是给人一种 Deus ex machina 的感觉。我相信可能很多时候众多设定都是提前想好的，但是一个设定只用一次，具体执行下来就让读者觉得很无趣——明显是为了追求一种诡计性叙事，但是至少在我这里达成了反效果。\n情感线有的时候也是这样：忽然就喜欢上了，没有理由，即使玩家刚刚推过其他三条线。最搞笑的是，紧接着表白就要设置 HS，C 的时候都要绷不住了。这个游戏的几个 HS 设置有如 Jump scare，无法预测的命运之舞台.mp4。\n虽然这么喷了，但是不得不说，这个故事中也是有很多亮点的，毕竟是💩里淘金，如果一点金子都没有，我也不会被骗进来坐牢 30h。有些秘密的揭晓是 Genuinely surprising and moving 的。小春线 & TE 的主要剧情脉络还是一脉相承，作为本作故事和设定的主要线索（你这不是能做到吗），看着它展开还是能给人带来不少满足感。客观上来说，这应该是本作质量最高的两条线。\n但是我推 TE 的时候甚至有点恶心，它是我主观上体验最差的一条线，因为我实在无法接受这条线讲的这个故事，和它想表达的东西。我不带保留地爱这个故事的结局，但是我也不带保留地恨写这个故事的人展示出的恶意。\n\n轮回\n接下来有一些剧透。\n---\nTE 的 OP2 是《輪廻》，我推 TE 也有种身处轮回中的感觉。\n我看到，仿佛同样一个故事，在几个角色身上，反复展开。我又看到同一个故事，苦难，在同一个角色身上，反复显现。在充斥着“人工感”的情节中，透过雪人反反复复的念白，我看到角色们因为同样的东西而永恒地挣扎着。而雪人表达角色痛苦的方法，只有让其哭诉呻吟。\nIt grows old real quick.\n在面临苦难时，角色意外地获得了力量，克服了困难，然后呢？在下一幕中，他又变回了之前那个因为相同的苦恼而痛苦着的人，反复着没有什么变化的呻吟。剧情上，经历了或许幸福或许孤独的一生，在重生的时候，他应该是一个久经风霜，能够平淡面临一切的灵魂了，但没有，他要继续哭诉同样的苦恼，犯下同样的错误。因为这些困难，这些经历，都是被作者轻浮的加到角色身上的，自然角色也毫无成长。\n到了 TE 的中段，我甚至要关闭角色语音，因为我实在听不下去这一次又一次仿佛没有变化的煎熬。从某种角度上，这是我见过表现抑郁性精神疾病最准确的作品。也正巧，这些角色们面临的苦难，正好是内心中“我不应获得幸福”的自卑。可能也是因为这，让我更无法去听这些哭号。\n当然你可以说设定这是合理的：“夜”里的灵魂们要直面自己的“噩梦”。That’s fair，但是我显然不在“夜”里，所以在我看来，这是一种廉价的写作，尝试将一团混淆不清的情绪，其中甚至有互相冲突的部分，在不直面它的情况下，一股脑不负责任地丢给读者。\n如果雪人自己也或多或少处于一个这样的“轮回”中，那么我无比的同情他，但是我个人无法接受这样的故事，也无法接受能够享受这样故事的心态。它实在是太混沌了，让人无法区分真正的感动和希望，还是自我安慰以及自怨自艾。\n在这团混沌中，最明亮的一点光，是小黑在 TE 线中直面自己“噩梦”的那段情节。即使雪人毫不手软就把她杀了，这也是我在整个 TE 线中，看到的最坚定的勇气，也十分符合小黑的角色。可能雪人自己也不相信不靠奇迹自己战胜“噩梦”的可能性，但是无论如何，这是明确让我把小黑当成本作我最喜欢的角色的契机。\n\n“愿你的身边永远有魔法相伴”\n那么雪人为角色们最终想象的出路是什么呢？他想告诉读者什么呢？\n人们的身边永远有自己看不见的魔法陪伴着，保护着。这让人能度过一个又一个不眠之夜，能够活下去的勇气。\n更进一步地，每个人的克服苦难的故事，都能成为他人的力量和慰藉。这给人以意义。\n这些是好的，我很喜欢这种想法，这是一个很温柔的作品。但是很遗憾，我无法从角色本身的心态变化相信这些，所以给我的感觉是，这也是雪人想表达的那一团混淆不清的情绪中的几个线头——可能是稍微比较粗的那几条就是了。我甚至都在怀疑，雪人他自己真的相信这些吗？依靠一个角色们反复牺牲自己的故事，尝试传达“人人都可以获得幸福”这个想法，实在是有点勉强。\n更何况，相信“魔法”的存在确实是困难的，而通过“他人”赋予的意义，可能也是不稳定的。与自己的情绪和解的方式，本作在共通线中有所讨论，但是到了后面却仿佛忘记一般，但这才是我觉得最重要的地方。\n虽说如此，我还是很希望有需要的人们能够读到樱摸鱼中的这些想法，能够或多或少相信他们，因为这些温柔可以成为当下最重要的力量，而想法可以延伸，分享，传递。至少从这个角度，我希望樱摸鱼能够做到“成为他人力量和慰藉”这件事。\n不过，我可能最喜欢的是第三个本作想说的事情，那就是在每个故事中，都有穿越时间，与重要之人相遇的未来，即使在轮回之后，依旧能够重逢，这样的故事，我觉得这是本作剧情中执行得最好的一部分。当然，可能是因为我一直就是很喜欢这样的故事吧。\n\nFinal thoughts\n好像我和很多其他推过樱摸鱼的网友们对于本作的观点大不相同。很多人最终看到了这个温柔的故事的结尾，和雪人语和解了，我则是一开始就能接受雪人语，但是非常讨厌这个故事本身。自负一点想，这也是一种长大了所以看不见“夜”吗（笑），不过都说樱摸鱼是“大人的童话”，所以估计也不是，但我却觉得这不算给大人的童话，至少不算给我的，虽然我只能算个不大不小的中猫。可能是我的认知太僵硬了吧。\n无论如何，在几个月，几年之后，我估计还是会很喜欢 OST 里面的歌，听到它，我想起的会是未来和重要之人相遇的故事，给人的心情就像飘落的樱花的淡淡香气。而上面写的这些讨厌的情绪，可能早已淡忘掉了吧。到那个时候，再写一篇博客吧[1]！\n---\n- 真的要和雪人语和解了吗（笑）\n\n- 在写本文的过程中群友发了个这个，震惊：FAVORITE社游戏可以直接从bios(UEFI)启动了_哔哩哔哩_bilibili\n\n- 一开始写的时候开了 Copilot，打了一个词之后把我乐死了。然后我把第一句话打完他就不补全了，看来是彻底不会了。\n\n  "},{"metadata":{"id":"nixos-in-a-nspawn-box","lang":"zh-CN","title":"NixOS in a (nspawn) box","tags":["Linux"],"publish_time":"2026-03-21T08:25:43+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617},{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612}],"text":"NixOS","hadv":3207,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"in","hadv":1055,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599}],"text":"a","hadv":599,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"(","components":[["M 206 -315C 206 -504 242 -638 376 -803L 352 -825C 180 -684 86 -529 86 -315C 86 -101 180 53 352 195L 376 173C 249 12 206 -126 206 -315Z",[-0.002,0.755]]],"bbox":{"top":-825,"bottom":195,"left":86,"right":376},"hadv":418}],"text":"(","hadv":418,"breakAfter":false},{"chars":[{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"nspawn","hadv":4087,"breakAfter":false},{"chars":[{"char":")","components":[["M 212 -315C 212 -126 176 8 42 173L 66 195C 238 54 332 -101 332 -315C 332 -529 238 -683 66 -825L 42 -803C 169 -642 212 -504 212 -315Z",[-0.001,0.755]]],"bbox":{"top":-825,"bottom":195,"left":42,"right":332},"hadv":418}],"text":")","hadv":418,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617}],"text":"box","hadv":1943,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>最近开始高强度 Vibe，继续推进把思考转移给<ruby>流浪猫<rp>(</rp><rt>LLM</rt><rp>)</rp></ruby>的伟大历程。为了让 Agent 能够通宵工作，跳过所有 Approval，需要把它放到一个容器里。为了能够让多个容器可以共享部分文件系统内容（e.g. 基础库，编译器，etc），一个常见方法是 Docker 然后让他们都共享 Overlay，但是容器重建之后已经下好的东西还是丢了。</p>\n<p>Idea：NixOS，但是所有容器共享 daemon 和 store，所有构建交给 Host 上的 Nix daemon 做，这样可以最大化利用缓存，共享文件系统内容，还顺便提供了 Immutability 和 Reproducibility。</p>\n<p>结论是这是可以工作的，见 <a href=\"https://github.com/CircuitCoder/nixos-nspawn-container\">CircuitCoder/nixos-nspawn-container</a>. 基本流程是：</p>\n<ul>\n<li>在 Host 上，根据 NixOS 的初始配置，构建一个 system derivation，symlink 到 <code>/nix/var/nix/gc-roots/per-container/&lt;ID&gt;/system</code>.</li>\n<li>生成一个 rootfs，里面把初始配置复制进去放到 <code>/etc/nixos/configuration.nix</code>.</li>\n<li>生成 nspawn 配置，把 socket，store，还有 per-container 的 gcroot 给 bind mount 进去。</li>\n</ul>\n<p>nspawn 和 NixOS 配置会有一些 Caveat，记录一下。</p>\n<h2>nspawn rootfs</h2>\n<p>nspawn 管的很宽，<a href=\"https://github.com/systemd/systemd/blob/61bceb1/src/nspawn/nspawn.c#L6356-L6369\">他会看 Rootfs 里面有没有 <code>os-release</code></a>，没有的话拒绝执行。</p>\n<p>问题：他是在进行 Bind mount 和 chroot 之前检查的。然后 NixOS 会在启动之后把 <code>/etc</code> 里面内容全都变成 symlink，然后 nspawn 看不懂 <code>os-release</code> 内容就爆炸了…</p>\n<p>还好 nspawn 除了 <code>/etc/os-release</code> 之外<a href=\"https://github.com/systemd/systemd/blob/7c1075fb8ff2d3b87fa463d542e2e00ac086cbd3/src/basic/os-util.c#L105-L114\">还会检查一个 fallback <code>/usr/lib/os-release</code></a>，这个目录（暂时）不会被 NixOS 覆盖掉，所以可以把 <code>os-release</code> 放在这里。不过只能在这里放一个文件而不是 Symlink 了。</p>\n<h2>gcroots</h2>\n<p>为了避免 Host 上的 GC 把容器里面在用的东西给扬了，常见的做法是把容器的 system derivation 放到 <code>gcroots</code> 下面。Nix 已经有一个 <code>/nix/var/nix/gcroots/per-container</code> 目录专门用来干这件事儿了，所以可以进行如下的 Bind mount:</p>\n<pre><code>/nix/var/nix/gcroots/per-container/&lt;ID&gt; -&gt; /nix/var/nix/profiles\n</code></pre>\n<p>这样容器里用到的所有 profile 都会自动进到 Host 的 gcroots 里。</p>\n<p>一些要注意的地方：NixOS expects rootfs 在 <code>/nix/var/nix/profiles/system</code> 下，<code>nixos-rebuild</code> 会生成的也都会在这个目录下放，所以这个目录得 RW mount，而且如果开 UID namespace 的话，里面的 root 在外面没有权限写这个目录，所以得开 idmap。如果在 zfs 上，没有 idmap 支持的话，可能得把 UID namespace 关了。</p>\n<h2>Initial build</h2>\n<p>在普通 Nix setup 上其实也可以 build NixOS system derivation:</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">nix-build </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#859900;\">$</span><span style=\"color:#268bd2;\">CHANNEL</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#268bd2;\"> -A</span><span style=\"color:#839496;\"> system</span><span style=\"color:#268bd2;\"> -I </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">nixos-config=</span><span style=\"color:#859900;\">$</span><span style=\"color:#268bd2;\">CONFIG</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#268bd2;\"> --no-out-link\n</span></code></pre>\n</div>\n<p>NixOS 会预期 system derivation 在 <code>/nix/var/nix/profiles/system</code> 下面，所以我们需要手动把它 symlink 到 <code>/nix/var/nix/gcroots/per-container/&lt;ID&gt;/system</code>.</p>\n<h2>Init</h2>\n<p>nspawn 默认会去找 <code>/usr/lib/systemd/systemd</code> 来当 init。NixOS 里面的 systemd 在 store 里，所以这样自然找不到。不过我们可以用 system derivation 里面的 init wrapper 脚本，注意得用容器里面的路径。在 nspawn 配置里需要加：</p>\n<pre><code>[Exec]\nParameters=/nix/var/nix/profiles/system/init\n</code></pre>\n<h2>NixOS config</h2>\n<p>首先，因为 daemon socket 是外面来的，我们得把容器里面的 daemon 干掉，并且要求所有 Nix 操作经过 daemon：</p>\n<pre><code class=\"language-nix\">boot.isContainer = true;\n\n# Daemon socket is bind mounted from the host\nsystemd.services.nix-daemon.enable = false;\nsystemd.sockets.nix-daemon.enable = false;\n\n# Store is ro-mounted\nnix.gc.automatic = false;\nnix.optimise.automatic = false;\n\n# Force commands through the daemon\nenvironment.variables.NIX_REMOTE = \"daemon\";\n</code></pre>\n<p>虽然即使这样做了，nix 命令还是会抱怨找不到 db。我们可以把 db 也 RO bind mount 进去：<code>NIX_REMOTE = \"daemon\"</code> 的时候，nix 不会直接修改 db，一定会通过 daemon。此外，这个 setup 在初次启动的时候，不会把外面的 channel 也加进去，所以如果 <code>configuration.nix</code> 依赖了特定 channel，在第一次 rebuild 之前在里面对应跑一次 <code>nix-channel --add</code> 就行了。</p>\n<p>NixOS 默认自然不会预期自己在容器里面执行。SystemD 会自动检测容器的存在，但是 NixOS 的各个脚本默认会预期自己在物理机上执行，这导致 <code>nixos-rebuild switch</code> 的时候 NixOS 的 activation script 会尝试 mount 各种 special fs，但是这些 fs 已经被 nspawn 管理了。注意到 switch 并不会 pivot root，所以之前已经 mount 好的东西不会掉。我们只需要让 NixOS 不要自己 mount：</p>\n<pre><code class=\"language-nix\">system.activationScripts.specialfs = lib.mkForce \"\";\n</code></pre>\n","plain":"最近开始高强度 Vibe，继续推进把思考转移给流浪猫(LLM)的伟大历程。为了让 Agent 能够通宵工作，跳过所有 Approval，需要把它放到一个容器里。为了能够让多个容器可以共享部分文件系统内容（e.g. 基础库，编译器，etc），一个常见方法是 Docker 然后让他们都共享 Overlay，但是容器重建之后已经下好的东西还是丢了。\nIdea：NixOS，但是所有容器共享 daemon 和 store，所有构建交给 Host 上的 Nix daemon 做，这样可以最大化利用缓存，共享文件系统内容，还顺便提供了 Immutability 和 Reproducibility。\n结论是这是可以工作的，见 CircuitCoder/nixos-nspawn-container. 基本流程是：\n- 在 Host 上，根据 NixOS 的初始配置，构建一个 system derivation，symlink 到 /nix/var/nix/gc-roots/per-container/<ID>/system.\n- 生成一个 rootfs，里面把初始配置复制进去放到 /etc/nixos/configuration.nix.\n- 生成 nspawn 配置，把 socket，store，还有 per-container 的 gcroot 给 bind mount 进去。\nnspawn 和 NixOS 配置会有一些 Caveat，记录一下。\n\nnspawn rootfs\nnspawn 管的很宽，他会看 Rootfs 里面有没有 os-release，没有的话拒绝执行。\n问题：他是在进行 Bind mount 和 chroot 之前检查的。然后 NixOS 会在启动之后把 /etc 里面内容全都变成 symlink，然后 nspawn 看不懂 os-release 内容就爆炸了…\n还好 nspawn 除了 /etc/os-release 之外还会检查一个 fallback /usr/lib/os-release，这个目录（暂时）不会被 NixOS 覆盖掉，所以可以把 os-release 放在这里。不过只能在这里放一个文件而不是 Symlink 了。\n\ngcroots\n为了避免 Host 上的 GC 把容器里面在用的东西给扬了，常见的做法是把容器的 system derivation 放到 gcroots 下面。Nix 已经有一个 /nix/var/nix/gcroots/per-container 目录专门用来干这件事儿了，所以可以进行如下的 Bind mount:\n/nix/var/nix/gcroots/per-container/<ID> -> /nix/var/nix/profiles\n\n这样容器里用到的所有 profile 都会自动进到 Host 的 gcroots 里。\n一些要注意的地方：NixOS expects rootfs 在 /nix/var/nix/profiles/system 下，nixos-rebuild 会生成的也都会在这个目录下放，所以这个目录得 RW mount，而且如果开 UID namespace 的话，里面的 root 在外面没有权限写这个目录，所以得开 idmap。如果在 zfs 上，没有 idmap 支持的话，可能得把 UID namespace 关了。\n\nInitial build\n在普通 Nix setup 上其实也可以 build NixOS system derivation:\nnix-build \"$CHANNEL\" -A system -I \"nixos-config=$CONFIG\" --no-out-link\n\nNixOS 会预期 system derivation 在 /nix/var/nix/profiles/system 下面，所以我们需要手动把它 symlink 到 /nix/var/nix/gcroots/per-container/<ID>/system.\n\nInit\nnspawn 默认会去找 /usr/lib/systemd/systemd 来当 init。NixOS 里面的 systemd 在 store 里，所以这样自然找不到。不过我们可以用 system derivation 里面的 init wrapper 脚本，注意得用容器里面的路径。在 nspawn 配置里需要加：\n[Exec]\nParameters=/nix/var/nix/profiles/system/init\n\n\nNixOS config\n首先，因为 daemon socket 是外面来的，我们得把容器里面的 daemon 干掉，并且要求所有 Nix 操作经过 daemon：\nboot.isContainer = true;\n\n# Daemon socket is bind mounted from the host\nsystemd.services.nix-daemon.enable = false;\nsystemd.sockets.nix-daemon.enable = false;\n\n# Store is ro-mounted\nnix.gc.automatic = false;\nnix.optimise.automatic = false;\n\n# Force commands through the daemon\nenvironment.variables.NIX_REMOTE = \"daemon\";\n\n虽然即使这样做了，nix 命令还是会抱怨找不到 db。我们可以把 db 也 RO bind mount 进去：NIX_REMOTE = \"daemon\" 的时候，nix 不会直接修改 db，一定会通过 daemon。此外，这个 setup 在初次启动的时候，不会把外面的 channel 也加进去，所以如果 configuration.nix 依赖了特定 channel，在第一次 rebuild 之前在里面对应跑一次 nix-channel --add 就行了。\nNixOS 默认自然不会预期自己在容器里面执行。SystemD 会自动检测容器的存在，但是 NixOS 的各个脚本默认会预期自己在物理机上执行，这导致 nixos-rebuild switch 的时候 NixOS 的 activation script 会尝试 mount 各种 special fs，但是这些 fs 已经被 nspawn 管理了。注意到 switch 并不会 pivot root，所以之前已经 mount 好的东西不会掉。我们只需要让 NixOS 不要自己 mount：\nsystem.activationScripts.specialfs = lib.mkForce \"\";\n\n"},{"metadata":{"id":"tun-misc","lang":"en-US","title":"Misc. Notes on Writing a TUN/TAP Device","tags":["Linux"],"publish_time":"2026-02-20T08:09:54+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579}],"text":"Misc","hadv":2463,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Notes","hadv":2966,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"W","components":[["M 9 -713L 161 -698L 196 -698L 347 -713L 347 -747L 9 -747Z",[-0.785,0.009]],["M 284 2L 377 2L 550 -576L 554 -590L 534 -590L 713 2L 806 2L 1030 -747L 972 -747L 811 -157L 808 -140L 826 -140L 655 -747L 553 -747L 385 -160L 381 -145L 399 -145L 244 -747L 63 -747Z",[-0.209,0.055]],["M 446 -713L 572 -698L 637 -698L 774 -713L 774 -747L 446 -747Z",[-0.673,0.043]],["M 867 -713L 973 -698L 1002 -698L 1108 -713L 1108 -747L 867 -747Z",[-0.544,0.089]]],"bbox":{"top":-747,"bottom":2,"left":9,"right":1108},"hadv":1111},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"Writing","hadv":4062,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599}],"text":"a","hadv":599,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"U","components":[["M 36 -713L 198 -698L 228 -698L 392 -713L 392 -747L 36 -747Z",[-0.815,0.01]],["M 417 20C 595 20 692 -84 695 -314L 699 -747L 647 -747L 651 -316C 653 -135 586 -62 470 -62C 355 -62 295 -129 295 -312L 295 -406C 295 -520 295 -634 297 -747L 121 -747C 125 -633 125 -518 125 -406L 125 -297C 125 -61 245 20 417 20Z",[-0.062,0.22]],["M 533 -713L 657 -697L 689 -697L 802 -713L 802 -747L 533 -747Z",[-0.295,0.048]]],"bbox":{"top":-747,"bottom":20,"left":36,"right":802},"hadv":829},{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825}],"text":"TUN","hadv":2368,"breakAfter":false},{"chars":[{"char":"/","components":[["M 26 181L 96 181L 399 -804L 330 -804Z",[0.277,0.894]]],"bbox":{"top":-804,"bottom":181,"left":26,"right":399},"hadv":425}],"text":"/","hadv":425,"breakAfter":true},{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690}],"text":"TAP","hadv":2165,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Device","hadv":3501,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>Taking a course in <ruby>networking<rp>(</rp><rt>网络原理</rt><rp>)</rp></ruby> prepares one for other difficulties in their lives. Here are some notes on writing a TUN/TAP device in Linux.</p>\n<h2>MTU</h2>\n<p>Since both Ethernet and IP are “datagram-y”, the outer connection will benefit from using a datagram protocol, since we won’t be dealing with retransmission and latency coming from sequential delivery. Wireguard and tinc both do this and use UDP.</p>\n<p>But the Internet™ is a dangerous place. MTU across multiple hops might be hard to predict. While wireguard just sends the encapsulated packet and hopes for the best, tinc tries to do Path MTU discovery, so it knows the (approximate) MTU towards a certain destination.</p>\n<p>This MTU is not necessarily the same as the MTU set on the TUN/TAP device. The detected PMTU may lag behind the real network condition, and the device drivers are not expected to change their MTU on the fly. Therefore, tinc’s dataplane has to do a lot of MTU-related work that’s normally done by the Linux kernel according to the device MTU, with a lot of arithmetic with hardcoded constants. This includes:</p>\n<ul>\n<li><a href=\"https://github.com/gsliepen/tinc/blob/1.1/src/route.c#L690\">Generation of ICMP “Fragmentation Needed”</a> in order for PMTU discovery inside the tunnel to work. (v4 &amp; v6)</li>\n<li><a href=\"https://github.com/gsliepen/tinc/blob/1.1/src/route.c#L570\">IPv4 Fragmentation</a> (This is NOT FUN to implement AT ALL. Luckily for us, IPv6 drops fragmentation. Unluckily for us, we haven’t dropped IPv4.)</li>\n<li><a href=\"https://github.com/gsliepen/tinc/blob/1.1/src/route.c#L389\">TCP MSS Clamping</a></li>\n</ul>\n<h2>Double routing</h2>\n<p>For a TUN device with multiple peers, when it’s fed with a packet, there is no way for the driver to know where the packet is routed to by the kernel. Asking the kernel is time-consuming and may race. So the TUN driver has to do the routing again, and this routing procedure is also not necessarily identical to the kernel’s routing table. Sticking to their respective philosophies, Wireguard routes according to CIDR ranges from the configuration file, while tinc routes according to the <a href=\"https://tinc-vpn.org/documentation-1.1/The-meta_002dprotocol.html\">advertised subnets</a> from the peers.</p>\n<p>For a P2P tunnel, this is not a problem. For a TAP device, this is also mostly not a problem, because we assume MAC addresses can be used as unique identifiers, and simply drop unrecognized unicast MAC destinations. But for a TAP to work, we need broadcasting.</p>\n<p>Speaking of broadcasting…</p>\n<h2>Broadcasting in a Mesh</h2>\n<p>Broadcasting in a mesh network can take a few approaches:</p>\n<ol>\n<li>Flood fill + filtering. This is the “easy way”, but relies on the assumption that packet delivery time is bounded, because we need to eventually discard the old filters.</li>\n<li>Spanning tree. Although the most elegant solution, this is just a nightmare to implement, and requires a meta-protocol. It also risks creating routing loops, so a lot of care has to be taken.</li>\n<li>Duplicated unicast. If the ingest node knows the internal ID of each reachable node in the broadcast domain, it can duplicate a broadcast packet into multiple unicast packets. This works best when:</li>\n</ol>\n<ul>\n<li>We’re already doing IP routing at the source, so the entire internal forwarding plane within the mesh operates on internal node IDs.</li>\n<li>Each node knows the internal ID of each node, and knows how to route to each node, but does not know a lot of other information (i.e. the entire network topology). This is common for mesh networks using a distance-vector routing protocol.</li>\n</ul>\n<p>tinc is a serious mesh VPN, so it took on the challenge of implementing <a href=\"https://tinc-vpn.org/documentation/Main-configuration-variables.html\">both 2 &amp; 3</a>. I’m lazy, so only option 3 for me.</p>\n<h2>Android-specific problems</h2>\n<ol>\n<li>After the creation of the VPN, the traffic of the VPN connection itself will be routed inside the VPN. The VPN application has to add itself to the blacklist of the VPN. In contrast, common practice on Linux is to use a fwmark w/ ip rule to route the traffic using another routing table. We don’t have that on Android.</li>\n<li>The application <strong>cannot close the fd</strong> of the TUN device. Relevant control logic has to deliberately leak the fd, before asking <code>VpnService</code> to terminate.</li>\n<li>Android apps can only create TUN.</li>\n<li>You cannot actually control the name of the TUN device. You also cannot easily listen to the changes on the device (i.e. routes and addresses through rtnetlink). We can poll it, but since the configurations of a TUN device cannot be easily changed by the user, we can assume it stays the same after it’s created.</li>\n</ol>\n<h2>Local tunnel loop on Linux</h2>\n<p>Linux really hates when it receives an input packet that apparently originates from a local address. This will mess up our testing setup, since we want to loop the tunnel back onto the same machine.</p>\n<p>The objectively correct way to solve this problem is via netns. But we’re lazy. Tuning the following sysctl parameter will allow us to send IPv4 packets looping back to the same machine:</p>\n<pre><code>echo \"1\" &gt; /proc/sys/net/ipv4/conf/all/accept_local\n</code></pre>\n<p>Surprisingly, we don’t need <code>rp_filter</code> settings besides this. Apparently, <code>accept_local</code> <a href=\"https://github.com/torvalds/linux/blob/8bf22c33e7a172fbc72464f4cc484d23a6b412ba/net/ipv4/netfilter/ipt_rpfilter.c#L41-L44\">short-circuits local addresses</a>. IPv6 reverse path filtering is implemented in netfilter, so if not explicitly enabled, we won’t be disturbed by it.</p>\n<h2>Additional resources</h2>\n<ul>\n<li>tinc’s author Guus Sliepen gave a great talk on some of the nitty-gritty details about tinc: <a href=\"https://www.youtube.com/watch?v=R7P_vvz1AP8\">tinc: the difficulties of a peer-to-peer VPN on the hostile Internet</a>. The talk was given in 2010, which is closer to the birth of Linux’s TUN/TAP interface and tinc (1997) than today. Time goes fast.</li>\n</ul>\n","plain":"Taking a course in networking(网络原理) prepares one for other difficulties in their lives. Here are some notes on writing a TUN/TAP device in Linux.\n\nMTU\nSince both Ethernet and IP are “datagram-y”, the outer connection will benefit from using a datagram protocol, since we won’t be dealing with retransmission and latency coming from sequential delivery. Wireguard and tinc both do this and use UDP.\nBut the Internet™ is a dangerous place. MTU across multiple hops might be hard to predict. While wireguard just sends the encapsulated packet and hopes for the best, tinc tries to do Path MTU discovery, so it knows the (approximate) MTU towards a certain destination.\nThis MTU is not necessarily the same as the MTU set on the TUN/TAP device. The detected PMTU may lag behind the real network condition, and the device drivers are not expected to change their MTU on the fly. Therefore, tinc’s dataplane has to do a lot of MTU-related work that’s normally done by the Linux kernel according to the device MTU, with a lot of arithmetic with hardcoded constants. This includes:\n- Generation of ICMP “Fragmentation Needed” in order for PMTU discovery inside the tunnel to work. (v4 & v6)\n- IPv4 Fragmentation (This is NOT FUN to implement AT ALL. Luckily for us, IPv6 drops fragmentation. Unluckily for us, we haven’t dropped IPv4.)\n- TCP MSS Clamping\n\nDouble routing\nFor a TUN device with multiple peers, when it’s fed with a packet, there is no way for the driver to know where the packet is routed to by the kernel. Asking the kernel is time-consuming and may race. So the TUN driver has to do the routing again, and this routing procedure is also not necessarily identical to the kernel’s routing table. Sticking to their respective philosophies, Wireguard routes according to CIDR ranges from the configuration file, while tinc routes according to the advertised subnets from the peers.\nFor a P2P tunnel, this is not a problem. For a TAP device, this is also mostly not a problem, because we assume MAC addresses can be used as unique identifiers, and simply drop unrecognized unicast MAC destinations. But for a TAP to work, we need broadcasting.\nSpeaking of broadcasting…\n\nBroadcasting in a Mesh\nBroadcasting in a mesh network can take a few approaches:\n- Flood fill + filtering. This is the “easy way”, but relies on the assumption that packet delivery time is bounded, because we need to eventually discard the old filters.\n- Spanning tree. Although the most elegant solution, this is just a nightmare to implement, and requires a meta-protocol. It also risks creating routing loops, so a lot of care has to be taken.\n- Duplicated unicast. If the ingest node knows the internal ID of each reachable node in the broadcast domain, it can duplicate a broadcast packet into multiple unicast packets. This works best when:\n- We’re already doing IP routing at the source, so the entire internal forwarding plane within the mesh operates on internal node IDs.\n- Each node knows the internal ID of each node, and knows how to route to each node, but does not know a lot of other information (i.e. the entire network topology). This is common for mesh networks using a distance-vector routing protocol.\ntinc is a serious mesh VPN, so it took on the challenge of implementing both 2 & 3. I’m lazy, so only option 3 for me.\n\nAndroid-specific problems\n- After the creation of the VPN, the traffic of the VPN connection itself will be routed inside the VPN. The VPN application has to add itself to the blacklist of the VPN. In contrast, common practice on Linux is to use a fwmark w/ ip rule to route the traffic using another routing table. We don’t have that on Android.\n- The application cannot close the fd of the TUN device. Relevant control logic has to deliberately leak the fd, before asking VpnService to terminate.\n- Android apps can only create TUN.\n- You cannot actually control the name of the TUN device. You also cannot easily listen to the changes on the device (i.e. routes and addresses through rtnetlink). We can poll it, but since the configurations of a TUN device cannot be easily changed by the user, we can assume it stays the same after it’s created.\n\nLocal tunnel loop on Linux\nLinux really hates when it receives an input packet that apparently originates from a local address. This will mess up our testing setup, since we want to loop the tunnel back onto the same machine.\nThe objectively correct way to solve this problem is via netns. But we’re lazy. Tuning the following sysctl parameter will allow us to send IPv4 packets looping back to the same machine:\necho \"1\" > /proc/sys/net/ipv4/conf/all/accept_local\n\nSurprisingly, we don’t need rp_filter settings besides this. Apparently, accept_local short-circuits local addresses. IPv6 reverse path filtering is implemented in netfilter, so if not explicitly enabled, we won’t be disturbed by it.\n\nAdditional resources\n- tinc’s author Guus Sliepen gave a great talk on some of the nitty-gritty details about tinc: tinc: the difficulties of a peer-to-peer VPN on the hostile Internet. The talk was given in 2010, which is closer to the birth of Linux’s TUN/TAP interface and tinc (1997) than today. Time goes fast.\n"},{"metadata":{"id":"ldrl-staq","lang":"en-US","title":"Load Release, Store Acquire, and Seqlocks","tags":["内存序"],"publish_time":"2026-01-12T05:46:44+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"L","components":[["M 41 -0L 218 -0L 219 -50L 202 -50L 42 -34Z",[0.751,0.04]],["M 41 -713L 202 -698L 240 -698L 403 -713L 403 -747L 41 -747Z",[-0.878,0.008]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -346L 303 -411C 303 -514 303 -632 306 -747L 130 -747C 133 -631 133 -513 133 -395L 133 -324C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 619 -0L 617 -224L 562 -224L 503 -2L 588 -39L 219 -39Z",[0.547,0.208]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":619},"hadv":651},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"Load","hadv":2560,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Release","hadv":4005,"breakAfter":false},{"chars":[{"char":",","components":[["M 78 189C 191 159 262 70 262 -52C 262 -84 258 -104 247 -134C 224 -155 201 -162 171 -162C 119 -162 79 -122 79 -71C 79 -42 95 -10 139 12L 211 49L 198 11C 181 88 140 125 67 161Z",[0.041,0.481]]],"bbox":{"top":-162,"bottom":189,"left":67,"right":262},"hadv":340}],"text":",","hadv":340,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Store","hadv":2761,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"q","components":[["M 261 17C 335 17 400 -16 448 -84L 455 -84L 440 -95C 408 -66 380 -54 343 -54C 264 -54 208 -109 208 -270C 208 -434 264 -494 342 -494C 377 -494 409 -482 442 -450L 460 -461L 455 -465C 416 -530 356 -563 289 -563C 146 -563 35 -450 35 -267C 35 -86 133 17 261 17Z",[0.019,0.474]],["M 344 259L 646 259L 646 230L 544 219L 444 219L 344 230Z",[0.875,0.002]],["M 420 259L 586 259C 583 180 582 101 582 22L 582 -398L 586 -552L 571 -561L 420 -478L 420 -77L 424 -63L 424 22C 424 101 423 180 420 259Z",[0.007,0.803]]],"bbox":{"top":-563,"bottom":259,"left":35,"right":646},"hadv":657},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Acquire","hadv":4152,"breakAfter":false},{"chars":[{"char":",","components":[["M 78 189C 191 159 262 70 262 -52C 262 -84 258 -104 247 -134C 224 -155 201 -162 171 -162C 119 -162 79 -122 79 -71C 79 -42 95 -10 139 12L 211 49L 198 11C 181 88 140 125 67 161Z",[0.041,0.481]]],"bbox":{"top":-162,"bottom":189,"left":67,"right":262},"hadv":340}],"text":",","hadv":340,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"and","hadv":1969,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"q","components":[["M 261 17C 335 17 400 -16 448 -84L 455 -84L 440 -95C 408 -66 380 -54 343 -54C 264 -54 208 -109 208 -270C 208 -434 264 -494 342 -494C 377 -494 409 -482 442 -450L 460 -461L 455 -465C 416 -530 356 -563 289 -563C 146 -563 35 -450 35 -267C 35 -86 133 17 261 17Z",[0.019,0.474]],["M 344 259L 646 259L 646 230L 544 219L 444 219L 344 230Z",[0.875,0.002]],["M 420 259L 586 259C 583 180 582 101 582 22L 582 -398L 586 -552L 571 -561L 420 -478L 420 -77L 424 -63L 424 22C 424 101 423 180 420 259Z",[0.007,0.803]]],"bbox":{"top":-563,"bottom":259,"left":35,"right":646},"hadv":657},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Seqlocks","hadv":4622,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>Reading RISC-V specification is very fun and a totally normal hobby that’s not weird at all. Anyway there is an interesting remark in the specification of the newly ratified <a href=\"https://github.com/riscv/riscv-zalasr/releases/tag/v1.0\">Zalasr extension for load-acquire and store-release</a>:</p>\n<blockquote>\n<p>The versions without the aq bit set are RESERVED. <code>LD.{AQ, AQRL}</code> is RV64-only.</p>\n<p>The aq bit is mandatory because the two encodings that would be produced are not seen as useful at this time. … The version with only the rl bit would correspond to load-release. <strong>Load-release has theoretical applications in seqlocks</strong>, but is not supported in language-level memory models and so is not included.</p>\n</blockquote>\n<p>There is a similar remark on <code>S*.RL</code> about store-acquire.</p>\n<p>At first glance, load-release and store-acquire don’t even seem to make sense. However, it should be remembered that <em>coherence</em> has four flavors. The most obvious one is the write-read coherence, where a write is observed by a subsequent read. But we also have read-write coherence, where a read <em>did not</em> observe a subsequent write. Ignoring some troublesome details arising from mixed-size accesses, every memory address has a total order of all reads and writes. So it’s pretty natural to consider a load-release and store-acquire pair.</p>\n<h2>Seqlocks</h2>\n<p>To have a better understanding of the semantics of load-release and store-acquire, let’s take a look at a <a href=\"https://en.wikipedia.org/wiki/Seqlock\">seqlock</a>. Seqlocks are a variant of reader-writer locks that slightly prioritize writers more. The traditional reader-writer locks <small>, which <a href=\"/post/qreadwritelock-race\">an older post took a look at</a>,</small> may suffer from writer starvation. Seqlocks flip the priority, so a write can always proceed at any time, and readers may live-lock.</p>\n<p>The structure of a seqlock is very similar to an optimistic lock on the reader side, plus a normal mutex on the writer side:</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#586e75;\">// The sequence number\n</span><span style=\"color:#586e75;\">// - If odd, a write is in progress\n</span><span style=\"color:#586e75;\">// - If even, readers are safe to read\n</span><span style=\"color:#839496;\">atomic</span><span style=\"color:#657b83;\">&lt;</span><span style=\"color:#859900;\">uint64_t</span><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> seq </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">void </span><span style=\"color:#b58900;\">do_read</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">while </span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">true</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">uint64_t</span><span style=\"color:#839496;\"> begin </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> seq.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_acquire</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">begin </span><span style=\"color:#859900;\">&amp; </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#586e75;\">// Write in progress\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">    \n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">////////\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// Read data\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">////////\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// Release the lock\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#b58900;\">atomic_thread_fence</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_acquire</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">uint64_t</span><span style=\"color:#839496;\"> end </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> seq.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">end </span><span style=\"color:#657b83;\">==</span><span style=\"color:#839496;\"> begin</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#586e75;\">// No write happened during read\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">break</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">void </span><span style=\"color:#b58900;\">do_write</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// Acquire lock. This is done by treating the low bit of seq as a mutex.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">uint64_t</span><span style=\"color:#839496;\"> orig;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">while </span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">true</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    orig </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> seq.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">orig </span><span style=\"color:#859900;\">&amp; </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#586e75;\">// Another writer in progress\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">bool</span><span style=\"color:#839496;\"> updated </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> seq.</span><span style=\"color:#b58900;\">compare_exchange_weak</span><span style=\"color:#657b83;\">(\n</span><span style=\"color:#839496;\">      orig, orig </span><span style=\"color:#657b83;\">+ </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">      std::memory_order_relaxed,\n</span><span style=\"color:#839496;\">      std::memory_order_relaxed\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">updated</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#b58900;\">atomic_thread_fence</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_release</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">break</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">////////\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// Update data\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">////////\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// Release the lock\n</span><span style=\"color:#839496;\">  seq.</span><span style=\"color:#b58900;\">store</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">orig </span><span style=\"color:#657b83;\">+ </span><span style=\"color:#6c71c4;\">2</span><span style=\"color:#839496;\">, std::memory_order_release</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>Notably, like any optimistic lock, the locking successfulness is (also) checked at the end of the critical section. This results in a load-release / store-acquire pair.<sup>[1]</sup></p>\n<p>However, since we don’t have load-release and store-acquire in the C++ memory model, we have to use two fences to emulate them.<sup>[2]</sup> This is really unfortunate, because from a hardware perspective, there is an opportunity to optimize load-release and store-acquire better than fences, i.e. add a load-wait-for-store control path for individual load-queue elements. Hardware can also just fallback to a fence. In fact, RISC-V already has some <del>cursed</del> stuff such as <code>fence w,r</code>.</p>\n<p>It’s quite counterintuitive that for a load-release we need an <em>acquire</em> fence, and vice-versa. This is also due to the fact that in C++, a release-fence is only meaningful when followed by a store, not a load. Since we’re trying to prevent a load-load reordering, we need to use an <em>acquire</em> fence coupled with all previous loads. On RISC-V, the release fence will compile to <code>fence rw, w</code>, and the acquire fence will compile to <code>fence r, rw</code>. Ideally we need <code>fence r, r</code> and <code>fence w, w</code>, but there is no way to do that in C++ right now.</p>\n<h2>Additional resources</h2>\n<p>The initial ideas for Zalasr seem to stem from the discussion in the RISC-V mailing list thread <a href=\"https://lists.riscv.org/g/tech-unprivileged/topic/risc_v_memory_model_topics/92916241\">RISC-V memory model topics</a>. The seqlocks remark originally comes from the C++ paper <a href=\"https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4455.html\">N4455 No Sane Compiler Would Optimize Atomics</a></p>\n<p>For seqlocks themselves, there is <a href=\"https://stackoverflow.com/questions/54611003/implementing-64-bit-atomic-counter-with-32-bit-atomics\">an amazing explanation on StackOverflow by Peter Cordes</a>. Everyday I dream of being as knowledgeable as him. Please check it out.</p>\n<div class=\"footnotes\">\n<ul>\n<li>[1] As for the other combinations, since for any acquire-release pair, no matter which one is the read or write, only a read can generate results that can be used as a condition. So a store-acquire / store-release pair does not seem to be useful. For a load-release / load-acquire pair, the read-read coherence needs to be mediated by at least one write in between. There might be niche use cases where a dedicated thread maintains a counter to schedule other threads, whose work has a deadline but can be retried (re-grab a sequence number from a ticket generator).</li>\n<li>[2] Stronger orders like <code>std::memory_order_seq_cst</code> alone do not increase the strength of a single load or store. Per C++ standard, a seq-cst load may reorder with other memory accesses. The fence is necessary here.</li>\n</ul>\n</div>","plain":"Reading RISC-V specification is very fun and a totally normal hobby that’s not weird at all. Anyway there is an interesting remark in the specification of the newly ratified Zalasr extension for load-acquire and store-release:\nThe versions without the aq bit set are RESERVED. LD.{AQ, AQRL} is RV64-only.\nThe aq bit is mandatory because the two encodings that would be produced are not seen as useful at this time. … The version with only the rl bit would correspond to load-release. Load-release has theoretical applications in seqlocks, but is not supported in language-level memory models and so is not included.\n\nThere is a similar remark on S*.RL about store-acquire.\nAt first glance, load-release and store-acquire don’t even seem to make sense. However, it should be remembered that coherence has four flavors. The most obvious one is the write-read coherence, where a write is observed by a subsequent read. But we also have read-write coherence, where a read did not observe a subsequent write. Ignoring some troublesome details arising from mixed-size accesses, every memory address has a total order of all reads and writes. So it’s pretty natural to consider a load-release and store-acquire pair.\n\nSeqlocks\nTo have a better understanding of the semantics of load-release and store-acquire, let’s take a look at a seqlock. Seqlocks are a variant of reader-writer locks that slightly prioritize writers more. The traditional reader-writer locks , which an older post took a look at, may suffer from writer starvation. Seqlocks flip the priority, so a write can always proceed at any time, and readers may live-lock.\nThe structure of a seqlock is very similar to an optimistic lock on the reader side, plus a normal mutex on the writer side:\n// The sequence number\n// - If odd, a write is in progress\n// - If even, readers are safe to read\natomic<uint64_t> seq = 0;\n\nvoid do_read() {\n  while (true) {\n    uint64_t begin = seq.load(std::memory_order_acquire);\n    if (begin & 1) {\n      // Write in progress\n      continue;\n    }\n    \n    ////////\n    // Read data\n    ////////\n\n    // Release the lock\n    atomic_thread_fence(std::memory_order_acquire);\n    uint64_t end = seq.load(std::memory_order_relaxed);\n\n    if (end == begin) {\n      // No write happened during read\n      break;\n    }\n  }\n}\n\nvoid do_write() {\n  // Acquire lock. This is done by treating the low bit of seq as a mutex.\n  uint64_t orig;\n  while (true) {\n    orig = seq.load(std::memory_order_relaxed);\n    if (orig & 1) {\n      // Another writer in progress\n      continue;\n    }\n\n    bool updated = seq.compare_exchange_weak(\n      orig, orig + 1,\n      std::memory_order_relaxed,\n      std::memory_order_relaxed\n    );\n    if (updated) {\n      atomic_thread_fence(std::memory_order_release);\n      break;\n    }\n  }\n\n  ////////\n  // Update data\n  ////////\n\n  // Release the lock\n  seq.store(orig + 2, std::memory_order_release);\n}\n\nNotably, like any optimistic lock, the locking successfulness is (also) checked at the end of the critical section. This results in a load-release / store-acquire pair.[1]\nHowever, since we don’t have load-release and store-acquire in the C++ memory model, we have to use two fences to emulate them.[2] This is really unfortunate, because from a hardware perspective, there is an opportunity to optimize load-release and store-acquire better than fences, i.e. add a load-wait-for-store control path for individual load-queue elements. Hardware can also just fallback to a fence. In fact, RISC-V already has some cursed stuff such as fence w,r.\nIt’s quite counterintuitive that for a load-release we need an acquire fence, and vice-versa. This is also due to the fact that in C++, a release-fence is only meaningful when followed by a store, not a load. Since we’re trying to prevent a load-load reordering, we need to use an acquire fence coupled with all previous loads. On RISC-V, the release fence will compile to fence rw, w, and the acquire fence will compile to fence r, rw. Ideally we need fence r, r and fence w, w, but there is no way to do that in C++ right now.\n\nAdditional resources\nThe initial ideas for Zalasr seem to stem from the discussion in the RISC-V mailing list thread RISC-V memory model topics. The seqlocks remark originally comes from the C++ paper N4455 No Sane Compiler Would Optimize Atomics\nFor seqlocks themselves, there is an amazing explanation on StackOverflow by Peter Cordes. Everyday I dream of being as knowledgeable as him. Please check it out.\n- [1] As for the other combinations, since for any acquire-release pair, no matter which one is the read or write, only a read can generate results that can be used as a condition. So a store-acquire / store-release pair does not seem to be useful. For a load-release / load-acquire pair, the read-read coherence needs to be mediated by at least one write in between. There might be niche use cases where a dedicated thread maintains a counter to schedule other threads, whose work has a deadline but can be retried (re-grab a sequence number from a ticket generator).\n- [2] Stronger orders like std::memory_order_seq_cst alone do not increase the strength of a single load or store. Per C++ standard, a seq-cst load may reorder with other memory accesses. The fence is necessary here.\n"},{"metadata":{"id":"about-expedition-33","lang":"zh-CN","title":"玩了 Clair Obscur: Expedition 33","tags":["游戏屋"],"publish_time":"2026-01-10T12:52:45+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"玩","components":[["M 14 -166L 77 -7C 90 -10 101 -22 106 -35C 257 -124 358 -195 420 -244L 418 -253C 253 -213 81 -177 14 -166Z",[0.613,0.259]],["M 29 -759L 37 -731L 400 -731C 415 -731 426 -736 428 -747C 385 -789 309 -853 309 -853L 242 -759Z",[0.889,0.087]],["M 34 -475L 42 -447L 393 -447C 407 -447 417 -452 420 -463C 388 -502 328 -564 328 -564L 275 -475Z",[0.968,0.085]],["M 141 -759L 141 -129L 281 -179L 281 -759Z",[0.008,0.769]],["M 464 -495C 469 -257 448 -59 232 84L 237 94C 556 -4 609 -218 614 -495Z",[0.269,0.684]],["M 367 -495L 375 -467L 956 -467C 971 -467 982 -472 985 -483C 938 -528 857 -596 857 -596L 785 -495Z",[0.86,0.073]],["M 416 -750L 424 -722L 915 -722C 930 -722 941 -727 944 -738C 897 -782 817 -848 817 -848L 746 -750Z",[0.637,0.0]],["M 665 -494L 665 -48C 665 37 680 64 773 64L 829 64C 945 64 987 36 987 -14C 987 -39 981 -55 951 -71L 948 -234L 938 -234C 918 -167 899 -101 888 -80C 882 -69 878 -66 869 -66C 863 -66 856 -66 847 -66L 821 -66C 807 -66 804 -71 804 -84L 804 -456C 804 -466 804 -482 804 -494Z",[-0.144,0.526]]],"bbox":{"top":-853,"bottom":94,"left":14,"right":987},"hadv":1000}],"text":"玩","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Clair","hadv":2551,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Obscur","hadv":3786,"breakAfter":false},{"chars":[{"char":":","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]],["M 170 -368C 222 -368 262 -409 262 -459C 262 -510 222 -552 170 -552C 118 -552 78 -510 78 -459C 78 -409 118 -368 170 -368Z",[0.001,0.01]]],"bbox":{"top":-552,"bottom":17,"left":78,"right":262},"hadv":340}],"text":":","hadv":340,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"E","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 634 -0L 632 -207L 576 -207L 519 -1L 605 -39L 218 -39Z",[0.604,0.185]],["M 218 -363L 467 -363L 467 -399L 218 -399Z",[-0.86,0.001]],["M 554 -548L 612 -548L 613 -747L 218 -747L 218 -708L 583 -708L 499 -747Z",[-0.58,0.193]],["M 454 -263L 504 -263L 504 -505L 454 -505L 438 -395L 438 -374Z",[0.007,0.742]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":634},"hadv":674},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"Expedition","hadv":5695,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"3","components":[["M 283 17C 454 17 559 -67 559 -189C 559 -307 488 -389 279 -400L 279 -384C 468 -401 536 -482 536 -587C 536 -690 461 -764 303 -764C 181 -764 76 -713 73 -593C 84 -574 104 -562 129 -562C 164 -562 195 -579 204 -630L 224 -733L 161 -708C 198 -723 229 -730 256 -730C 332 -730 377 -680 377 -581C 377 -462 318 -408 230 -408L 196 -408L 196 -369L 235 -369C 337 -369 391 -306 391 -188C 391 -76 334 -18 231 -18C 196 -18 174 -26 145 -41L 196 -12L 178 -120C 169 -187 144 -207 104 -207C 78 -207 52 -193 41 -161C 50 -49 131 17 283 17Z",[0.011,0.423]]],"bbox":{"top":-764,"bottom":17,"left":41,"right":559},"hadv":612},{"char":"3","components":[["M 283 17C 454 17 559 -67 559 -189C 559 -307 488 -389 279 -400L 279 -384C 468 -401 536 -482 536 -587C 536 -690 461 -764 303 -764C 181 -764 76 -713 73 -593C 84 -574 104 -562 129 -562C 164 -562 195 -579 204 -630L 224 -733L 161 -708C 198 -723 229 -730 256 -730C 332 -730 377 -680 377 -581C 377 -462 318 -408 230 -408L 196 -408L 196 -369L 235 -369C 337 -369 391 -306 391 -188C 391 -76 334 -18 231 -18C 196 -18 174 -26 145 -41L 196 -12L 178 -120C 169 -187 144 -207 104 -207C 78 -207 52 -193 41 -161C 50 -49 131 17 283 17Z",[0.011,0.423]]],"bbox":{"top":-764,"bottom":17,"left":41,"right":559},"hadv":612}],"text":"33","hadv":1224,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<style>\nfigure:has(iframe) {\n    width: 100%;\n}\nfigure > iframe {\n    width: 100%;\n    height: auto;\n    aspect-ratio: 16 / 9;\n}\n</style>\n<p>我感觉 E33 成为了一个少见的可以无条件给别人推荐的游戏。作为一个 Outer Wilds 吹，卖 OW 安利的经验是安利游戏成功率很低。电子游戏的体裁众多，玩家自然各自有自己喜欢的内容。然而 E33 做到的了一件非常困难的事情：结合了数个不同类型游戏的较为核心的机制，并且执行极为出色，在音乐、美术、叙事等各个方面都可圈可点。这让我相信几乎所有玩家都可以在这个游戏里找到享受的部分。</p>\n<p>本文简单讨论一下我自己在 60h 游戏过程中的感想。本文基本没有 Spoiler。</p>\n<h2>音乐</h2>\n<p>这个游戏的音乐是我觉得它最出彩的部分<small>，并不是说其他部分不NB</small>。E33 的 OST 里几乎每一首歌拿出来单独都可以单曲循环很久，每一首曲子都和游戏其他部分完美结合，无论是战斗过程、当下的叙事、角色的情绪表现等等。整个 OST 的 154 首 (8h) 都保持了这种高水平，甚至到了一种让人难以理解的地步。</p>\n<figure>\n  <iframe src=\"https://www.youtube.com/embed/bTAlomrlDvo\" title=\"Clair Obscur: Expedition 33 (Original Soundtrack) 100 - Sirène - Robe de Jour\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n  <figcaption><a href=\"https://www.youtube.com/watch?v=bTAlomrlDvo\">Clair Obscur: Expedition 33 (Original Soundtrack) 100 - Sirène - Robe de Jour</a></figcaption>\n</figure>\n<p>看看我玩过的之前的 Indie game 中的 NB OST: C418 的 Minecraft<sup>[1]</sup>, Andrew Prahlow 的 OW, Disasterpeace 的 FEZ 和 HLD, Lifeformed 的 TUNIC，这些都是优秀的游戏 OST，但是通常共享的模式是 Motif 的反复演绎。其中的例外是 C418 在 Minecraft: Volume Alpha 中表现出了多种不同的作曲风格和用器，但是还是风格集中在营造一种孤单、怀旧的情绪上，主要用钢琴。Lorien Testard (and Alice Duport-Percier) 在 E33 OST 中展现出了更多不同的音乐风格，以对应游戏过程中各个片段叙事的情绪。OST 中很大一部分是交响乐 + 人声，但是也有其他各种完全迥然不同的曲子，在听了三小时的钢琴之后忽然被游戏在脸上甩了一首 Electro funk，是一个很独特的体验。很自然也有很多玩家在游戏过程中被音乐 Stunlock，甚至在标题界面，<del>还好这是一个回合制 RPG。</del></p>\n<p>传奇的一点是，Lorien Testard 是主创团队在一个（现在已经🈚了的）法语论坛上找到的<sup>[2,4]</sup>，双方都只上了一次这个网站，只发了一个帖，结果最终就产生了这个 OST。在此之前，Lorien Testard 是一个吉他老师<sup>[5]</sup>，在五年的开发时间内，平均每两周就能产出一首曲子最终用到了游戏里。现在我对法国一般通过吉他老师的印象就是他们可以随手掏出来一首 Alicia。</p>\n<figure>\n  <iframe width=\"1536\" height=\"621\" src=\"https://www.youtube.com/embed/p00EF6_b5pI\" title=\"Clair Obscur: Expedition 33 | Alicia [Official Music Video]\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n  <figcaption><a href=\"https://www.youtube.com/watch?v=p00EF6_b5pI\">Clair Obscur: Expedition 33 | Alicia [Official Music Video]</a></figcaption>\n</figure>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/2026-01-10-e33-music-2.png\">\n  <img src=\"https://layered-assets.thu.fail/2026-01-10-e33-music-1.png\">\n  <figcaption>感想</figcaption>\n</figure>\n<p>然而我不懂音乐，所以总之就是：音乐很好听。考虑到这是半个音乐游戏，这已经比绝大多数音乐游戏要厉害了（？）。希望我能够安利更多其他懂音乐的群友网友玩这个游戏，然后锐评，供我学习。非常欢迎大家先来听一听 OST，Sandfall 在他们 YouTube 上直接传了<a href=\"https://youtube.com/playlist?list=PLI0_h8FqQIs3pcDzzO8AOdVLN-FqCA4sO\">整个 OST</a>，<del>比 Bandcamp 和 Steam 上能买到的还要全</del>。B 站和油管各地也有大量的 E33 音乐的分析。</p>\n<h2>战斗系统</h2>\n<p>这是一个<a href=\"https://youtu.be/_Lk542gbjBc?t=263\">下落式音游</a>。有根据时机按键，有好听音乐，有下落的敌人，所以是下落式音游。</p>\n<figure>\n  <video controls>\n    <source src=\"https://layered-assets.thu.fail/2026-01-10-e33-music-game.mp4\" />\n  </video>\n  <figcaption>下落式.mp4</figcaption>\n</figure>\n<p>即使不把这个当作一个下落式音游，从战斗系统角度而言，这个游戏其实更接近一个类魂的游戏。玩家需要像类魂游戏一样“下载”敌人的动作，在游戏后期闪避和格挡几乎是必须的。<del>并且连快慢刀都学来了</del>。传统 Turn-based RPG 的战斗中重点是战术、战略，即战斗前的装备管理，战斗时的资源管理（动作点，属性，HP），但是在敌人环节就几乎完全脱离玩家控制。E33 把格挡系统放进来，再加上玩家技能的 QTE，构成了一个极为动态的战斗系统。最终给玩家带来多巴胺的，也一般不是通过解谜一样的精度推过了一个 Boss，而是战斗过程中按到了所有的格挡。难度设置上，通过伤害膨胀来控制玩家行为、动态难度平衡（i.e. 刷级用时间换操作），也更像一个类魂游戏。</p>\n<p>事实上，选择符文的页面 UI 非常糟糕，但我都没有听到像当时 Death Stranding 开喷的讨论，说明可能真的无人关心（</p>\n<h2>故事和叙事</h2>\n<p>根据 The Internet™️ 上的讨论，本游戏的故事对许多玩家而言也是一大亮点。这是首个在 OW 之外我看到有人说想要 “Forget everything and play it again” 的。玩家群体经常讲的另一个玩笑话是 Sandfall should pay for my therpy，可见这个故事的动人程度。</p>\n<p>然而为了不剧透，这里只讨论序章 <sub><a href=\"https://www.youtube.com/watch?v=WmB89Ht0lgE\">[录像，无剧透]</a></sub>，也就基本就是预告片和 Steam 商品页的内容。即便如此，E33 在序章中两小时内也基本完全完成了游戏情绪基调的营造，并且勾起玩家的兴趣。事实上，游戏开始的第一段对话基本就很有意思：</p>\n<blockquote>\n<p><em>Maelle</em>: If you’re going to give someone flowers, you should probably do it BEFORE they wither and die.</p>\n<p><em>Gustave</em>: What, the flower? Or Sophie?</p>\n<p><em>Maelle</em>: Ooh, dark. Sophie would approve.</p>\n</blockquote>\n<p>游戏整体剧情总体就是这种幽默风趣，但又伤感（或者说别扭）的情绪下逐渐展开的。整个序章的精致程度，以及在叙事角度上的有效程度都是很出色的，上一次见到这种还是 <del>紫社的 アオイトリ</del>。我感觉原因之一是音乐，原因之二是美术和画面：现代游戏引擎的 Photorealistic 渲染最强的一个优势就是在演出和叙事上；原因之三就是设定是有趣的。这是 <a href=\"https://store.steampowered.com/app/1903340/Clair_Obscur_Expedition_33/\">Steam 商店页</a>简介第一段：</p>\n<blockquote>\n<p>Once a year, the Paintress wakes and paints upon her monolith. Paints her cursed number. And everyone past that age turns to smoke and fades away. Year by year, that number ticks down and more of us are erased. Tomorrow she’ll wake and paint “33.” And tomorrow we depart on our final mission - Destroy the Paintress, so she can never paint death again.</p>\n<p>We are Expedition 33.</p>\n</blockquote>\n<p>弑神这个设定自然是 JRPG 人狂喜了。但是更重要的问题是，Paintress 的力量来源是哪里？世界的本质是什么？玩家处于远征队 33 视角，那么其他的远征队的故事是什么？这是这个游戏剧情的 Hook，而不是一个单纯的英雄谭。</p>\n<p>当然，人物对白还有演出节奏是最关键的，我感觉我的水平难以描述 E33 的文字中的魔法，上面提到的游戏中的第一段对白是一个例子，更多的可以看序章的录像。另一个很传奇的一件事情是，游戏的主笔 Jennifer Svedberg-Yen 最开始是主创在 Reddit 上找到应聘声优的人<sup>[4]</sup>…这真的是很神奇的一个游戏。</p>\n<p>整个游戏主线的剧情和叙事在众多转折之中，一直保持着这种高水准。想通过游戏体验一个悲剧的群像故事的群友有福了，而且这游戏还有个 Story mode 难度供小手残玩家（比如我）体验。</p>\n<h2>玩家引导及内容布置</h2>\n<p>刚刚提到了游戏主要靠伤害数做 Gatekeeping 从而实现玩家引导。游戏大概可以分为两半，前一半是一个线性叙事结构，对应一个线性的关卡设计，后一半转换成开放世界，世界地图会变得开放。但是前面说的这种引导方式放到开放世界中真的完全不工作，因为基本没办法控制在特定一个场景的玩家的等级有多少。E33 做了一个妥协是标记了每个场景的推荐最低等级，如果没有达到会给玩家显示一个红色的<span style=\"color: red\">危险</span>，但是另一个方向就没法保证了。最终 Boss 的预定等级设计是在地图打开之后玩家立刻去打最终 Boss<sup>[3]</sup>，做了一些支线之后就非常明显 Over level 了。即使在支线之中，也很难知道应该按什么顺序，一不小心就到了 One-shot 一个 Boss 的地步，那所有的演出都失效了，变成看速通一样（</p>\n<p>其他类型的 RPG 其实也有类似的问题，但是开放世界 RPG 会有意不让数值膨胀变得这么严重，以及让敌人也随玩家的等级（或者游戏进度）变强。Sandfall 不少主创的老东家阿育是一个在 Sandbox AVG / RPG 里 <del>不思进取</del> 摸爬滚打多年的选手，感觉真可以抄抄刺客信条（笑）。</p>\n<h2>TGA Drama and “indie games”</h2>\n<p>Finally, let’s talk about the 🐘 in the 🏠. <a href=\"https://www.youtube.com/watch?v=YvRm4HKK4gQ\">在 TGA 横扫了九个奖项之后</a>，招了很多恨。其中也许可能可以讨论一下的 Argument 大概可以归为如下两类：</p>\n<ul>\n<li>这不够 Indie</li>\n<li>这不是 RPG</li>\n</ul>\n<p>关于 Indie 的批评，有一部分说的是画面，这类批评一般是说因为他看上去像 AAA 所以占了其他 Indie game 的名额，这种说法简直就是现在 AAA Games “mistake spectacle as quality” 的对偶，我感觉是没啥道理的。一个更值得讨论的话题是关于资金的问题。10M 的 Budget 对很多 Indie studio 而言确实是天文数字，很多网民也是捕风捉影推断这是因为 <a href=\"https://www.reddit.com/r/IndieDev/comments/1j2wpg5/how_did_sandfall_interactive_clair_obscur/\">导演 Guillaume Broche 在拼爹</a>，这是很多批评的来源，但是也有说是发行商 Kepler 靠本事赚来的：<a href=\"https://www.reuters.com/technology/gaming-company-kepler-raises-120-mln-chinas-netease-2021-09-28/\">Gaming company Kepler raises $120 mln from China’s NetEase</a><sub>这下第一个拿 GotY 的中国游戏了</sub>。</p>\n<p>但是从另一个角度，如果从技术上定义，Larian Studios 也是 Indie，BG3 花了 100M 呢。所以最终这类讨论都会落到 E33 “像不像”一个 indie-game。从选材角度，像，从执行角度，那完全不像。Indie 这个词可能现在已经失去有效的内涵了。</p>\n<p>业界的 Indie-game 奖项可能需要重新考虑自己的目的：是给予某个特定的游戏知名度，还是刚进入业界的某些开发者知名度呢？前者从某种角度上已经由其他各个奖项完成了，如果是后者的话，那么需要业界重新对于 Indie 给出定义，目前来看这是模糊、困难的。</p>\n<p>至于它是不是 RPG，这类批评主要来自于 KCD2 社区。这就有点不幸了，Dark Soul 也是 RPG，但它其实不关心自己是不是 RPG。那么拿了 RPG 的奖，其他 Sub-genre 的玩家自然有意见。这种二元对立非常常见了，你看古代 JRPG 是 FF，现代 JRPG 是<del>FROMSOFT</del> <del>小岛</del> 八方和 P5 呢。结果就是大家都不开心，Perceived losers 会破口大骂这个奖项是 Popularity contest.</p>\n<p>但是很神奇的是，<a href=\"https://store.steampowered.com/steamawards/2025\">Steam award</a> 作为真正的 Popularity contest，反而有更平衡的获奖结果：Silksong, DISPATCH, Hades 2, PEAK, E33 人人有份。但是 KCD2 又输了，真的很惨。</p>\n<p>虽然但是我感觉 KCD2 确实应该拿 TGA 的 Best RPG 吧。</p>\n<h2>脚注</h2>\n<div class=\"footnotes\">\n<ul>\n<li>\n<p>[1] 哈哈当时还是 Indie</p>\n</li>\n<li>\n<p>[2] <a href=\"https://youtu.be/b4KzkHpaCt0?t=1152\">Clair Obscur: Expedition 33 | Dev Interview | Sponsored By Kepler Interactive &amp; Sandfall Interactive</a></p>\n</li>\n<li>\n<p>[3] <a href=\"https://www.gamesradar.com/games/rpg/clair-obscur-expedition-33-lead-underestimated-how-many-players-would-do-all-the-side-content-regrets-disappointing-people-that-wanted-a-challenging-end-boss/\">Clair Obscur Expedition 33 lead “underestimated” how many players would do all the side content, regrets disappointing “people that wanted a challenging end boss”</a></p>\n</li>\n<li>\n<p>[4] <a href=\"https://www.bbc.com/news/articles/c078j5gd71ro\">Clair Obscur: How a passion project became 2025’s most talked-about game</a></p>\n</li>\n<li>\n<p>[5] <a href=\"https://www.expedition33.com/post/composing-the-music\">Lorien Testard | Composing the Music of Expedition 33</a></p>\n</li>\n</ul>\n</div>","plain":"我感觉 E33 成为了一个少见的可以无条件给别人推荐的游戏。作为一个 Outer Wilds 吹，卖 OW 安利的经验是安利游戏成功率很低。电子游戏的体裁众多，玩家自然各自有自己喜欢的内容。然而 E33 做到的了一件非常困难的事情：结合了数个不同类型游戏的较为核心的机制，并且执行极为出色，在音乐、美术、叙事等各个方面都可圈可点。这让我相信几乎所有玩家都可以在这个游戏里找到享受的部分。\n本文简单讨论一下我自己在 60h 游戏过程中的感想。本文基本没有 Spoiler。\n\n音乐\n这个游戏的音乐是我觉得它最出彩的部分，并不是说其他部分不NB。E33 的 OST 里几乎每一首歌拿出来单独都可以单曲循环很久，每一首曲子都和游戏其他部分完美结合，无论是战斗过程、当下的叙事、角色的情绪表现等等。整个 OST 的 154 首 (8h) 都保持了这种高水平，甚至到了一种让人难以理解的地步。\n看看我玩过的之前的 Indie game 中的 NB OST: C418 的 Minecraft[1], Andrew Prahlow 的 OW, Disasterpeace 的 FEZ 和 HLD, Lifeformed 的 TUNIC，这些都是优秀的游戏 OST，但是通常共享的模式是 Motif 的反复演绎。其中的例外是 C418 在 Minecraft: Volume Alpha 中表现出了多种不同的作曲风格和用器，但是还是风格集中在营造一种孤单、怀旧的情绪上，主要用钢琴。Lorien Testard (and Alice Duport-Percier) 在 E33 OST 中展现出了更多不同的音乐风格，以对应游戏过程中各个片段叙事的情绪。OST 中很大一部分是交响乐 + 人声，但是也有其他各种完全迥然不同的曲子，在听了三小时的钢琴之后忽然被游戏在脸上甩了一首 Electro funk，是一个很独特的体验。很自然也有很多玩家在游戏过程中被音乐 Stunlock，甚至在标题界面，还好这是一个回合制 RPG。\n传奇的一点是，Lorien Testard 是主创团队在一个（现在已经🈚了的）法语论坛上找到的[2,4]，双方都只上了一次这个网站，只发了一个帖，结果最终就产生了这个 OST。在此之前，Lorien Testard 是一个吉他老师[5]，在五年的开发时间内，平均每两周就能产出一首曲子最终用到了游戏里。现在我对法国一般通过吉他老师的印象就是他们可以随手掏出来一首 Alicia。\n然而我不懂音乐，所以总之就是：音乐很好听。考虑到这是半个音乐游戏，这已经比绝大多数音乐游戏要厉害了（？）。希望我能够安利更多其他懂音乐的群友网友玩这个游戏，然后锐评，供我学习。非常欢迎大家先来听一听 OST，Sandfall 在他们 YouTube 上直接传了整个 OST，比 Bandcamp 和 Steam 上能买到的还要全。B 站和油管各地也有大量的 E33 音乐的分析。\n\n战斗系统\n这是一个下落式音游。有根据时机按键，有好听音乐，有下落的敌人，所以是下落式音游。\n即使不把这个当作一个下落式音游，从战斗系统角度而言，这个游戏其实更接近一个类魂的游戏。玩家需要像类魂游戏一样“下载”敌人的动作，在游戏后期闪避和格挡几乎是必须的。并且连快慢刀都学来了。传统 Turn-based RPG 的战斗中重点是战术、战略，即战斗前的装备管理，战斗时的资源管理（动作点，属性，HP），但是在敌人环节就几乎完全脱离玩家控制。E33 把格挡系统放进来，再加上玩家技能的 QTE，构成了一个极为动态的战斗系统。最终给玩家带来多巴胺的，也一般不是通过解谜一样的精度推过了一个 Boss，而是战斗过程中按到了所有的格挡。难度设置上，通过伤害膨胀来控制玩家行为、动态难度平衡（i.e. 刷级用时间换操作），也更像一个类魂游戏。\n事实上，选择符文的页面 UI 非常糟糕，但我都没有听到像当时 Death Stranding 开喷的讨论，说明可能真的无人关心（\n\n故事和叙事\n根据 The Internet™️ 上的讨论，本游戏的故事对许多玩家而言也是一大亮点。这是首个在 OW 之外我看到有人说想要 “Forget everything and play it again” 的。玩家群体经常讲的另一个玩笑话是 Sandfall should pay for my therpy，可见这个故事的动人程度。\n然而为了不剧透，这里只讨论序章 [录像，无剧透]，也就基本就是预告片和 Steam 商品页的内容。即便如此，E33 在序章中两小时内也基本完全完成了游戏情绪基调的营造，并且勾起玩家的兴趣。事实上，游戏开始的第一段对话基本就很有意思：\nMaelle: If you’re going to give someone flowers, you should probably do it BEFORE they wither and die.\nGustave: What, the flower? Or Sophie?\nMaelle: Ooh, dark. Sophie would approve.\n\n游戏整体剧情总体就是这种幽默风趣，但又伤感（或者说别扭）的情绪下逐渐展开的。整个序章的精致程度，以及在叙事角度上的有效程度都是很出色的，上一次见到这种还是 紫社的 アオイトリ。我感觉原因之一是音乐，原因之二是美术和画面：现代游戏引擎的 Photorealistic 渲染最强的一个优势就是在演出和叙事上；原因之三就是设定是有趣的。这是 Steam 商店页简介第一段：\nOnce a year, the Paintress wakes and paints upon her monolith. Paints her cursed number. And everyone past that age turns to smoke and fades away. Year by year, that number ticks down and more of us are erased. Tomorrow she’ll wake and paint “33.” And tomorrow we depart on our final mission - Destroy the Paintress, so she can never paint death again.\nWe are Expedition 33.\n\n弑神这个设定自然是 JRPG 人狂喜了。但是更重要的问题是，Paintress 的力量来源是哪里？世界的本质是什么？玩家处于远征队 33 视角，那么其他的远征队的故事是什么？这是这个游戏剧情的 Hook，而不是一个单纯的英雄谭。\n当然，人物对白还有演出节奏是最关键的，我感觉我的水平难以描述 E33 的文字中的魔法，上面提到的游戏中的第一段对白是一个例子，更多的可以看序章的录像。另一个很传奇的一件事情是，游戏的主笔 Jennifer Svedberg-Yen 最开始是主创在 Reddit 上找到应聘声优的人[4]…这真的是很神奇的一个游戏。\n整个游戏主线的剧情和叙事在众多转折之中，一直保持着这种高水准。想通过游戏体验一个悲剧的群像故事的群友有福了，而且这游戏还有个 Story mode 难度供小手残玩家（比如我）体验。\n\n玩家引导及内容布置\n刚刚提到了游戏主要靠伤害数做 Gatekeeping 从而实现玩家引导。游戏大概可以分为两半，前一半是一个线性叙事结构，对应一个线性的关卡设计，后一半转换成开放世界，世界地图会变得开放。但是前面说的这种引导方式放到开放世界中真的完全不工作，因为基本没办法控制在特定一个场景的玩家的等级有多少。E33 做了一个妥协是标记了每个场景的推荐最低等级，如果没有达到会给玩家显示一个红色的危险，但是另一个方向就没法保证了。最终 Boss 的预定等级设计是在地图打开之后玩家立刻去打最终 Boss[3]，做了一些支线之后就非常明显 Over level 了。即使在支线之中，也很难知道应该按什么顺序，一不小心就到了 One-shot 一个 Boss 的地步，那所有的演出都失效了，变成看速通一样（\n其他类型的 RPG 其实也有类似的问题，但是开放世界 RPG 会有意不让数值膨胀变得这么严重，以及让敌人也随玩家的等级（或者游戏进度）变强。Sandfall 不少主创的老东家阿育是一个在 Sandbox AVG / RPG 里 不思进取 摸爬滚打多年的选手，感觉真可以抄抄刺客信条（笑）。\n\nTGA Drama and “indie games”\nFinally, let’s talk about the 🐘 in the 🏠. 在 TGA 横扫了九个奖项之后，招了很多恨。其中也许可能可以讨论一下的 Argument 大概可以归为如下两类：\n- 这不够 Indie\n- 这不是 RPG\n关于 Indie 的批评，有一部分说的是画面，这类批评一般是说因为他看上去像 AAA 所以占了其他 Indie game 的名额，这种说法简直就是现在 AAA Games “mistake spectacle as quality” 的对偶，我感觉是没啥道理的。一个更值得讨论的话题是关于资金的问题。10M 的 Budget 对很多 Indie studio 而言确实是天文数字，很多网民也是捕风捉影推断这是因为 导演 Guillaume Broche 在拼爹，这是很多批评的来源，但是也有说是发行商 Kepler 靠本事赚来的：Gaming company Kepler raises $120 mln from China’s NetEase这下第一个拿 GotY 的中国游戏了。\n但是从另一个角度，如果从技术上定义，Larian Studios 也是 Indie，BG3 花了 100M 呢。所以最终这类讨论都会落到 E33 “像不像”一个 indie-game。从选材角度，像，从执行角度，那完全不像。Indie 这个词可能现在已经失去有效的内涵了。\n业界的 Indie-game 奖项可能需要重新考虑自己的目的：是给予某个特定的游戏知名度，还是刚进入业界的某些开发者知名度呢？前者从某种角度上已经由其他各个奖项完成了，如果是后者的话，那么需要业界重新对于 Indie 给出定义，目前来看这是模糊、困难的。\n至于它是不是 RPG，这类批评主要来自于 KCD2 社区。这就有点不幸了，Dark Soul 也是 RPG，但它其实不关心自己是不是 RPG。那么拿了 RPG 的奖，其他 Sub-genre 的玩家自然有意见。这种二元对立非常常见了，你看古代 JRPG 是 FF，现代 JRPG 是FROMSOFT 小岛 八方和 P5 呢。结果就是大家都不开心，Perceived losers 会破口大骂这个奖项是 Popularity contest.\n但是很神奇的是，Steam award 作为真正的 Popularity contest，反而有更平衡的获奖结果：Silksong, DISPATCH, Hades 2, PEAK, E33 人人有份。但是 KCD2 又输了，真的很惨。\n虽然但是我感觉 KCD2 确实应该拿 TGA 的 Best RPG 吧。\n\n脚注\n- [1] 哈哈当时还是 Indie\n\n- [2] Clair Obscur: Expedition 33 | Dev Interview | Sponsored By Kepler Interactive & Sandfall Interactive\n\n- [3] Clair Obscur Expedition 33 lead “underestimated” how many players would do all the side content, regrets disappointing “people that wanted a challenging end boss”\n\n- [4] Clair Obscur: How a passion project became 2025’s most talked-about game\n\n- [5] Lorien Testard | Composing the Music of Expedition 33\n\n"},{"metadata":{"id":"qreadwritelock-race","lang":"en-US","title":"A race condition in QReadWriteLock","tags":["开发"],"publish_time":"2026-01-03T04:26:28+08:00","update_time":"2026-01-03T04:32:53+08:00","title_outline":{"groups":[{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761}],"text":"A","hadv":761,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"race","hadv":2284,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"condition","hadv":5042,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"in","hadv":1055,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"Q","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]],["M 560 230C 614 230 667 216 707 193L 695 164C 667 177 645 180 616 180C 520 180 461 109 475 -5L 313 -5L 313 3C 313 125 392 230 560 230Z",[-0.487,0.331]]],"bbox":{"top":-767,"bottom":230,"left":43,"right":752},"hadv":795},{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"W","components":[["M 9 -713L 161 -698L 196 -698L 347 -713L 347 -747L 9 -747Z",[-0.785,0.009]],["M 284 2L 377 2L 550 -576L 554 -590L 534 -590L 713 2L 806 2L 1030 -747L 972 -747L 811 -157L 808 -140L 826 -140L 655 -747L 553 -747L 385 -160L 381 -145L 399 -145L 244 -747L 63 -747Z",[-0.209,0.055]],["M 446 -713L 572 -698L 637 -698L 774 -713L 774 -747L 446 -747Z",[-0.673,0.043]],["M 867 -713L 973 -698L 1002 -698L 1108 -713L 1108 -747L 867 -747Z",[-0.544,0.089]]],"bbox":{"top":-747,"bottom":2,"left":9,"right":1108},"hadv":1111},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"L","components":[["M 41 -0L 218 -0L 219 -50L 202 -50L 42 -34Z",[0.751,0.04]],["M 41 -713L 202 -698L 240 -698L 403 -713L 403 -747L 41 -747Z",[-0.878,0.008]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -346L 303 -411C 303 -514 303 -632 306 -747L 130 -747C 133 -631 133 -513 133 -395L 133 -324C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 619 -0L 617 -224L 562 -224L 503 -2L 588 -39L 219 -39Z",[0.547,0.208]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":619},"hadv":651},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673}],"text":"QReadWriteLock","hadv":8944,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>A few weeks ago <a href=\"https://github.com/shankerwangmiao\">@shankerwangmiao</a> brought me on a magical journey to debug <a href=\"https://qt-project.atlassian.net/browse/QTBUG-142321\">a race condition in <code>QReadWriteLock</code></a>. The <a href=\"https://codereview.qt-project.org/c/qt/qtbase/+/696526\">fix</a> will be live in the v6.11.0 release. Although @shankerwangmiao has done most of the actual debugging and fixing, I got the right to brag about it in a blog post. So here is a post about how to write a reader-writer lock, and the cursed nature of weak memory ordering.</p>\n<h2>The buggy behavior</h2>\n<p>Sometimes, <a href=\"https://codereview.qt-project.org/c/qt/qtbase/+/696526/12/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp#607\">a heavily contended <code>QReadWriteLock</code></a> fails to guarantee the wanted semantics of exclusive access. A reader might find itself running concurrently with a writer, and two writers might run together as well.</p>\n<p>When looking inside the state of <code>QReadWriteLock</code>, it seems that sometimes the internal state of the lock is corrupted and inconsistent. It sometimes shows that there are negative numbers of readers or writers. That can explain why the lock fails: it does not realize that there are some live accesses.</p>\n<p>Curiously, the bug only happens on ISAs with weaker memory ordering than TSO, such as AArch64. On these architectures, semantics of TSO can mostly be recovered by annotating everything with acquire and release ordering. So it hints that the bug is caused by insufficient strength of some memory accesses’ ordering, which results in a race condition that loses some updates to the internal state of the lock.</p>\n<h2>The anatomy of a reader-writer lock</h2>\n<p>In contrast to the ubiquitous mutex lock (or <code>unique_lock</code> for the C++ folks out there), a reader-writer lock allows two levels of concurrency control: unique access for writers, and shared readonly access for readers. <a href=\"https://doc.qt.io/qt-6/qreadwritelock.html\"><code>QReadWriteLock</code></a> is Qt’s cross-platform implementation of the reader-writer lock. Other common implementations on various platforms are:</p>\n<ul>\n<li><a href=\"https://doc.rust-lang.org/std/sync/struct.RwLock.html\"><code>RwLock</code></a> in Rust</li>\n<li><a href=\"https://en.cppreference.com/w/cpp/thread/shared_lock.html\"><code>std::shared_lock</code></a> in C++</li>\n<li><a href=\"https://man7.org/linux/man-pages/man3/pthread_rwlock_trywrlock.3p.html\"><code>pthread_rwlock_*</code></a> on POSIX w/ pthread.</li>\n</ul>\n<p>The implementation of <code>QReadWriteLock</code> is quite interesting. It primarily depends on the Qt’s platform-independent encapsulation of the unique mutex and condvar. To speed up reader-heavy workloads a <code>QReadWriteLock</code> has two states:</p>\n<ul>\n<li>A “thin” state, where there are no waiting threads. In this state, the only data a lock needs to keep track of is the number of concurrent accessing threads, and their access types. <a href=\"https://github.com/qt/qtbase/blob/4eb4462b14cc8065e098412d9dd8a1ade90897e2/src/corelib/thread/qreadwritelock.cpp#L19-L29\"><code>QReadWriteLock</code> encodes it as a <code>size_t</code></a>:\n<ul>\n<li><code>0x0</code> represents no live access.</li>\n<li><code>0x2</code> represents a live exclusive access.</li>\n<li><code>0x1 | (num_access &lt;&lt; 4)</code> represents some shared exclusive accesses.</li>\n</ul>\n</li>\n<li>A “heavy” state, where there are waiting threads. Since the waiting is implemented with underlying condvars, another <code>QReadWriteLockPrivate</code> struct is allocated to keep track of all the extra data, and <code>QReadWriteLock</code> stores its pointer.</li>\n</ul>\n<p>With some <code>reinterpret_cast</code> magic, the QReadWriteLock is basically a <code>size_t</code> integer in both cases <sup>[1]</sup>. When the lock remains in the “thin” state, which is on the fast path, all locking and unlocking is done through a simple atomic CAS operation, directly operating on the integral state <sup>[2]</sup>. Whenever the lock needs to transfer into / out of the “heavy” state, an actual mutex is used to protect the atomicity during the modification of the state of the lock itself. When the bug happens, the inconsistent state can be found in the “heavy” state.</p>\n<p>In essence, <code>QReadWriteLockPrivate</code> struct stores the following data:</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#268bd2;\">struct </span><span style=\"color:#b58900;\">QReadWriteLockPrivate_is_basically </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">size_t</span><span style=\"color:#839496;\"> num_reader, num_writer, num_reader_waiting, num_writer_waiting;\n</span><span style=\"color:#839496;\">  mutex </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">actual_mutex;\n</span><span style=\"color:#839496;\">  condvar </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">read_waiting, </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">write_waiting;\n</span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>The <code>actual_mutex</code> protects the lock state, i.e. gets locked whenever some thread tries to read or write the <code>QReadWriteLockPrivate</code> object. <strong>It does not get held by the process which held the macroscopic <code>QReadWriteLock</code></strong>, which allows the lock to transfer back into a “thin” state at the earliest possible moment, which is very neat and smart.</p>\n<p>Therefore, the pseudo-code for <a href=\"https://github.com/qt/qtbase/blob/4eb4462b14cc8065e098412d9dd8a1ade90897e2/src/corelib/thread/qreadwritelock.cpp#L192\">locking <code>QReadWriteLock</code></a> is:</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#268bd2;\">void </span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">QReadWriteLock </span><span style=\"color:#268bd2;\">lock</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">bool exclusive</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">while</span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">true</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    cur_state </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> lock.</span><span style=\"color:#268bd2;\">state</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">lock is thin </span><span style=\"color:#859900;\">and</span><span style=\"color:#839496;\"> compatible with requested exclusiveness</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      new_state </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">lock_thin_incr</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cur_state, exclusiveness</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">lock.</span><span style=\"color:#268bd2;\">state</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">cas</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cur_state, new_state</span><span style=\"color:#657b83;\">)) </span><span style=\"color:#859900;\">return</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">lock is thin</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#586e75;\">// Needs to transfer into &quot;heavy&quot; state, allocate new lock and set\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#586e75;\">// inner state based on the current &quot;thin&quot; state\n</span><span style=\"color:#839496;\">      QReadWriteLockPrivate </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">heavy </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">alloc_heavy_lock</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cur_state</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(!</span><span style=\"color:#839496;\">lock.</span><span style=\"color:#268bd2;\">state</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">cas</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cur_state, </span><span style=\"color:#859900;\">reinterpret_cast</span><span style=\"color:#657b83;\">&lt;</span><span style=\"color:#859900;\">size_t</span><span style=\"color:#657b83;\">&gt;(</span><span style=\"color:#839496;\">heavy</span><span style=\"color:#657b83;\">))) {\n</span><span style=\"color:#839496;\">        </span><span style=\"color:#586e75;\">// &quot;thin&quot; state changed, try again\n</span><span style=\"color:#839496;\">        </span><span style=\"color:#b58900;\">dealloc_heavy_lock</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">heavy</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">    \n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// Now lock is guaranteed to be &quot;heavy&quot;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// Naively (but incorrectly), we would do:\n</span><span style=\"color:#839496;\">    QReadWriteLock </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">heavy </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">reinterpret_cast</span><span style=\"color:#657b83;\">&lt;</span><span style=\"color:#839496;\">QReadWriteLock </span><span style=\"color:#859900;\">*</span><span style=\"color:#657b83;\">&gt;(</span><span style=\"color:#839496;\">cur_state</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    lock_guard guard </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> heavy-&gt;</span><span style=\"color:#268bd2;\">actual_mutex</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    heavy-&gt;</span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">exclusive</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>The unlocking side is analogous.</p>\n<p>However, the above implementation is incomplete. It turns out, there are <em>two</em> more obvious problems with the above pseudo-code’s handling of the “heavy” state.</p>\n<h2>Looking into the pointer</h2>\n<p>In order to lock the <code>actual_mutex</code>, we have to look into the pointer of a <code>QReadWriteLockPrivate</code>. Although all mainstream CPU architectures (with the notable exception of Alpha) guarantee dependency ordering, C++ standard explicitly allows compilers to reorder memory accesses even though they carry dependencies.</p>\n<p>The weakest order that can preserve dependency ordering is to use the infamous <code>std::memory_order_consume</code> to load the pointer. cppreference.com has a <a href=\"https://en.cppreference.com/w/cpp/atomic/memory_order.html#Release-Consume_ordering\">nice summary</a> of the caveats of <code>std:memory_order</code> with this kind of pointer-mediated communication. Since <code>std::memory_order_consume</code> is deprecated, we will use <code>std::memory_order_acquire</code> to reload the pointer, and guarantee that we look into the pointer after we read the pointer itself.</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#586e75;\">// Better\n</span><span style=\"color:#839496;\">cur_state </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> lock.</span><span style=\"color:#268bd2;\">state</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_acquire</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cur_state is thin</span><span style=\"color:#657b83;\">) </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">QReadWriteLock </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">heavy </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">reinterpret_cast</span><span style=\"color:#657b83;\">&lt;</span><span style=\"color:#839496;\">QReadWriteLock </span><span style=\"color:#859900;\">*</span><span style=\"color:#657b83;\">&gt;(</span><span style=\"color:#839496;\">cur_state</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">lock_guard guard </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> heavy-&gt;</span><span style=\"color:#268bd2;\">actual_mutex</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">heavy-&gt;</span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">exclusive</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">// ... but some how still wrong\n</span></code></pre>\n</div>\n<h2>Deallocating the lock under our feet</h2>\n<p>Since the “heavy” state is on the slow path, what’s actually happening is that we first read the <code>QReadWriteLock</code> state, check if it’s “heavy”, and then lock its <code>actual_mutex</code>. During this time, the state of the lock may have changed, potentially caused by another thread allocating / deallocating this “heavy” lock.</p>\n<p>As such, the handling of the “heavy” state is <a href=\"https://github.com/qt/qtbase/blob/4eb4462b14cc8065e098412d9dd8a1ade90897e2/src/corelib/thread/qreadwritelock.cpp#L236-L247\">implemented more carefully</a>. Instead of the naive code above, additional checks are added to make sure the lock is still in the “heavy” state, and more importantly, the same “heavy” lock object after we lock it:</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#586e75;\">// Even better\n</span><span style=\"color:#839496;\">cur_state </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> lock.</span><span style=\"color:#268bd2;\">state</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_acquire</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">; </span><span style=\"color:#586e75;\">// (1)\n</span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cur_state is thin</span><span style=\"color:#657b83;\">) </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">QReadWriteLock </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">heavy </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">reinterpret_cast</span><span style=\"color:#657b83;\">&lt;</span><span style=\"color:#839496;\">QReadWriteLock </span><span style=\"color:#859900;\">*</span><span style=\"color:#657b83;\">&gt;(</span><span style=\"color:#839496;\">cur_state</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">lock_guard guard </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> heavy-&gt;</span><span style=\"color:#268bd2;\">actual_mutex</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">lock.</span><span style=\"color:#268bd2;\">state</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">std::memory_order_relaxed</span><span style=\"color:#657b83;\">) !=</span><span style=\"color:#839496;\"> cur_state</span><span style=\"color:#657b83;\">) { </span><span style=\"color:#586e75;\">// (2)\n</span><span style=\"color:#839496;\">  guard.</span><span style=\"color:#b58900;\">unlock</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">; </span><span style=\"color:#586e75;\">// Or let RAII do its thing\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">heavy-&gt;</span><span style=\"color:#b58900;\">lock</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">exclusive</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">; </span><span style=\"color:#586e75;\">// (3)\n</span></code></pre>\n</div>\n<p>We’ve now arrived at the implementation in v6.10, the version where we encountered the bug.</p>\n<h2>The race</h2>\n<p>… Unfortunately, there is still a hidden race condition here. To see why, we have to first look into how are the “heavy” locks allocated and deallocated.</p>\n<p>Qt keeps <a href=\"https://github.com/qt/qtbase/blob/4eb4462b14cc8065e098412d9dd8a1ade90897e2/src/corelib/thread/qreadwritelock.cpp#L561-L562\">a pool of pre-allocated “heavy” locks</a> to speed up the allocation. So “heavy” locks can be reused, or even placed back into the same <code>QReadWriteLock</code>. However, even if we don’t use the pool, there’s still a possibility that the libc allocator may return the same address for a newly allocated “heavy” lock.</p>\n<p>Now it seems that it won’t be a problem, since the same “heavy” lock always corresponds to the same <code>actual_mutex</code>, so we retain exclusive access. That would be the case if we’re running on a TSO architecture. Unfortunately, on a WMO architecture, the branch condition may get delayed until after we modify the content of the “heavy” lock (i.e. <code>heavy-&gt;lock(exclusive);</code>). So the actual sequence of events may be:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>→</mo><mo stretchy=\"false\">(</mo><mn>3</mn><mo stretchy=\"false\">)</mo><mo>→</mo><mo stretchy=\"false\">(</mo><mn>2</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\n(1) \\rightarrow (3) \\rightarrow (2)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\">3</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\">2</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>And between (1) and (2), other threads may have deallocated and reallocated the same “heavy” lock object, and placing it back into the same <code>QReadWriteLock</code> we are trying to lock.</p>\n<p>… And the <code>alloc_heavy_lock</code> procedure assumes exclusive access to the <code>QReadWriteLockPrivate</code> object (with good reason), and <a href=\"https://github.com/qt/qtbase/blob/4eb4462b14cc8065e098412d9dd8a1ade90897e2/src/corelib/thread/qreadwritelock.cpp#L213-L226\">did not lock <code>actual_mutex</code> when initializing the content of <code>QReadWriteLockPrivate</code></a>, so the modification by one side of the race can be lost. We finally arrived at the race condition:</p>\n<pre><code>Thread A: (1) load heavy lock pointer\nThread B: dealloc heavy lock, place back into pool\nThread A: lock actual_mutex\n=== Race starts\nThread C: alloc heavy lock, initialize data\n---\nThread A: (3) modify heavy lock data\n=== Race ends\nThread C: place heavy lock back into QReadWriteLock\nThread A: (2) check heavy lock pointer didn't change\n</code></pre>\n<h2>The fix</h2>\n<p>There are two possible fixes. The patch went for the lighter one, which is to simply change the relaxed load in (2) to an acquire load. This is sufficient to order (3) after the initialization of the “heavy” lock in the allocating thread.</p>\n<p>Alternatively, we can force the allocating thread to lock <code>actual_mutex</code> during the entire initialization and CAS operation (the placement of the “heavy” lock into <code>QReadWriteLock</code>). Therefore holding <code>actual_mutex</code> is sufficient to guarantee that the initialization has completed and is visible.</p>\n<hr />\n<div class=\"footnotes\">\n<ul>\n<li>[1]: To make sure the two states don’t get confused, <code>alignof(QReadWriteLockPrivate) &gt;= 4</code></li>\n<li>[2]: CAS suffers from the ABA problem, but we’re fine with it <strong>if the lock remains “thin” </strong><del>subtle foreshadowing</del>. In some sense, the result of each kind of state change only depends on the previous state (or “pure”), so as long as the compare and swap is atomic, the state is consistent.</li>\n</ul>\n</div>","plain":"A few weeks ago @shankerwangmiao brought me on a magical journey to debug a race condition in QReadWriteLock. The fix will be live in the v6.11.0 release. Although @shankerwangmiao has done most of the actual debugging and fixing, I got the right to brag about it in a blog post. So here is a post about how to write a reader-writer lock, and the cursed nature of weak memory ordering.\n\nThe buggy behavior\nSometimes, a heavily contended QReadWriteLock fails to guarantee the wanted semantics of exclusive access. A reader might find itself running concurrently with a writer, and two writers might run together as well.\nWhen looking inside the state of QReadWriteLock, it seems that sometimes the internal state of the lock is corrupted and inconsistent. It sometimes shows that there are negative numbers of readers or writers. That can explain why the lock fails: it does not realize that there are some live accesses.\nCuriously, the bug only happens on ISAs with weaker memory ordering than TSO, such as AArch64. On these architectures, semantics of TSO can mostly be recovered by annotating everything with acquire and release ordering. So it hints that the bug is caused by insufficient strength of some memory accesses’ ordering, which results in a race condition that loses some updates to the internal state of the lock.\n\nThe anatomy of a reader-writer lock\nIn contrast to the ubiquitous mutex lock (or unique_lock for the C++ folks out there), a reader-writer lock allows two levels of concurrency control: unique access for writers, and shared readonly access for readers. QReadWriteLock is Qt’s cross-platform implementation of the reader-writer lock. Other common implementations on various platforms are:\n- RwLock in Rust\n- std::shared_lock in C++\n- pthread_rwlock_* on POSIX w/ pthread.\nThe implementation of QReadWriteLock is quite interesting. It primarily depends on the Qt’s platform-independent encapsulation of the unique mutex and condvar. To speed up reader-heavy workloads a QReadWriteLock has two states:\n- A “thin” state, where there are no waiting threads. In this state, the only data a lock needs to keep track of is the number of concurrent accessing threads, and their access types. QReadWriteLock encodes it as a size_t:- 0x0 represents no live access.\n- 0x2 represents a live exclusive access.\n- 0x1 | (num_access << 4) represents some shared exclusive accesses.\n\n- A “heavy” state, where there are waiting threads. Since the waiting is implemented with underlying condvars, another QReadWriteLockPrivate struct is allocated to keep track of all the extra data, and QReadWriteLock stores its pointer.\nWith some reinterpret_cast magic, the QReadWriteLock is basically a size_t integer in both cases [1]. When the lock remains in the “thin” state, which is on the fast path, all locking and unlocking is done through a simple atomic CAS operation, directly operating on the integral state [2]. Whenever the lock needs to transfer into / out of the “heavy” state, an actual mutex is used to protect the atomicity during the modification of the state of the lock itself. When the bug happens, the inconsistent state can be found in the “heavy” state.\nIn essence, QReadWriteLockPrivate struct stores the following data:\nstruct QReadWriteLockPrivate_is_basically {\n  size_t num_reader, num_writer, num_reader_waiting, num_writer_waiting;\n  mutex *actual_mutex;\n  condvar *read_waiting, *write_waiting;\n};\n\nThe actual_mutex protects the lock state, i.e. gets locked whenever some thread tries to read or write the QReadWriteLockPrivate object. It does not get held by the process which held the macroscopic QReadWriteLock, which allows the lock to transfer back into a “thin” state at the earliest possible moment, which is very neat and smart.\nTherefore, the pseudo-code for locking QReadWriteLock is:\nvoid lock(QReadWriteLock lock, bool exclusive) {\n  while(true) {\n    cur_state = lock.state.load(relaxed);\n    if (lock is thin and compatible with requested exclusiveness) {\n      new_state = lock_thin_incr(cur_state, exclusiveness);\n      if (lock.state.cas(cur_state, new_state)) return;\n      continue;\n    }\n\n    if (lock is thin) {\n      // Needs to transfer into \"heavy\" state, allocate new lock and set\n      // inner state based on the current \"thin\" state\n      QReadWriteLockPrivate *heavy = alloc_heavy_lock(cur_state);\n      if (!lock.state.cas(cur_state, reinterpret_cast<size_t>(heavy))) {\n        // \"thin\" state changed, try again\n        dealloc_heavy_lock(heavy);\n      }\n      continue;\n    }\n    \n    // Now lock is guaranteed to be \"heavy\"\n\n    // Naively (but incorrectly), we would do:\n    QReadWriteLock *heavy = reinterpret_cast<QReadWriteLock *>(cur_state);\n    lock_guard guard = heavy->actual_mutex.lock();\n    heavy->lock(exclusive);\n  }\n}\n\nThe unlocking side is analogous.\nHowever, the above implementation is incomplete. It turns out, there are two more obvious problems with the above pseudo-code’s handling of the “heavy” state.\n\nLooking into the pointer\nIn order to lock the actual_mutex, we have to look into the pointer of a QReadWriteLockPrivate. Although all mainstream CPU architectures (with the notable exception of Alpha) guarantee dependency ordering, C++ standard explicitly allows compilers to reorder memory accesses even though they carry dependencies.\nThe weakest order that can preserve dependency ordering is to use the infamous std::memory_order_consume to load the pointer. cppreference.com has a nice summary of the caveats of std:memory_order with this kind of pointer-mediated communication. Since std::memory_order_consume is deprecated, we will use std::memory_order_acquire to reload the pointer, and guarantee that we look into the pointer after we read the pointer itself.\n// Better\ncur_state = lock.state.load(std::memory_order_acquire);\nif (cur_state is thin) continue;\n\nQReadWriteLock *heavy = reinterpret_cast<QReadWriteLock *>(cur_state);\nlock_guard guard = heavy->actual_mutex.lock();\nheavy->lock(exclusive);\n\n// ... but some how still wrong\n\n\nDeallocating the lock under our feet\nSince the “heavy” state is on the slow path, what’s actually happening is that we first read the QReadWriteLock state, check if it’s “heavy”, and then lock its actual_mutex. During this time, the state of the lock may have changed, potentially caused by another thread allocating / deallocating this “heavy” lock.\nAs such, the handling of the “heavy” state is implemented more carefully. Instead of the naive code above, additional checks are added to make sure the lock is still in the “heavy” state, and more importantly, the same “heavy” lock object after we lock it:\n// Even better\ncur_state = lock.state.load(std::memory_order_acquire); // (1)\nif (cur_state is thin) continue;\n\nQReadWriteLock *heavy = reinterpret_cast<QReadWriteLock *>(cur_state);\nlock_guard guard = heavy->actual_mutex.lock();\nif (lock.state.load(std::memory_order_relaxed) != cur_state) { // (2)\n  guard.unlock(); // Or let RAII do its thing\n  continue;\n}\nheavy->lock(exclusive); // (3)\n\nWe’ve now arrived at the implementation in v6.10, the version where we encountered the bug.\n\nThe race\n… Unfortunately, there is still a hidden race condition here. To see why, we have to first look into how are the “heavy” locks allocated and deallocated.\nQt keeps a pool of pre-allocated “heavy” locks to speed up the allocation. So “heavy” locks can be reused, or even placed back into the same QReadWriteLock. However, even if we don’t use the pool, there’s still a possibility that the libc allocator may return the same address for a newly allocated “heavy” lock.\nNow it seems that it won’t be a problem, since the same “heavy” lock always corresponds to the same actual_mutex, so we retain exclusive access. That would be the case if we’re running on a TSO architecture. Unfortunately, on a WMO architecture, the branch condition may get delayed until after we modify the content of the “heavy” lock (i.e. heavy->lock(exclusive);). So the actual sequence of events may be:\n\n(1) \\rightarrow (3) \\rightarrow (2)\n\nAnd between (1) and (2), other threads may have deallocated and reallocated the same “heavy” lock object, and placing it back into the same QReadWriteLock we are trying to lock.\n… And the alloc_heavy_lock procedure assumes exclusive access to the QReadWriteLockPrivate object (with good reason), and did not lock actual_mutex when initializing the content of QReadWriteLockPrivate, so the modification by one side of the race can be lost. We finally arrived at the race condition:\nThread A: (1) load heavy lock pointer\nThread B: dealloc heavy lock, place back into pool\nThread A: lock actual_mutex\n=== Race starts\nThread C: alloc heavy lock, initialize data\n---\nThread A: (3) modify heavy lock data\n=== Race ends\nThread C: place heavy lock back into QReadWriteLock\nThread A: (2) check heavy lock pointer didn't change\n\n\nThe fix\nThere are two possible fixes. The patch went for the lighter one, which is to simply change the relaxed load in (2) to an acquire load. This is sufficient to order (3) after the initialization of the “heavy” lock in the allocating thread.\nAlternatively, we can force the allocating thread to lock actual_mutex during the entire initialization and CAS operation (the placement of the “heavy” lock into QReadWriteLock). Therefore holding actual_mutex is sufficient to guarantee that the initialization has completed and is visible.\n---\n- [1]: To make sure the two states don’t get confused, alignof(QReadWriteLockPrivate) >= 4\n- [2]: CAS suffers from the ABA problem, but we’re fine with it if the lock remains “thin” subtle foreshadowing. In some sense, the result of each kind of state change only depends on the previous state (or “pure”), so as long as the compare and swap is atomic, the state is consistent.\n"},{"metadata":{"id":"hello-2026","lang":"zh-CN","title":"2026","tags":["扯淡"],"publish_time":"2026-01-01T23:22:47+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"6","components":[["M 317 17C 477 17 573 -90 573 -231C 573 -364 501 -457 370 -457C 290 -457 224 -424 179 -361L 170 -361L 190 -347C 225 -387 266 -400 307 -400C 378 -400 415 -337 415 -216C 415 -76 373 -18 318 -18C 250 -18 204 -109 204 -323C 204 -529 318 -689 533 -739L 528 -764C 238 -738 40 -535 40 -289C 40 -96 148 17 317 17Z",[-0.032,0.21]]],"bbox":{"top":-764,"bottom":17,"left":40,"right":573},"hadv":613}],"text":"2026","hadv":2451,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/2026-cat.png"},"html":"<p>又是一年翻篇。过去一年相比之前写了很多很多博客，所以一年到头的这一篇文章，莫名觉得重要程度轻了很多，缺少了长长达几天时间的心理准备，感觉也并没什么好写的。然而耐着羞耻心读着过去几年的总结，真正打开编辑器准备开始写的时候，却意识到时间的流逝从未远离，只是我变得更加习惯了而已。作为马上要正式开始奔三的人，2026 年度年的时刻，只是在<a href=\"https://t.me/MeowMiniMeow\">群里</a>发了张猫猫表情，然后继续<a href=\"https://github.com/CircuitCoder/kqt/commit/8c31baaba1efe69bea1155ab4bbf3a99b04ce0bf\">大战 Rustc borrowck</a>.</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/2026-cat.png\" class=\"preview\">\n  <figcaption>猫猫表情 in question</figcaption>\n</figure>\n<p>不过并不是没有可以总结的事情。这个网站去年存在这么多新的文章，就是一个让我很自豪的事情，即使和年初的时候心态不同，也算是完成了去年展望中的计划：在这里留下更多的文字。甚至在此之上，尝试了更多的东西，文章内容开始包括我喜欢的一些游戏，进行的一些工作，其他的一些爱好，有中文写成的，也有英文写成的，很多原来最后在年度总结中一句带过的事情，都已经被讲过了。从某种角度来说，这个个人网站更 “Personal” 了一些。而且对应地，其实也并不是真的没有什么好写的，有很多要写的事情，其实已经被计划成了单独的文章：最近修理的一些 Bug，进行的项目，使用 AI 的一些心得，刚玩完的 Expedition 33 和 Xenoblade 3, 等等，他们都是很令人兴奋的，等待被叙述成文字的想法和故事。</p>\n<p>为了不让这篇文章的主题变回比较假大空的状态了，于是跳过做一些简单的，似有似无的自我批评与反省。意识到对抗一切来自他人还是内心的叙事的最好方式，就是列下来可以做到的事情，然后将其完成，在这一规律的指导下，简单列一些接下来要做的有趣的事情：将 Tunaive 画完，尝试让 LLM 操作 SCAD 然后把我吃灰的 CNC 运行起来，学习写 Kernel Module 和 ESP32 上的软件。</p>\n<p>当然，还有和往年的传统一样，把屋子收拾好。这通常是让我变开心的最简单的事情。</p>\n","plain":"又是一年翻篇。过去一年相比之前写了很多很多博客，所以一年到头的这一篇文章，莫名觉得重要程度轻了很多，缺少了长长达几天时间的心理准备，感觉也并没什么好写的。然而耐着羞耻心读着过去几年的总结，真正打开编辑器准备开始写的时候，却意识到时间的流逝从未远离，只是我变得更加习惯了而已。作为马上要正式开始奔三的人，2026 年度年的时刻，只是在群里发了张猫猫表情，然后继续大战 Rustc borrowck.\n不过并不是没有可以总结的事情。这个网站去年存在这么多新的文章，就是一个让我很自豪的事情，即使和年初的时候心态不同，也算是完成了去年展望中的计划：在这里留下更多的文字。甚至在此之上，尝试了更多的东西，文章内容开始包括我喜欢的一些游戏，进行的一些工作，其他的一些爱好，有中文写成的，也有英文写成的，很多原来最后在年度总结中一句带过的事情，都已经被讲过了。从某种角度来说，这个个人网站更 “Personal” 了一些。而且对应地，其实也并不是真的没有什么好写的，有很多要写的事情，其实已经被计划成了单独的文章：最近修理的一些 Bug，进行的项目，使用 AI 的一些心得，刚玩完的 Expedition 33 和 Xenoblade 3, 等等，他们都是很令人兴奋的，等待被叙述成文字的想法和故事。\n为了不让这篇文章的主题变回比较假大空的状态了，于是跳过做一些简单的，似有似无的自我批评与反省。意识到对抗一切来自他人还是内心的叙事的最好方式，就是列下来可以做到的事情，然后将其完成，在这一规律的指导下，简单列一些接下来要做的有趣的事情：将 Tunaive 画完，尝试让 LLM 操作 SCAD 然后把我吃灰的 CNC 运行起来，学习写 Kernel Module 和 ESP32 上的软件。\n当然，还有和往年的传统一样，把屋子收拾好。这通常是让我变开心的最简单的事情。\n"},{"metadata":{"id":"single-port-sram-fifo","lang":"en-US","title":"FIFO on Single Port SRAM","tags":["开发"],"publish_time":"2025-12-01T04:57:03+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795}],"text":"FIFO","hadv":2546,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Single","hadv":3231,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Port","hadv":2253,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014}],"text":"SRAM","hadv":3157,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>The obvious way to implement a FIFO using SRAM is by using a dual-port SRAM — one port for reading, one for writing. Dual-port SRAMs are expensive (in multiple senses), so the traditional way is to “emulate” them using multiple banks of single-port SRAMs.</p>\n<p>It’s also <a href=\"https://chipress.online/2024/05/05/design-a-sync-fifo-using-single-port-srams/\">well known</a> that since we’re specifically implementing a FIFO, the two halves of SRAM accesses have a special pattern, i.e. with the classic banking method through address modulo, <strong>consective accesses from any one of the ports will never land on the same bank</strong> — they are guaranteed to loop though all banks in order. So instead of using more banks and hope that probability works in our favor, we can mostly get away with only using two banks, with a little bit of write buffering.</p>\n<ul>\n<li>Each cycle, if reading and writing do not involves a bank conflict, do both.</li>\n<li>Else, read has priority, and buffer the write. The buffered write will be guaranteed to not conflict with the reading half in the next cycle.\n<ul>\n<li>If no read is presented in the next cycle, the write is free to execute.</li>\n<li>Else, the read will land on the other bank, making it possible to write into this bank.</li>\n</ul>\n</li>\n<li>Since the buffer is guaranteed to be cleared next cycle, the storage can be bounded to one element, and the combinatory path going into FIFO’s push ready signal does not depend on the state of the buffer.</li>\n</ul>\n<p>All of these depends on the nice behavior of FIFO’s consecutive memory accesses. Let’s now try to introduce some other features that can potentially break this nice property.</p>\n<h2>Flushing FIFO</h2>\n<p>Consider a FIFO that allows for a single-cycle flushing operation (clearing all contents). These kind of queues are frequently used in pipelines with speculative executions, where the entire pipeline needs to be discarded (quickly).</p>\n<p>This means at least one of the head and tail pointers may snap to a place that does not depend on the previous value, most likely by reseting both pointer into their initial value, which can break the assumption of continous SRAM access.</p>\n<p>However in practice it does not matter in this use case. We will also reset the state of the buffer during flush. As long as we do not feed the write address of the <em>next</em> cycle into the memory in advance, there is no additional risk of strutural hazard.</p>\n<h2>Multi-port FIFO</h2>\n<p>Multi-port FIFO can read and/or write multiple entries at the same cycle. This is the kind of concurrency that often warrants banking for most storage structures.</p>\n<p>To implement a multi-port FIFO, number of banks have to increase. Generally, for a FIFO with <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> reading ports and <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> writing ports, <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>+</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W + R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> banks are required.</p>\n<p><strong>Also, the size of the buffer needs to increase to <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">⌈</mo><mi>R</mi><mi mathvariant=\"normal\">/</mi><mi>W</mi><mo stretchy=\"false\">⌉</mo><mo>×</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">\\lceil R / W \\rceil \\times W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">⌈</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mord\">/</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mclose\">⌉</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span>.</strong> To show this, consider whether we have more read ports or write ports.</p>\n<ul>\n<li>The easier case is when <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>≤</mo><mi>W</mi><mo>⇒</mo><mo stretchy=\"false\">⌈</mo><mi>R</mi><mi mathvariant=\"normal\">/</mi><mi>W</mi><mo stretchy=\"false\">⌉</mo><mo>×</mo><mi>W</mi><mo>=</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">R \\le W \\Rightarrow \\lceil R / W \\rceil \\times W = W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8193em;vertical-align:-0.136em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⇒</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">⌈</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mord\">/</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mclose\">⌉</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span>. A conflicting bank is guaranteed to be available for writes nexe cycle, and at most <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> banks can conflict at each cycle.</li>\n<li>For <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>&gt;</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">R &gt; W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7224em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">&gt;</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span>, the situation gets more complicated. Let’s first introduce an example. Consider the case <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>=</mo><mn>3</mn><mo separator=\"true\">,</mo><mi>W</mi><mo>=</mo><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">R = 3, W = 2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2</span></span></span></span>, assume that initially the buffer and queue is empty, <code>head = tail = 0</code>.</li>\n</ul>\n<blockquote>\n<p>Let’s write down the bank index of the writes, which are consecutive elements in <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"double-struck\">Z</mi><mi mathvariant=\"normal\">/</mi><mn>5</mn><mi mathvariant=\"double-struck\">Z</mi></mrow><annotation encoding=\"application/x-tex\">\\mathbb{Z} / 5 \\mathbb{Z}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathbb\">Z</span><span class=\"mord\">/5</span><span class=\"mord mathbb\">Z</span></span></span></span>:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mn>0</mn><mo separator=\"true\">,</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>2</mn><mo separator=\"true\">,</mo><mn>3</mn><mo separator=\"true\">,</mo><mn>4</mn><mo separator=\"true\">,</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>2</mn><mo separator=\"true\">,</mo><mn>3</mn><mo separator=\"true\">,</mo><mn>4...</mn></mrow><annotation encoding=\"application/x-tex\">0, 1, 2, 3, 4, 0, 1, 2, 3, 4...</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8389em;vertical-align:-0.1944em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">2</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">2</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4...</span></span></span></span></span></p>\n<p>Similarly, let’s write down the bank indexes of **banks that are available for writes for each cycle. Also let’s arbitrarily assume that on even cycles there are 3 reads, on odd cycles there is 1 read. To make thinks clearer, we will draw a <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>∣</mo><mo>−</mo></mrow><annotation encoding=\"application/x-tex\">\\mid-</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord\">−</span></span></span></span>divider between cycles. <small>cycles start at 0</small></p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mn>3</mn><mo separator=\"true\">,</mo><mn>4</mn><mo>∣</mo><mn>4</mn><mo separator=\"true\">,</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>2</mn><mo>∣</mo><mn>2</mn><mo separator=\"true\">,</mo><mn>3</mn><mo>∣</mo><mn>3</mn><mo separator=\"true\">,</mo><mn>4</mn><mo separator=\"true\">,</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>1...</mn></mrow><annotation encoding=\"application/x-tex\">3, 4 \\mid 4, 0, 1, 2 \\mid 2, 3 \\mid 3, 4, 0, 1 ...</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">4</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">2</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">2</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">3</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8389em;vertical-align:-0.1944em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">1...</span></span></span></span></span></p>\n<p>At first glance that seems very random, and depends highly on read pattern. However if we write the sequence in each cycle <strong>in reverse</strong>:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mn>4</mn><mo separator=\"true\">,</mo><mn>3</mn><mo>∣</mo><mn>2</mn><mo separator=\"true\">,</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>4</mn><mo>∣</mo><mn>3</mn><mo separator=\"true\">,</mo><mn>2</mn><mo>∣</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>4</mn><mo separator=\"true\">,</mo><mn>3...</mn></mrow><annotation encoding=\"application/x-tex\">4, 3 \\mid 2, 1, 0, 4 \\mid 3, 2 \\mid 1, 0, 4, 3 ...</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">4</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">3</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">2</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">2</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8389em;vertical-align:-0.1944em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">3...</span></span></span></span></span></p>\n<p>That’s exactly <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"double-struck\">Z</mi><mi mathvariant=\"normal\">/</mi><mn>5</mn><mi mathvariant=\"double-struck\">Z</mi></mrow><annotation encoding=\"application/x-tex\">\\mathbb{Z} / 5 \\mathbb{Z}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathbb\">Z</span><span class=\"mord\">/5</span><span class=\"mord mathbb\">Z</span></span></span></span> in reverse order.</p>\n</blockquote>\n<p>In general, the indexes of banks available for writes is <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"double-struck\">Z</mi><mi mathvariant=\"normal\">/</mi><mo stretchy=\"false\">(</mo><mi>W</mi><mo>+</mo><mi>R</mi><mo stretchy=\"false\">)</mo><mi mathvariant=\"double-struck\">Z</mi></mrow><annotation encoding=\"application/x-tex\">\\mathbb{Z} / (W + R) \\mathbb{Z}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathbb\">Z</span><span class=\"mord\">/</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mclose\">)</span><span class=\"mord mathbb\">Z</span></span></span></span> in reverse order. That means for each bank, in every <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">⌈</mo><mo stretchy=\"false\">(</mo><mi>W</mi><mo>+</mo><mi>R</mi><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mi>W</mi><mo stretchy=\"false\">⌉</mo><mo>=</mo><mo stretchy=\"false\">⌈</mo><mi>R</mi><mi mathvariant=\"normal\">/</mi><mi>W</mi><mo stretchy=\"false\">⌉</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">\\lceil (W + R) / W \\rceil = \\lceil R / W \\rceil + 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">⌈(</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mclose\">)</span><span class=\"mord\">/</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mclose\">⌉</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">⌈</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mord\">/</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mclose\">⌉</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> cycles, at lease one cycle is available for writes. So each write will at most remain in the buffer for <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">⌈</mo><mi>R</mi><mi mathvariant=\"normal\">/</mi><mi>W</mi><mo stretchy=\"false\">⌉</mo></mrow><annotation encoding=\"application/x-tex\">\\lceil R / W \\rceil</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">⌈</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mord\">/</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mclose\">⌉</span></span></span></span> cycles, giving us the size bound for the buffer.</p>\n<blockquote>\n<p><strong>Remark 1</strong>: The buffer have to be scheduled in an out-of-order fashion, both during enqueuing and executing. But the location for overwriting can be a simple autoincrement counter, because the <strong>upperbound</strong> for retiring time in the buffer is monotonic.</p>\n</blockquote>\n<blockquote>\n<p><strong>Remark 2</strong>: It’s possible to reduce this bound to <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span>, which may save at most <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">W - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> space. In fact we’ve already proved this for <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>≤</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">R \\le W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8193em;vertical-align:-0.136em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span>. However the other part of the proof seems pretty convoluted, and it’s possible that I’ve made some mistake, so that proof will have to wait for another blog post.</p>\n<p>We have to relax the “in-order overwriting” for the <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> bound to work.</p>\n</blockquote>\n<!--\nIt suffices to prove that the buffer never contains entries with the same bank index. It's possible to have a write presented on the cycle that has the same bank index as one of the entry in the buffer, but it's guaranteed that the \n\nThe index in the segment will increase\n\nmax wait time: ceil((R + W) / W) = ceil(R / W)\nSo buffer size: ceil(R / W) * W -> R? difference: at most W - 1\nk dist max: \n\n3 is not enough: 0 3, \n-->\n<details>\n<summary>Counterexample for buffer size of only W</summary>\nConsider W = 1, R = 3.\n<ul>\n<li>Cycle 0, Write bank 0, Read bank 0, 1, 2. Write gets buffered.</li>\n<li>Cycle 1, Write bank 1, Read bank 3, 0, 1. Previous buffered write still conflicts, new access also conflicts, but buffer is full.</li>\n</ul>\n</details>\n<details>\n<summary>Counterexample for a in-order buffer</summary>\nConsider W = 2, R = 1\n<ul>\n<li>Cycle 0, Write bank 0, 1, Read bank 0. Both write gets buffered because the writes operate in a FIFO manner.</li>\n<li>Cycle 1, Write bank 2, 0, Read bank 1. One write from buffer is clear to execute, but one still conflicts. Buffer overflows.</li>\n</ul>\n</details>\n<h2>Speculative FIFO</h2>\n<p>Another type of FIFO that takes speculative execution into account are FIFOs that have a separate embedded “committed” state. An additional head pointer denotes the actual committed FIFO head, but reads come from the speculative head location. One separate signal is used to increment the committed head pointer, and another one to indicate that the read pointer should revert to the committed state.</p>\n<p>Note the difference between this and the flusing FIFO is that the state needs to be kept. The canonical example for this kind of FIFO is the load/store queue for a in-order LSU with replay.</p>\n<p>In this scenario, although buffered writes are not guaranteed to complete next cycle, still at most one writes are block at each cycle. So we only need to allow writes presented at each cycle to schedule independently from the buffer write (i.e. writes out-of-order into the SRAM), which should only require minimal modification.</p>\n<blockquote>\n<p><strong>Remark 3</strong>: The original arbiter for each bank already have to consider three data sources (read port, write port, buffered write state). Instead, it’s the buffer that needs modification, so that it only update when the request from the write port gets blocked (which necessarily means that current buffered writes is scheduled).</p>\n</blockquote>\n<blockquote>\n<p><strong>Remark 4</strong>: Alternatively, more often than not, the readout data at the exact cycle of reverting does not matter. In this case, we can allow the write to go through. The caveat is that there might already be a buffered write, so the scheduler should be able to schedule two writes at the same cycle.</p>\n</blockquote>\n<h2>What if the SRAM has a non-zero write-to-read bypass latency?</h2>\n<p>This commonly means that writes to <strong>certain address</strong> cannot be reliably read within some cycles. The easiet way to solve this is by judging the validness of readout data by the tail pointer some cycles ago.</p>\n<p>But if the SRAM cannot reliably serve <strong>any</strong> read request within certain cycles of the write, or vice versa? e.g. this is a cursed SDRAM that has a really bad timing and precharge latency of eternality. Assume the latency is <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>L</mi><mi>W</mi></msub></mrow><annotation encoding=\"application/x-tex\">L_W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">L</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.13889em;\">W</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> and <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>L</mi><mi>R</mi></msub></mrow><annotation encoding=\"application/x-tex\">L_R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">L</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.00773em;\">R</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> for writes and reads.</p>\n<p>Within the latency, the ongoing request should be considered to have exclusive access to that bank. This implies we have to use <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>L</mi><mi>W</mi></msub><mo>+</mo><msub><mi>L</mi><mi>R</mi></msub></mrow><annotation encoding=\"application/x-tex\">L_W + L_R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">L</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.13889em;\">W</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">L</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.00773em;\">R</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> banks to have a shot at full pipeline bandwidth, with <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>L</mi><mi>R</mi></msub></mrow><annotation encoding=\"application/x-tex\">L_R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">L</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.00773em;\">R</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> buffers for writes, and <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>L</mi><mi>W</mi></msub></mrow><annotation encoding=\"application/x-tex\">L_W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">L</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.13889em;\">W</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> buffers for readout data.</p>\n","plain":"The obvious way to implement a FIFO using SRAM is by using a dual-port SRAM — one port for reading, one for writing. Dual-port SRAMs are expensive (in multiple senses), so the traditional way is to “emulate” them using multiple banks of single-port SRAMs.\nIt’s also well known that since we’re specifically implementing a FIFO, the two halves of SRAM accesses have a special pattern, i.e. with the classic banking method through address modulo, consective accesses from any one of the ports will never land on the same bank — they are guaranteed to loop though all banks in order. So instead of using more banks and hope that probability works in our favor, we can mostly get away with only using two banks, with a little bit of write buffering.\n- Each cycle, if reading and writing do not involves a bank conflict, do both.\n- Else, read has priority, and buffer the write. The buffered write will be guaranteed to not conflict with the reading half in the next cycle.- If no read is presented in the next cycle, the write is free to execute.\n- Else, the read will land on the other bank, making it possible to write into this bank.\n\n- Since the buffer is guaranteed to be cleared next cycle, the storage can be bounded to one element, and the combinatory path going into FIFO’s push ready signal does not depend on the state of the buffer.\nAll of these depends on the nice behavior of FIFO’s consecutive memory accesses. Let’s now try to introduce some other features that can potentially break this nice property.\n\nFlushing FIFO\nConsider a FIFO that allows for a single-cycle flushing operation (clearing all contents). These kind of queues are frequently used in pipelines with speculative executions, where the entire pipeline needs to be discarded (quickly).\nThis means at least one of the head and tail pointers may snap to a place that does not depend on the previous value, most likely by reseting both pointer into their initial value, which can break the assumption of continous SRAM access.\nHowever in practice it does not matter in this use case. We will also reset the state of the buffer during flush. As long as we do not feed the write address of the next cycle into the memory in advance, there is no additional risk of strutural hazard.\n\nMulti-port FIFO\nMulti-port FIFO can read and/or write multiple entries at the same cycle. This is the kind of concurrency that often warrants banking for most storage structures.\nTo implement a multi-port FIFO, number of banks have to increase. Generally, for a FIFO with R reading ports and W writing ports, W + R banks are required.\nAlso, the size of the buffer needs to increase to \\lceil R / W \\rceil \\times W. To show this, consider whether we have more read ports or write ports.\n- The easier case is when R \\le W \\Rightarrow \\lceil R / W \\rceil \\times W = W. A conflicting bank is guaranteed to be available for writes nexe cycle, and at most R banks can conflict at each cycle.\n- For R > W, the situation gets more complicated. Let’s first introduce an example. Consider the case R = 3, W = 2, assume that initially the buffer and queue is empty, head = tail = 0.\nLet’s write down the bank index of the writes, which are consecutive elements in \\mathbb{Z} / 5 \\mathbb{Z}:\n0, 1, 2, 3, 4, 0, 1, 2, 3, 4...\nSimilarly, let’s write down the bank indexes of **banks that are available for writes for each cycle. Also let’s arbitrarily assume that on even cycles there are 3 reads, on odd cycles there is 1 read. To make thinks clearer, we will draw a \\mid-divider between cycles. cycles start at 0\n3, 4 \\mid 4, 0, 1, 2 \\mid 2, 3 \\mid 3, 4, 0, 1 ...\nAt first glance that seems very random, and depends highly on read pattern. However if we write the sequence in each cycle in reverse:\n4, 3 \\mid 2, 1, 0, 4 \\mid 3, 2 \\mid 1, 0, 4, 3 ...\nThat’s exactly \\mathbb{Z} / 5 \\mathbb{Z} in reverse order.\n\nIn general, the indexes of banks available for writes is \\mathbb{Z} / (W + R) \\mathbb{Z} in reverse order. That means for each bank, in every \\lceil (W + R) / W \\rceil = \\lceil R / W \\rceil + 1 cycles, at lease one cycle is available for writes. So each write will at most remain in the buffer for \\lceil R / W \\rceil cycles, giving us the size bound for the buffer.\nRemark 1: The buffer have to be scheduled in an out-of-order fashion, both during enqueuing and executing. But the location for overwriting can be a simple autoincrement counter, because the upperbound for retiring time in the buffer is monotonic.\n\nRemark 2: It’s possible to reduce this bound to R, which may save at most W - 1 space. In fact we’ve already proved this for R \\le W. However the other part of the proof seems pretty convoluted, and it’s possible that I’ve made some mistake, so that proof will have to wait for another blog post.\nWe have to relax the “in-order overwriting” for the R bound to work.\n\n- Cycle 0, Write bank 0, Read bank 0, 1, 2. Write gets buffered.\n- Cycle 1, Write bank 1, Read bank 3, 0, 1. Previous buffered write still conflicts, new access also conflicts, but buffer is full.\n- Cycle 0, Write bank 0, 1, Read bank 0. Both write gets buffered because the writes operate in a FIFO manner.\n- Cycle 1, Write bank 2, 0, Read bank 1. One write from buffer is clear to execute, but one still conflicts. Buffer overflows.\n\nSpeculative FIFO\nAnother type of FIFO that takes speculative execution into account are FIFOs that have a separate embedded “committed” state. An additional head pointer denotes the actual committed FIFO head, but reads come from the speculative head location. One separate signal is used to increment the committed head pointer, and another one to indicate that the read pointer should revert to the committed state.\nNote the difference between this and the flusing FIFO is that the state needs to be kept. The canonical example for this kind of FIFO is the load/store queue for a in-order LSU with replay.\nIn this scenario, although buffered writes are not guaranteed to complete next cycle, still at most one writes are block at each cycle. So we only need to allow writes presented at each cycle to schedule independently from the buffer write (i.e. writes out-of-order into the SRAM), which should only require minimal modification.\nRemark 3: The original arbiter for each bank already have to consider three data sources (read port, write port, buffered write state). Instead, it’s the buffer that needs modification, so that it only update when the request from the write port gets blocked (which necessarily means that current buffered writes is scheduled).\n\nRemark 4: Alternatively, more often than not, the readout data at the exact cycle of reverting does not matter. In this case, we can allow the write to go through. The caveat is that there might already be a buffered write, so the scheduler should be able to schedule two writes at the same cycle.\n\n\nWhat if the SRAM has a non-zero write-to-read bypass latency?\nThis commonly means that writes to certain address cannot be reliably read within some cycles. The easiet way to solve this is by judging the validness of readout data by the tail pointer some cycles ago.\nBut if the SRAM cannot reliably serve any read request within certain cycles of the write, or vice versa? e.g. this is a cursed SDRAM that has a really bad timing and precharge latency of eternality. Assume the latency is L_W and L_R for writes and reads.\nWithin the latency, the ongoing request should be considered to have exclusive access to that bank. This implies we have to use L_W + L_R banks to have a shot at full pipeline bandwidth, with L_R buffers for writes, and L_W buffers for readout data.\n"},{"metadata":{"id":"time-traveling-with-relaxed-atomics","lang":"en-US","title":"Time traveling with relaxed atomics","tags":["微架构"],"publish_time":"2025-10-19T01:07:39+08:00","update_time":"2025-10-19T01:31:39+08:00","title_outline":{"groups":[{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Time","hadv":2683,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"traveling","hadv":4737,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"with","hadv":2357,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"relaxed","hadv":3947,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"atomics","hadv":4116,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>Several days earlier, <a href=\"https://dram.page/\">@dram</a> showed me <a href=\"https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3292r0.html#early-escape\">this piece of C++ code from the WG21 paper P3292R0</a> that is “miscompiled” by both G++ and Clang++, and convinced me that it does not actually happen on RISC-V. The essence of the code is the following:</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#b58900;\">foo</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#268bd2;\">q</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(0)*/ </span><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">p </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">new </span><span style=\"color:#268bd2;\">int</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(1)*/ </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">p </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">123</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(2)*/ </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">q </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">456</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(3)*/ </span><span style=\"color:#859900;\">assert</span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">p </span><span style=\"color:#657b83;\">== </span><span style=\"color:#6c71c4;\">123</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(4)*/ </span><span style=\"color:#859900;\">return</span><span style=\"color:#839496;\"> p;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>Surprisingly <strong>this assertion can fail</strong>, because it’s possible for <code>p == q</code>. The problem is that we can use another thread to send the pointer “back in time”:</p>\n<div class=\"highlighted highlighted-cpp\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-cpp\"><span style=\"color:#839496;\">std::atomic</span><span style=\"color:#657b83;\">&lt;</span><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> AtoB, BtoA;\n</span><span style=\"color:#268bd2;\">void </span><span style=\"color:#b58900;\">threadA</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(5)*/ </span><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">q </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> BtoA.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(6)*/ </span><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">p </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">foo</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">q</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(7)*/</span><span style=\"color:#839496;\"> AtoB.</span><span style=\"color:#b58900;\">store</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">p, relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">void </span><span style=\"color:#b58900;\">threadB</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(8)*/ </span><span style=\"color:#268bd2;\">int </span><span style=\"color:#859900;\">*</span><span style=\"color:#839496;\">ptr </span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\"> AtoB.</span><span style=\"color:#b58900;\">load</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/*(9)*/</span><span style=\"color:#839496;\"> BtoA.</span><span style=\"color:#b58900;\">store</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ptr, relaxed</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>Observing <code>p == q</code> inside foo does not break any lifetime or memory order restriction, and does not involve any UB (unlike an unsynchronized racing condition). Notice that crucially, reading the value of <code>p</code> in <code>void threadA()</code> (in order to store it into <code>AtoB</code>) only depends on the operations caused by the <code>new</code> operator, thus remains unordered with the assignment <code>*p = 123</code>.</p>\n<p>Even assuming MCA, the only “happens-after” chains we can deduce, in the case that <code>p == q</code>, are:</p>\n<p><code>(0)</code> -&gt; <code>(4) == (6)</code> -&gt; <code>(7)</code> -&gt; <code>(8)</code> -&gt; <code>(9)</code> -&gt; <code>(5)</code> -&gt; <code>(1)</code> -&gt; <code>(2)</code> -&gt; <code>(3)</code></p>\n<p>There is no loop and no contradiction, so this is a perfectly fine candidate execution.</p>\n<h2>The miscompilation</h2>\n<p>Essentially both G++ and Clang++ figure that <code>p != q</code> and do constant propagation such that <code>*p == 123</code> becomes <code>true</code>.</p>\n<p>I initially thought that this is not a miscompilation, or calling it one is a little bit too harsh. After all, the predominant part of all possible candidate executions will result in <code>p != q</code>, and getting <code>p == q</code> would require some really weird hardware shenanigans as we will see later.</p>\n<p>But during the writing of this post, I noticed that:</p>\n<ul>\n<li>the property of <code>p == q?</code> can be checked by other means. So this optimization introduces potential inconsistencies.</li>\n<li>More importantly, <strong>there is no UB at play here</strong>. Most of the time such concurrency problems would require some kind of racing. But there is none here.</li>\n</ul>\n<p>Since there is no UB, and potential for an inconsistency situation, the implementation cannot freely optimize this single expression into covering only <em>SOME</em> of the possible outcomes. So this is indeed a miscompilation.</p>\n<h2>The hardware</h2>\n<p>How is this possible from the hardware perspective? The obvious possibility is value prediction, but that’s only for the architectures with the weakest memory models. It seems that no other viable microarchitecture optimization would result in this behavior.</p>\n<details>\n<summary>Well Ackchyually🤓, if you try hard enough...</summary>\n...You can get a somewhat sane architecture that does this.\n<p>The end target is to let <code>(7)</code> happens-before <code>(5)</code>. Note that a simple “commit early after point-of-no-return” does not work because <code>(2)</code> needs the value of <code>q</code> to decide whether to exception, so <code>(7)</code> cannot be committed before <code>(5)</code>.</p>\n<p>So we have to assert that on this particular architecture, the memory exceptions are imprecise, or no memory exception is present (e.g. without MMU and memory protection). Combined with “commit early after PNR”, we can potentially observe <code>(7)</code> happening before <code>(5)</code>.</p>\n<p>That architecture in theory can produce the desired result, but with very low probability, because inter-core coherence is rather slow. Another architectural feature we can consider is SMT. In uarch with combined store buffer (which promptly breaks MCA), the store only has to commit to the store buffer for the other thread to see.</p>\n</details>\n<p>However, AArch64 memory model does allow this behavior<sup>[1]</sup>. This is one of the sad examples where the memory model disconnects with current hardware behaviors.</p>\n<p>In comparison, RISC-V forbids this. RISC-V specifically has a kind of rule (pipeline dependency) to forbid this kind of behavior (ppo rule 13 to be more concrete). It explicitly forbids <code>(7)</code> to commit before the address of <code>(2)</code> being ready, which is after <code>(5)</code>. This is actually a rare case of pipeline dependency being useful (as designed), and essentially dictates that all hardware implementations should not commit stores which are younger than memory accesses with unresolved addresses.</p>\n<p>As a side note, although looking similar to the OOTA (Out-of-thin-air) problem, these two scenarios are fundamentally different, as there is no read-from loop in this case. In contrast, the OOTA problem is already forbidden in all MCA architectures, but RISC-V requires an additional pipeline dependency.</p>\n<h2>The crab language</h2>\n<p>Since this was a C++ problem, it’s obligatory to talk about 🦀Rust🦀.</p>\n<p>General Rust is not interesting. You can just pass around raw pointers between threads with static global atomics, and get the same result. In that case, also no UB is present (all pointers are “alive” during accesses). So deep down, this is an LLVM bug.</p>\n<p>Talking about safe Rust is more interesting. To be precise, safe Rust is <code>rustc</code> + <code>std</code> + other safe code. It seems that in safe Rust, we also cannot produce this kind of scenario, but the chain is broken at a different place.</p>\n<p>It turns out safe Rust <em>really</em> hates to pass references to other threads with <strong>relaxed</strong> operations. It boils down to the fact that passing references by relaxed order means that the other thread may not even see the memory being initialized. So the only safe way to pass references across threads is through <a href=\"https://godbolt.org/z/fdjec6d53\">Mutexes</a>, which induces an acquire-release pair. If <code>(7) -&gt; (8) -&gt; (9) -&gt; (5)</code> establishes an acquire-release chain, <code>(0)</code> has to happen before itself, which is not possible.</p>\n<p>But Rust only needs the changes to <em>referenced memory</em> being visible on the other thread. But current ISAs don’t provide such fine-grained memory ordering primitives, so Rust doesn’t have more fine-grained APIs (e.g. similar to OnceCell, allocate and send), and it just happens that it also forbids this problem from happening in safe Rust.</p>\n<div class=\"footnotes\">\n[1] Both ARM and INRIA's herd-www are broken at the moment, so all I can say is \"trust me bro\".\n</div>","plain":"Several days earlier, @dram showed me this piece of C++ code from the WG21 paper P3292R0 that is “miscompiled” by both G++ and Clang++, and convinced me that it does not actually happen on RISC-V. The essence of the code is the following:\nint *foo(int *q) {\n    /*(0)*/ int *p = new int;\n\n    /*(1)*/ *p = 123;\n    /*(2)*/ *q = 456;\n    /*(3)*/ assert(*p == 123);\n\n    /*(4)*/ return p;\n}\n\nSurprisingly this assertion can fail, because it’s possible for p == q. The problem is that we can use another thread to send the pointer “back in time”:\nstd::atomic<int *> AtoB, BtoA;\nvoid threadA() {\n    /*(5)*/ int *q = BtoA.load(relaxed);\n    /*(6)*/ int *p = foo(q);\n    /*(7)*/ AtoB.store(p, relaxed);\n}\n\nvoid threadB() {\n    /*(8)*/ int *ptr = AtoB.load(relaxed);\n    /*(9)*/ BtoA.store(ptr, relaxed);\n}\n\nObserving p == q inside foo does not break any lifetime or memory order restriction, and does not involve any UB (unlike an unsynchronized racing condition). Notice that crucially, reading the value of p in void threadA() (in order to store it into AtoB) only depends on the operations caused by the new operator, thus remains unordered with the assignment *p = 123.\nEven assuming MCA, the only “happens-after” chains we can deduce, in the case that p == q, are:\n(0) -> (4) == (6) -> (7) -> (8) -> (9) -> (5) -> (1) -> (2) -> (3)\nThere is no loop and no contradiction, so this is a perfectly fine candidate execution.\n\nThe miscompilation\nEssentially both G++ and Clang++ figure that p != q and do constant propagation such that *p == 123 becomes true.\nI initially thought that this is not a miscompilation, or calling it one is a little bit too harsh. After all, the predominant part of all possible candidate executions will result in p != q, and getting p == q would require some really weird hardware shenanigans as we will see later.\nBut during the writing of this post, I noticed that:\n- the property of p == q? can be checked by other means. So this optimization introduces potential inconsistencies.\n- More importantly, there is no UB at play here. Most of the time such concurrency problems would require some kind of racing. But there is none here.\nSince there is no UB, and potential for an inconsistency situation, the implementation cannot freely optimize this single expression into covering only SOME of the possible outcomes. So this is indeed a miscompilation.\n\nThe hardware\nHow is this possible from the hardware perspective? The obvious possibility is value prediction, but that’s only for the architectures with the weakest memory models. It seems that no other viable microarchitecture optimization would result in this behavior.\nThe end target is to let (7) happens-before (5). Note that a simple “commit early after point-of-no-return” does not work because (2) needs the value of q to decide whether to exception, so (7) cannot be committed before (5).\nSo we have to assert that on this particular architecture, the memory exceptions are imprecise, or no memory exception is present (e.g. without MMU and memory protection). Combined with “commit early after PNR”, we can potentially observe (7) happening before (5).\nThat architecture in theory can produce the desired result, but with very low probability, because inter-core coherence is rather slow. Another architectural feature we can consider is SMT. In uarch with combined store buffer (which promptly breaks MCA), the store only has to commit to the store buffer for the other thread to see.\nHowever, AArch64 memory model does allow this behavior[1]. This is one of the sad examples where the memory model disconnects with current hardware behaviors.\nIn comparison, RISC-V forbids this. RISC-V specifically has a kind of rule (pipeline dependency) to forbid this kind of behavior (ppo rule 13 to be more concrete). It explicitly forbids (7) to commit before the address of (2) being ready, which is after (5). This is actually a rare case of pipeline dependency being useful (as designed), and essentially dictates that all hardware implementations should not commit stores which are younger than memory accesses with unresolved addresses.\nAs a side note, although looking similar to the OOTA (Out-of-thin-air) problem, these two scenarios are fundamentally different, as there is no read-from loop in this case. In contrast, the OOTA problem is already forbidden in all MCA architectures, but RISC-V requires an additional pipeline dependency.\n\nThe crab language\nSince this was a C++ problem, it’s obligatory to talk about 🦀Rust🦀.\nGeneral Rust is not interesting. You can just pass around raw pointers between threads with static global atomics, and get the same result. In that case, also no UB is present (all pointers are “alive” during accesses). So deep down, this is an LLVM bug.\nTalking about safe Rust is more interesting. To be precise, safe Rust is rustc + std + other safe code. It seems that in safe Rust, we also cannot produce this kind of scenario, but the chain is broken at a different place.\nIt turns out safe Rust really hates to pass references to other threads with relaxed operations. It boils down to the fact that passing references by relaxed order means that the other thread may not even see the memory being initialized. So the only safe way to pass references across threads is through Mutexes, which induces an acquire-release pair. If (7) -> (8) -> (9) -> (5) establishes an acquire-release chain, (0) has to happen before itself, which is not possible.\nBut Rust only needs the changes to referenced memory being visible on the other thread. But current ISAs don’t provide such fine-grained memory ordering primitives, so Rust doesn’t have more fine-grained APIs (e.g. similar to OnceCell, allocate and send), and it just happens that it also forbids this problem from happening in safe Rust.\n"},{"metadata":{"id":"about-blue-prince","lang":"zh-CN","title":"玩了 Blue Prince","tags":["游戏屋"],"publish_time":"2025-10-16T00:17:46+08:00","update_time":"2025-10-16T00:24:46+08:00","title_outline":{"groups":[{"chars":[{"char":"玩","components":[["M 14 -166L 77 -7C 90 -10 101 -22 106 -35C 257 -124 358 -195 420 -244L 418 -253C 253 -213 81 -177 14 -166Z",[0.613,0.259]],["M 29 -759L 37 -731L 400 -731C 415 -731 426 -736 428 -747C 385 -789 309 -853 309 -853L 242 -759Z",[0.889,0.087]],["M 34 -475L 42 -447L 393 -447C 407 -447 417 -452 420 -463C 388 -502 328 -564 328 -564L 275 -475Z",[0.968,0.085]],["M 141 -759L 141 -129L 281 -179L 281 -759Z",[0.008,0.769]],["M 464 -495C 469 -257 448 -59 232 84L 237 94C 556 -4 609 -218 614 -495Z",[0.269,0.684]],["M 367 -495L 375 -467L 956 -467C 971 -467 982 -472 985 -483C 938 -528 857 -596 857 -596L 785 -495Z",[0.86,0.073]],["M 416 -750L 424 -722L 915 -722C 930 -722 941 -727 944 -738C 897 -782 817 -848 817 -848L 746 -750Z",[0.637,0.0]],["M 665 -494L 665 -48C 665 37 680 64 773 64L 829 64C 945 64 987 36 987 -14C 987 -39 981 -55 951 -71L 948 -234L 938 -234C 918 -167 899 -101 888 -80C 882 -69 878 -66 869 -66C 863 -66 856 -66 847 -66L 821 -66C 807 -66 804 -71 804 -84L 804 -456C 804 -466 804 -482 804 -494Z",[-0.144,0.526]]],"bbox":{"top":-853,"bottom":94,"left":14,"right":987},"hadv":1000}],"text":"玩","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"B","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -120 300 -242 300 -376L 300 -398C 300 -518 300 -633 304 -747L 130 -747C 133 -631 133 -516 133 -400L 133 -364C 133 -241 133 -119 130 -0Z",[0.0,0.776]],["M 218 -0L 358 -0C 628 -0 699 -110 699 -208C 699 -320 614 -391 401 -403L 399 -393C 596 -415 655 -489 655 -572C 655 -673 585 -747 393 -747L 218 -747L 218 -709L 349 -709C 450 -709 492 -657 492 -567C 492 -466 441 -409 339 -409L 218 -409L 218 -373L 347 -373C 468 -373 525 -321 525 -205C 525 -95 460 -37 353 -37L 218 -37Z",[-0.03,0.521]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":699},"hadv":727},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Blue","hadv":2370,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Prince","hadv":3430,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<style>\n.hide {\n    background: var(--color-fg);\n}\n</style>\n<p>上次在 <a href=\"/post/about-ghost-of-tsushima\">Ghost of Tsushima 的简评</a>里提到了最近在 Blue Prince 里面坐牢。Well，人总会走出自己划给自己的牢笼的，在经过 150h 左右的游戏时间之后，我总算觉得我可以把这游戏放下，并且写一点评论了。</p>\n<p>玩这个游戏的整体心路历程可以总结为如下的进程：</p>\n<ul>\n<li>最开始 30h: GotY，神作，引人入胜，神秘气氛拉满，Secrets everywhere</li>\n<li>30h-80h: 开始意识到 Rougelike 机制的存在，和其他尝试对随机性进行弥补的机制。开始逐步摸清剧情。开始遇到让人摸不到头脑的谜题。</li>\n<li>80h-110h: 开始坐牢，这 30h 几乎没有进展，有的谜题需要 Brute force，导致体验很差</li>\n<li>110h onward：放弃治疗，开始看 Reddit 的 Hint，意识到可能自己这些谜题真的就解不开，心灰意冷，有些 Endgame puzzle 直接开始跟攻略。从解密游戏角度来看，这段时间就是没有体验，我为什么不直接看 Let’s Play，看别人 Suffer instead of myself?</li>\n</ul>\n<p>可以看到，是一个单调下坡路的体验。要不是最后为了写这个简评把一些 CG 看了一遍重新唤醒了最开始 30h 中令人兴奋的游戏体验，我就要给出经典 Steam 评论区中的 300h+ do not recommend 了。</p>\n<p>本评论希望以完全 Spoiler free 的方式完成，会涉及 Spoiler 的东西都会放到 Spoiler 里面藏起来。对于这种<em>基于探索的推理/解谜游戏</em>，很重要的体验是发现 Unknown unknown，本文会尽量避免提到这件事，不过探讨机制是肯定会暴露一些谜题解答信息，甚至会导致我个人对游戏操作的理解影响读者，所以如果真的想要特别完美的 Spoiler-free 体验的玩家，可以只阅读我如下的总体评价，再决定是否前往 Steam 商店就好了：</p>\n<blockquote>\n<p>本游戏从解谜游戏角度，和 FEZ 的谜题设置思路高度相似，难度也类似，唯一区别是相比于 FEZ 只有数个 “extreme late-game puzzle” <span class=\"hide\">(a.k.a. heart blocks)</span>，Blue Prince 有大概至少 50% 的谜题、游戏和叙事内容不比这一难度更简单。如果你没有看过 FEZ，但是对 TUNIC 比较熟悉的话，这些谜题的难度和结构大概类似 TUNIC 的 <span class=\"hide\">ARG 部分</span></p>\n<p>如果你很喜欢这些解谜体验，那么推荐，并且尝试穷尽本游戏的所有谜题。尤其是如果你有朋友可以和你一起沟通交流。</p>\n<p>如果你愿意尝试，可以自选结束的时机。本游戏的“通关”大概需要 30h，之后还有很多难度很高的谜题，而且很依赖你有没有某些特定的灵感，这也挺有 Rougelike 的 RNG 感的吧…所以没有解出来特定的谜题不应该被认为是 Skill issue</p>\n<p>如果你是看到 Steam 上说这东西很像 Outer Wilds 或者 Obra Dinn 所以感兴趣（比如我），Be well aware that 这些游戏是在一个 <em>基于探索的推理/解谜游戏光谱</em> 上的，需要具体根据你对特定游戏的体验做调整。这个光谱从一端到另一端大致是：\nObra Dinn / Outer Wilds -&gt; FEZ / TUNIC -&gt; Blue Prince -&gt; Rusty Lake 的游戏</p>\n</blockquote>\n<details>\n<summary>我的进度 (Spoiler!)</summary>\n<p>完成本文的时候我的进度：</p>\n<ul>\n<li>All sigils</li>\n<li>All red envelops</li>\n<li>除了需要新开档的奖杯，只缺一个 Drafting sweeptake</li>\n<li>All blue memos</li>\n<li>Endgame puzzle: 推进到 Still water puzzle</li>\n</ul>\n<p>其中：</p>\n<ul>\n<li>一个 Red envelop 一个 Sanctum key 的位置看了攻略</li>\n<li>Satelite 看了部分提示（主要是我没把那六个数映射到 XYZABC 上，还以为是 Z/26Z 循环群呢，后面具体吐槽这个）。</li>\n<li><a href=\"https://www.reddit.com/r/BluePrince/comments/1k0jhq2/endgame_progress_route_major_spoilers_within/\">r/BluePrince: End-Game Progress Route [Major Spoilers Within]</a> 这篇文章基本 14 之后都或多或少看了一点。</li>\n</ul>\n</details>\n<p>接下来给一些细节的讨论…</p>\n<h2>推理 vs. 解谜：构造谜题的范式</h2>\n<p>上面那个“光谱”是什么意思呢？</p>\n<p>我一直觉得需要显著区分“推理游戏 (detective game)”和“解谜游戏 (puzzle game)”。但是现实中确实这两个还是挺混杂的，因为很容易糅合在一起。不过我们依旧可以讨论是侧重在哪边。</p>\n<p>Blue Prince 的绝大多数谜题都是一种 “Word play”：各种各样 Written repersentation 的各种各样解读形式。它的名字就是一个例子：Blue Prince / Blueprints.</p>\n<p>这会导致它基本没有推理元素，而是应该是某种纯解谜游戏，更像 The witness (但是 The witness 的核心我感觉是另外的东西，有机会另说)：谜题解答不依赖推理，而是依赖灵机一动，依赖在草稿纸上写写画画，以及对大量信息的记忆。这也导致，同样是 Word play，他和 Chants of Sennar 区别巨大，不能等同，后者可以理解成是在真实语言学理论框架下的推理游戏。</p>\n<p>这首先就意味着这游戏不可能有翻译了，而且对于来自其他文化/语言的玩家其实有一个很高的隐形门槛。其次一个问题是：这会导致对于每一个特定的玩家，总会在整个过程中接不到一些线索。这本身并不是什么本质麻烦，但是 Blue Prince 在执行上出现了一些偏差：它的线索结构存在问题。</p>\n<h2>线索结构，难度感知和“社区合作解谜”</h2>\n<p>作为一个半职业 OW 吹，我要准备起手式了。基于探索的解谜/推理游戏 Game loop 是“获取新线索 -&gt; 解开谜题，从而获得物品/新的可达游戏区域”，因此我们可以把线索之间组成一个网。这就是 OW 船上电脑的“传闻模式”干的事情。 <small>Mobius 真的什么都想明白了</small></p>\n<p>OW 之所以广受赞誉，是因为他的这一线索网络比较稠密，每个节点都有多个出边、入边，这样玩家可能体验到线索放在一起的 Aha moment 的个数是已经获得的线索个数的指数阶的。Blue Prince 看上去这个网络也和 OW 一样稠密，而且节点数多非常多，应该是神中神游戏，但是有几个很大的不同：</p>\n<ul>\n<li>很多谜题，尤其是在 Late-game puzzle 上，布置是完全线性的。在 Late-game puzzle guide 那个 Reddit 帖子中，居然连续出现了接近十个 “Building on the previous puzzle” 字样，所以只要一个倒闭，这整条线就完全撞墙。而整条线撞墙的概率，是每个谜题撞墙的概率的一个指数函数。</li>\n<li>而且每个谜题并没有冗余：只有一种得到谜底的方式。这个时候，入边多反而会构成一种累赘：玩家需要真的完全掌握所有前置线索，才能够抵达谜底，没有任何 Wiggle room。结合到前述谜题的构造方法，因此某个特定谜题倒闭的概率也很高。这样每个谜题倒闭的概率，也是每个线索倒闭概率的一个指数函数。</li>\n<li>最后，在玩家尝试在游戏内解决特定谜题时，需要的操作数很多。这是入边多的一个表现。当一个大门没动静的时候，你不知道门上五十把钥匙哪把是有问题的。它可以直接类比成 RL 的 Sparse reward。考虑到我没有 Deepseek 聪明，Deepseek 是 RL 训练的，RL 没办法很好处理 Sparse reward，那我吃到了一个 sparse 的谜题的时候遇到的困难也可想而知。</li>\n</ul>\n<p>我能想到的唯一同时符合这三个特点的游戏中的谜题，就是 FEZ 的 <span class=\"hide\">heart blocks 中的两个（望远镜那个我感觉还行，剩下俩是真不行）</span>。就算是 TUNIC 的 <span class=\"hide\">ARG / tuneic language</span>，也是一小步一小步的谜题设计，没有 Sparse reward，即使这样它也花了整个社区很长时间才解决。</p>\n<p>这样的结果是在玩家的感知中这个游戏有些谜题“异常困难”，因为到了一个时间点之后自己所有谜题都解不开。并且无论是真的通过重复反复读笔记、Brute-force 还是看提示/攻略真的解决了卡关的谜题的时候，玩家也并不会得到很大的成就感：自己 Miss 的东西通常都是一些很小的，本身并不困难的一小部分，<small>That’s the psychology of hindsight</small>。同时这种困难会给人一种非常“人造”的感觉，有时会让人非常恼火。Reddit 上可以看到一些 <a href=\"https://www.reddit.com/r/BluePrince/comments/1kga6c1/80_hours_in_im_calling_it_quits/\">60-80h rage quit 的帖子</a>，确实也不能怪他们。</p>\n<p>因此如果有至少一个同样喜欢这类游戏的朋友可以同步一起推进，然后共享笔记，经常讨论的话，游戏体验会大大提升。就像 TUNIC 的 End-game puzzle <span class=\"hide\">(fairies, ARG, tuneic language)</span>，可以看出来开发者故意是把这部分谜题交给整个社区一起合作解开的，它的难度明显比其他谜题高一个台阶，所以从游戏设计角度这些“社区合作解谜” as a bonus 是一个很令人兴奋的内容。说到这里…</p>\n<h2>Does it never end?</h2>\n<p>然而对于 Blue prince 而言给我感觉这些 Late-game puzzle 反而起到了反效果，降低了体验，问题也是有几个不幸的原因：</p>\n<ul>\n<li>本身的谜题数量太多了，有非常多 Early game 的线索是用于这些也许是希望社区一起解决的谜题的，因为谜题的结构是线性的，所以在卡关情况下，玩家会觉得自己手头只有少数没有解开的谜题，但是却有一大堆不知道意思的线索，而且没有什么可以换到手头的其他谜题。</li>\n<li>这部分内容包含的剧情也太多了…谜题的线索结构是线性的，它的叙事结构也是按线性逐个揭露信息的，而这部分谜题揭露的剧情内容几乎完全没有被别的游戏中其他的探索覆盖。所以只要不把所有谜题弄完，看上去就是一个残缺的故事。</li>\n</ul>\n<p>我个人感觉是这反映出来了一个对自己作品非常有激情的开发团队，有很多点子，在开发八年的情况下，往游戏中塞了很多很多想法，各个地方都可以体现出他们的热情（e.g. Antichamber 中<span class=\"hide\">包含了第一版的设计</span>，Blue Prince 看上去<span class=\"hide\">也是把第一版的设计包含了进去作为了最终谜题</span>）。但是忽略掉的一点是，自己看起来都非常 Approachable 的解谜步骤，对于第一次接触的玩家而言可能就是并不是 100% 能够解开的，所以放很多这样的谜题其实是不合理的，一个链式的设计是尤其不合理的。这让我想起来我前几次作为 TA 出题的时候，感觉搞一个端到端很完整的题目，只要文档写的全，每一步足够简单，那么就是 OK 的。事实证明基本所有这样的东西都会翻车，指数函数是非常恐怖的。</p>\n<details>\n<summary>As a side note... (Minor spoiler...)</summary>\n<p>其实就算把所有谜题搞定了，感觉也是一个不完整的故事：最后没有 CG，莫名其妙就结束了，一直等待的大结局看来并不存在（或者六个月了社区还没搞出来）。</p>\n<p>互联网上对此有 <a href=\"https://www.gamespot.com/articles/blue-prince-doesnt-have-a-satisfying-ending-but-thats-the-point/1100-6532795/\">Argument</a> and <a href=\"https://www.reddit.com/r/Games/comments/1lm592t/comment/n05bnm9/\">Counter-argument</a>，我个人的感觉是：</p>\n<p>我连看攻略都还没打到那儿呢，哪儿来的感想。</p>\n</details>\n<h2>Rougelike 解谜成立吗？</h2>\n<p>最后说一下对于 Rougelike 解谜是否成立这件事情的一些感想。很多玩家估计是看到 “Rougelike puzzle game” 这个 tagline 所以开始玩的（Also 比如我），这个想法确实之前非常少见。</p>\n<p>我个人的感觉是，这是一个非常有趣，也相对成功的对于这一想法的实验，游戏本身的完成度比较高（虽然有上述一些问题），但是其实并没有特别证明 Rougelike 和 Puzzle 是一个很能有机结合的东西。尤其是到了后期，非常能看到这两个组成部分的割裂感：在手头只有一个有点想法的谜题情况下，有的时候需要疯狂 Reroll 超过两百次，很难说是一个令人享受的体验。</p>\n<p>在前期，Rougelike 的随机性确实为不同玩家创造了不同的解谜体验，但是说实话，就连 Obra Dinn 那么线性的地图，我都从来没有见过两个人有非常相似的解谜流程。好奇心侧重点的不同本身就可以创造不同的解谜体验<small>（OW 吹，Ahem）</small>，何况到了后期这个线索结构又像个漏斗一样把大家都弄回了一条线上。</p>\n<p>因此，只能说这是一个很好玩的 Rougelike 游戏，也是个很深很复杂的解谜游戏，但是目前来看我感觉很难说这是一个很 NB 的 Rougelike puzzle。</p>\n","plain":"上次在 Ghost of Tsushima 的简评里提到了最近在 Blue Prince 里面坐牢。Well，人总会走出自己划给自己的牢笼的，在经过 150h 左右的游戏时间之后，我总算觉得我可以把这游戏放下，并且写一点评论了。\n玩这个游戏的整体心路历程可以总结为如下的进程：\n- 最开始 30h: GotY，神作，引人入胜，神秘气氛拉满，Secrets everywhere\n- 30h-80h: 开始意识到 Rougelike 机制的存在，和其他尝试对随机性进行弥补的机制。开始逐步摸清剧情。开始遇到让人摸不到头脑的谜题。\n- 80h-110h: 开始坐牢，这 30h 几乎没有进展，有的谜题需要 Brute force，导致体验很差\n- 110h onward：放弃治疗，开始看 Reddit 的 Hint，意识到可能自己这些谜题真的就解不开，心灰意冷，有些 Endgame puzzle 直接开始跟攻略。从解密游戏角度来看，这段时间就是没有体验，我为什么不直接看 Let’s Play，看别人 Suffer instead of myself?\n可以看到，是一个单调下坡路的体验。要不是最后为了写这个简评把一些 CG 看了一遍重新唤醒了最开始 30h 中令人兴奋的游戏体验，我就要给出经典 Steam 评论区中的 300h+ do not recommend 了。\n本评论希望以完全 Spoiler free 的方式完成，会涉及 Spoiler 的东西都会放到 Spoiler 里面藏起来。对于这种基于探索的推理/解谜游戏，很重要的体验是发现 Unknown unknown，本文会尽量避免提到这件事，不过探讨机制是肯定会暴露一些谜题解答信息，甚至会导致我个人对游戏操作的理解影响读者，所以如果真的想要特别完美的 Spoiler-free 体验的玩家，可以只阅读我如下的总体评价，再决定是否前往 Steam 商店就好了：\n本游戏从解谜游戏角度，和 FEZ 的谜题设置思路高度相似，难度也类似，唯一区别是相比于 FEZ 只有数个 “extreme late-game puzzle” (a.k.a. heart blocks)，Blue Prince 有大概至少 50% 的谜题、游戏和叙事内容不比这一难度更简单。如果你没有看过 FEZ，但是对 TUNIC 比较熟悉的话，这些谜题的难度和结构大概类似 TUNIC 的 ARG 部分\n如果你很喜欢这些解谜体验，那么推荐，并且尝试穷尽本游戏的所有谜题。尤其是如果你有朋友可以和你一起沟通交流。\n如果你愿意尝试，可以自选结束的时机。本游戏的“通关”大概需要 30h，之后还有很多难度很高的谜题，而且很依赖你有没有某些特定的灵感，这也挺有 Rougelike 的 RNG 感的吧…所以没有解出来特定的谜题不应该被认为是 Skill issue\n如果你是看到 Steam 上说这东西很像 Outer Wilds 或者 Obra Dinn 所以感兴趣（比如我），Be well aware that 这些游戏是在一个 基于探索的推理/解谜游戏光谱 上的，需要具体根据你对特定游戏的体验做调整。这个光谱从一端到另一端大致是： Obra Dinn / Outer Wilds -> FEZ / TUNIC -> Blue Prince -> Rusty Lake 的游戏\n\n完成本文的时候我的进度：\n- All sigils\n- All red envelops\n- 除了需要新开档的奖杯，只缺一个 Drafting sweeptake\n- All blue memos\n- Endgame puzzle: 推进到 Still water puzzle\n其中：\n- 一个 Red envelop 一个 Sanctum key 的位置看了攻略\n- Satelite 看了部分提示（主要是我没把那六个数映射到 XYZABC 上，还以为是 Z/26Z 循环群呢，后面具体吐槽这个）。\n- r/BluePrince: End-Game Progress Route [Major Spoilers Within] 这篇文章基本 14 之后都或多或少看了一点。\n接下来给一些细节的讨论…\n\n推理 vs. 解谜：构造谜题的范式\n上面那个“光谱”是什么意思呢？\n我一直觉得需要显著区分“推理游戏 (detective game)”和“解谜游戏 (puzzle game)”。但是现实中确实这两个还是挺混杂的，因为很容易糅合在一起。不过我们依旧可以讨论是侧重在哪边。\nBlue Prince 的绝大多数谜题都是一种 “Word play”：各种各样 Written repersentation 的各种各样解读形式。它的名字就是一个例子：Blue Prince / Blueprints.\n这会导致它基本没有推理元素，而是应该是某种纯解谜游戏，更像 The witness (但是 The witness 的核心我感觉是另外的东西，有机会另说)：谜题解答不依赖推理，而是依赖灵机一动，依赖在草稿纸上写写画画，以及对大量信息的记忆。这也导致，同样是 Word play，他和 Chants of Sennar 区别巨大，不能等同，后者可以理解成是在真实语言学理论框架下的推理游戏。\n这首先就意味着这游戏不可能有翻译了，而且对于来自其他文化/语言的玩家其实有一个很高的隐形门槛。其次一个问题是：这会导致对于每一个特定的玩家，总会在整个过程中接不到一些线索。这本身并不是什么本质麻烦，但是 Blue Prince 在执行上出现了一些偏差：它的线索结构存在问题。\n\n线索结构，难度感知和“社区合作解谜”\n作为一个半职业 OW 吹，我要准备起手式了。基于探索的解谜/推理游戏 Game loop 是“获取新线索 -> 解开谜题，从而获得物品/新的可达游戏区域”，因此我们可以把线索之间组成一个网。这就是 OW 船上电脑的“传闻模式”干的事情。 Mobius 真的什么都想明白了\nOW 之所以广受赞誉，是因为他的这一线索网络比较稠密，每个节点都有多个出边、入边，这样玩家可能体验到线索放在一起的 Aha moment 的个数是已经获得的线索个数的指数阶的。Blue Prince 看上去这个网络也和 OW 一样稠密，而且节点数多非常多，应该是神中神游戏，但是有几个很大的不同：\n- 很多谜题，尤其是在 Late-game puzzle 上，布置是完全线性的。在 Late-game puzzle guide 那个 Reddit 帖子中，居然连续出现了接近十个 “Building on the previous puzzle” 字样，所以只要一个倒闭，这整条线就完全撞墙。而整条线撞墙的概率，是每个谜题撞墙的概率的一个指数函数。\n- 而且每个谜题并没有冗余：只有一种得到谜底的方式。这个时候，入边多反而会构成一种累赘：玩家需要真的完全掌握所有前置线索，才能够抵达谜底，没有任何 Wiggle room。结合到前述谜题的构造方法，因此某个特定谜题倒闭的概率也很高。这样每个谜题倒闭的概率，也是每个线索倒闭概率的一个指数函数。\n- 最后，在玩家尝试在游戏内解决特定谜题时，需要的操作数很多。这是入边多的一个表现。当一个大门没动静的时候，你不知道门上五十把钥匙哪把是有问题的。它可以直接类比成 RL 的 Sparse reward。考虑到我没有 Deepseek 聪明，Deepseek 是 RL 训练的，RL 没办法很好处理 Sparse reward，那我吃到了一个 sparse 的谜题的时候遇到的困难也可想而知。\n我能想到的唯一同时符合这三个特点的游戏中的谜题，就是 FEZ 的 heart blocks 中的两个（望远镜那个我感觉还行，剩下俩是真不行）。就算是 TUNIC 的 ARG / tuneic language，也是一小步一小步的谜题设计，没有 Sparse reward，即使这样它也花了整个社区很长时间才解决。\n这样的结果是在玩家的感知中这个游戏有些谜题“异常困难”，因为到了一个时间点之后自己所有谜题都解不开。并且无论是真的通过重复反复读笔记、Brute-force 还是看提示/攻略真的解决了卡关的谜题的时候，玩家也并不会得到很大的成就感：自己 Miss 的东西通常都是一些很小的，本身并不困难的一小部分，That’s the psychology of hindsight。同时这种困难会给人一种非常“人造”的感觉，有时会让人非常恼火。Reddit 上可以看到一些 60-80h rage quit 的帖子，确实也不能怪他们。\n因此如果有至少一个同样喜欢这类游戏的朋友可以同步一起推进，然后共享笔记，经常讨论的话，游戏体验会大大提升。就像 TUNIC 的 End-game puzzle (fairies, ARG, tuneic language)，可以看出来开发者故意是把这部分谜题交给整个社区一起合作解开的，它的难度明显比其他谜题高一个台阶，所以从游戏设计角度这些“社区合作解谜” as a bonus 是一个很令人兴奋的内容。说到这里…\n\nDoes it never end?\n然而对于 Blue prince 而言给我感觉这些 Late-game puzzle 反而起到了反效果，降低了体验，问题也是有几个不幸的原因：\n- 本身的谜题数量太多了，有非常多 Early game 的线索是用于这些也许是希望社区一起解决的谜题的，因为谜题的结构是线性的，所以在卡关情况下，玩家会觉得自己手头只有少数没有解开的谜题，但是却有一大堆不知道意思的线索，而且没有什么可以换到手头的其他谜题。\n- 这部分内容包含的剧情也太多了…谜题的线索结构是线性的，它的叙事结构也是按线性逐个揭露信息的，而这部分谜题揭露的剧情内容几乎完全没有被别的游戏中其他的探索覆盖。所以只要不把所有谜题弄完，看上去就是一个残缺的故事。\n我个人感觉是这反映出来了一个对自己作品非常有激情的开发团队，有很多点子，在开发八年的情况下，往游戏中塞了很多很多想法，各个地方都可以体现出他们的热情（e.g. Antichamber 中包含了第一版的设计，Blue Prince 看上去也是把第一版的设计包含了进去作为了最终谜题）。但是忽略掉的一点是，自己看起来都非常 Approachable 的解谜步骤，对于第一次接触的玩家而言可能就是并不是 100% 能够解开的，所以放很多这样的谜题其实是不合理的，一个链式的设计是尤其不合理的。这让我想起来我前几次作为 TA 出题的时候，感觉搞一个端到端很完整的题目，只要文档写的全，每一步足够简单，那么就是 OK 的。事实证明基本所有这样的东西都会翻车，指数函数是非常恐怖的。\n其实就算把所有谜题搞定了，感觉也是一个不完整的故事：最后没有 CG，莫名其妙就结束了，一直等待的大结局看来并不存在（或者六个月了社区还没搞出来）。\n互联网上对此有 Argument and Counter-argument，我个人的感觉是：\n我连看攻略都还没打到那儿呢，哪儿来的感想。\n\nRougelike 解谜成立吗？\n最后说一下对于 Rougelike 解谜是否成立这件事情的一些感想。很多玩家估计是看到 “Rougelike puzzle game” 这个 tagline 所以开始玩的（Also 比如我），这个想法确实之前非常少见。\n我个人的感觉是，这是一个非常有趣，也相对成功的对于这一想法的实验，游戏本身的完成度比较高（虽然有上述一些问题），但是其实并没有特别证明 Rougelike 和 Puzzle 是一个很能有机结合的东西。尤其是到了后期，非常能看到这两个组成部分的割裂感：在手头只有一个有点想法的谜题情况下，有的时候需要疯狂 Reroll 超过两百次，很难说是一个令人享受的体验。\n在前期，Rougelike 的随机性确实为不同玩家创造了不同的解谜体验，但是说实话，就连 Obra Dinn 那么线性的地图，我都从来没有见过两个人有非常相似的解谜流程。好奇心侧重点的不同本身就可以创造不同的解谜体验（OW 吹，Ahem），何况到了后期这个线索结构又像个漏斗一样把大家都弄回了一条线上。\n因此，只能说这是一个很好玩的 Rougelike 游戏，也是个很深很复杂的解谜游戏，但是目前来看我感觉很难说这是一个很 NB 的 Rougelike puzzle。\n"},{"metadata":{"id":"wait-for-process-ex","lang":"en-US","title":"Advanced waiting for processes on Windows for showing off on Steam","tags":["灵车"],"publish_time":"2025-10-13T23:42:42+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"Advanced","hadv":5161,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"waiting","hadv":3923,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"for","hadv":1566,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"processes","hadv":5133,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"W","components":[["M 9 -713L 161 -698L 196 -698L 347 -713L 347 -747L 9 -747Z",[-0.785,0.009]],["M 284 2L 377 2L 550 -576L 554 -590L 534 -590L 713 2L 806 2L 1030 -747L 972 -747L 811 -157L 808 -140L 826 -140L 655 -747L 553 -747L 385 -160L 381 -145L 399 -145L 244 -747L 63 -747Z",[-0.209,0.055]],["M 446 -713L 572 -698L 637 -698L 774 -713L 774 -747L 446 -747Z",[-0.673,0.043]],["M 867 -713L 973 -698L 1002 -698L 1108 -713L 1108 -747L 867 -747Z",[-0.544,0.089]]],"bbox":{"top":-747,"bottom":2,"left":9,"right":1108},"hadv":1111},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Windows","hadv":4881,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"for","hadv":1566,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"showing","hadv":4409,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409}],"text":"off","hadv":1455,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025}],"text":"Steam","hadv":3228,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/2025-10-13-steam-sakura.png"},"html":"<p>It’s well known that you can add external programs on Steam to friendly remind your friends that you are doing hard work™ and maybe they should too.</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/2025-10-13-steam-vscode.png\">\n  <figcaption>There would be a very noisy popup on your friend's screen</figcaption>\n</figure>\n<p>But most windows programs have quirks that makes this method of showing off not exactly reliable:</p>\n<ol>\n<li>Programs often auto-updates by calling an updater, exits, and waits for the updater to re-execute itself.</li>\n<li>Sometimes processes want to be singleton so they try to find existing running instance and exits immediately upon seeing one.</li>\n<li>Some games uses launchers, and Steam lose track of the process once the launcher exits.</li>\n</ol>\n<p>VSCode does 1 &amp; 2, and most Galgames would require some form of 3 (and also 2).</p>\n<p>To reliably impress our friends on Steam, we may need some tech.</p>\n<div class=\"highlighted highlighted-bat\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bat\"><span style=\"color:#859900;\">REM</span><span style=\"color:#586e75;\"> run.bat\n</span><span style=\"color:#839496;\">C:\\Run\\Your\\Launcher.exe\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">sleep </span><span style=\"color:#6c71c4;\">5\n</span><span style=\"color:#839496;\">powershell -command &quot;</span><span style=\"color:#2aa198;\">Get-Process &#39;ProcName&#39; | ForEach-Object {$_.WaitForExit()}</span><span style=\"color:#839496;\">&quot;\n</span></code></pre>\n</div>\n<p>This script waits for five seconds, and waits for all processes with <code>ProcName</code> to exit. This is already sufficient for case 2 &amp; 3, but may suffer from process name collision. To mitigate that and also solve case 1, we need a loop.</p>\n<div class=\"highlighted highlighted-bat\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bat\"><span style=\"color:#859900;\">REM</span><span style=\"color:#586e75;\"> run.bat\n</span><span style=\"color:#839496;\">C:\\Run\\Your\\Launcher.exe\n</span><span style=\"color:#839496;\">powershell -Command &quot;</span><span style=\"color:#2aa198;\">while ($true) { Start-Sleep -Seconds 5; $procs = Get-Process | Where-Object { $_.Path -eq &#39;C:\\Your\\Program.exe&#39; }; if ($procs.Count -eq 0) { break }; $procs[0].WaitForExit() }</span><span style=\"color:#839496;\">&quot;\n</span></code></pre>\n</div>\n<p>Unfortunately I did not figure out how to do multi-line literal in argument place with batch scripts, so this abomination will have to do.</p>\n<p>Finally, don’t forget to set the library page name and background.</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/2025-10-13-steam-sakura.png\" class=\"preview\">\n  <figcaption><a href=\"https://bgm.tv/subject/233030\">https://bgm.tv/subject/233030</a></figcaption>\n</figure>","plain":"It’s well known that you can add external programs on Steam to friendly remind your friends that you are doing hard work™ and maybe they should too.\nBut most windows programs have quirks that makes this method of showing off not exactly reliable:\n- Programs often auto-updates by calling an updater, exits, and waits for the updater to re-execute itself.\n- Sometimes processes want to be singleton so they try to find existing running instance and exits immediately upon seeing one.\n- Some games uses launchers, and Steam lose track of the process once the launcher exits.\nVSCode does 1 & 2, and most Galgames would require some form of 3 (and also 2).\nTo reliably impress our friends on Steam, we may need some tech.\nREM run.bat\nC:\\Run\\Your\\Launcher.exe\n\nsleep 5\npowershell -command \"Get-Process 'ProcName' | ForEach-Object {$_.WaitForExit()}\"\n\nThis script waits for five seconds, and waits for all processes with ProcName to exit. This is already sufficient for case 2 & 3, but may suffer from process name collision. To mitigate that and also solve case 1, we need a loop.\nREM run.bat\nC:\\Run\\Your\\Launcher.exe\npowershell -Command \"while ($true) { Start-Sleep -Seconds 5; $procs = Get-Process | Where-Object { $_.Path -eq 'C:\\Your\\Program.exe' }; if ($procs.Count -eq 0) { break }; $procs[0].WaitForExit() }\"\n\nUnfortunately I did not figure out how to do multi-line literal in argument place with batch scripts, so this abomination will have to do.\nFinally, don’t forget to set the library page name and background.\n"},{"metadata":{"id":"haidian-marathon-2025","lang":"zh-CN","title":"海淀马拉松 2025","tags":["走路猫"],"publish_time":"2025-10-13T03:27:19+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"海","components":[["M 26 -610L 19 -605C 45 -569 73 -514 79 -462C 193 -380 308 -593 26 -610Z",[-0.214,0.26]],["M 85 -217C 74 -217 40 -217 40 -217L 40 -199C 62 -197 79 -192 93 -182C 117 -166 121 -63 100 43C 110 84 138 96 163 96C 218 96 256 59 257 6C 260 -88 214 -121 212 -179C 211 -206 218 -244 225 -280C 236 -339 291 -573 324 -700L 309 -704C 137 -277 137 -277 116 -238C 105 -217 101 -217 85 -217Z",[0.116,0.782]],["M 99 -844L 92 -839C 119 -798 149 -739 157 -682C 278 -594 399 -820 99 -844Z",[-0.2,0.27]],["M 901 -442L 850 -354L 254 -354L 262 -326L 962 -326C 976 -326 986 -331 988 -342C 959 -381 901 -442 901 -442Z",[0.909,0.041]],["M 596 -803L 412 -853C 391 -725 337 -567 272 -478L 280 -471C 402 -546 499 -672 558 -790C 584 -787 592 -792 596 -803Z",[0.34,0.597]],["M 541 -594L 386 -669C 377 -530 341 -236 312 -111L 345 -149C 324 -141 299 -125 285 -111L 407 -44L 452 -102L 444 -102C 468 -230 504 -493 515 -602L 502 -594Z",[0.107,0.765]],["M 889 -211L 842 -130L 395 -130L 395 -102L 947 -102C 960 -102 970 -107 973 -118C 944 -154 889 -211 889 -211Z",[0.886,0.054]],["M 845 -818L 777 -724L 447 -724L 447 -696L 939 -696C 953 -696 964 -701 967 -712C 922 -755 845 -818 845 -818Z",[0.686,0.098]],["M 789 -594L 462 -594L 462 -566L 789 -566Z",[0.714,0.043]],["M 534 -310L 525 -305C 551 -270 575 -214 576 -165C 669 -89 775 -269 534 -310Z",[-0.202,0.3]],["M 543 -530L 534 -525C 557 -491 585 -438 592 -392C 683 -325 776 -496 543 -530Z",[-0.091,0.206]],["M 732 -594L 744 -594C 735 -231 720 -77 684 -44C 675 -36 665 -32 650 -32C 630 -32 589 -34 561 -36L 561 -24C 597 -14 617 -3 631 17C 643 34 645 60 645 95C 703 95 750 87 786 52C 844 -4 861 -122 871 -543C 894 -547 908 -554 916 -563L 802 -664Z",[0.127,0.763]]],"bbox":{"top":-853,"bottom":96,"left":19,"right":988},"hadv":1000}],"text":"海","hadv":1000,"breakAfter":true},{"chars":[{"char":"淀","components":[["M 27 -620L 19 -615C 49 -574 78 -512 83 -455C 195 -368 313 -585 27 -620Z",[-0.205,0.315]],["M 85 -218C 74 -218 40 -218 40 -218L 40 -200C 61 -198 79 -193 93 -183C 117 -166 121 -63 100 43C 110 83 140 95 165 95C 221 95 260 58 262 4C 264 -90 217 -121 215 -181C 214 -208 221 -246 228 -283C 239 -344 295 -584 328 -714L 313 -717C 138 -279 138 -279 116 -239C 105 -218 101 -218 85 -218Z",[0.116,0.781]],["M 89 -841L 82 -836C 115 -795 155 -732 169 -674C 292 -597 392 -827 89 -841Z",[-0.265,0.29]],["M 554 -357L 376 -377C 382 -230 359 -41 247 87L 255 96C 441 -2 497 -169 517 -329C 541 -331 552 -341 554 -357Z",[0.248,0.679]],["M 417 -758L 406 -758C 398 -703 369 -667 335 -651C 218 -508 545 -447 417 -758Z",[0.177,0.455]],["M 829 -589L 760 -504L 332 -504L 340 -476L 926 -476C 941 -476 952 -481 955 -492C 907 -532 829 -589 829 -589Z",[0.83,0.058]],["M 866 -687L 405 -687L 405 -659L 866 -659Z",[0.835,0.0]],["M 456 -185L 448 -181C 488 21 578 72 749 72C 788 72 882 72 921 72C 920 17 937 -32 975 -41L 975 -52C 920 -51 802 -51 753 -51C 595 -51 510 -72 456 -185Z",[-0.689,0.124]],["M 557 -860L 550 -855C 574 -818 594 -762 594 -708C 711 -609 854 -830 557 -860Z",[-0.099,0.186]],["M 708 -504L 572 -504L 572 -37L 708 15Z",[-0.005,0.716]],["M 813 -388L 745 -289L 663 -289L 663 -261L 907 -261C 921 -261 932 -266 935 -277C 891 -321 813 -388 813 -388Z",[0.532,0.088]],["M 804 -687L 815 -687C 809 -655 796 -594 788 -561L 797 -555C 839 -575 902 -610 940 -633C 961 -634 971 -637 978 -645L 868 -751Z",[0.26,0.181]]],"bbox":{"top":-860,"bottom":96,"left":19,"right":978},"hadv":1000}],"text":"淀","hadv":1000,"breakAfter":true},{"chars":[{"char":"马","components":[["M 614 -297L 539 -201L 36 -201L 44 -173L 722 -173C 736 -173 748 -178 751 -189C 699 -233 614 -297 614 -297Z",[0.879,0.053]],["M 706 -797L 126 -797L 135 -769L 706 -769Z",[0.685,0.009]],["M 438 -690L 254 -725C 250 -654 220 -458 198 -374L 236 -412C 214 -404 188 -386 173 -370L 307 -299L 355 -362L 348 -362C 365 -444 393 -621 402 -689L 393 -665C 423 -664 435 -677 438 -690Z",[0.122,0.614]],["M 868 -390L 297 -390L 297 -362L 868 -362Z",[0.839,0.017]],["M 780 -390L 791 -390C 782 -198 768 -76 740 -54C 731 -47 723 -45 706 -45C 682 -45 599 -49 542 -53L 542 -43C 597 -32 640 -15 662 8C 684 28 689 57 689 97C 771 98 814 88 852 59C 909 16 929 -98 941 -336C 963 -339 975 -346 983 -355L 857 -463Z",[0.192,0.579]],["M 626 -797L 637 -797C 632 -691 618 -510 599 -374C 669 -363 719 -368 754 -388C 768 -494 783 -654 789 -744C 810 -748 823 -757 829 -765L 684 -871Z",[0.076,0.657]]],"bbox":{"top":-871,"bottom":98,"left":36,"right":983},"hadv":1000}],"text":"马","hadv":1000,"breakAfter":true},{"chars":[{"char":"拉","components":[["M 327 -839L 151 -855L 151 -91C 151 -80 146 -74 131 -74C 108 -74 7 -80 7 -80L 7 -67C 58 -56 79 -41 95 -16C 110 8 116 44 119 95C 271 80 291 24 291 -76L 291 -810C 316 -814 326 -824 327 -839Z",[0.038,0.826]],["M 18 -375L 70 -212C 83 -216 94 -228 99 -241C 253 -333 359 -409 423 -459L 421 -469C 258 -426 83 -387 18 -375Z",[0.605,0.274]],["M 329 -706L 270 -615L 20 -615L 28 -587L 404 -587C 418 -587 429 -592 431 -603C 395 -644 329 -706 329 -706Z",[0.796,0.083]],["M 851 -107L 775 -4L 333 -4L 341 24L 960 24C 975 24 986 19 989 8C 938 -38 851 -107 851 -107Z",[0.859,0.061]],["M 842 -717L 769 -620L 421 -620L 429 -592L 945 -592C 959 -592 971 -597 973 -608C 925 -652 842 -717 842 -717Z",[0.72,0.091]],["M 466 -532L 454 -527C 500 -394 496 -223 485 -119C 560 36 796 -215 466 -532Z",[-0.086,0.637]],["M 526 -854L 519 -849C 557 -801 591 -731 599 -664C 734 -563 863 -825 526 -854Z",[-0.209,0.27]],["M 921 -494L 727 -540C 718 -380 693 -146 662 19L 686 19C 772 -136 843 -338 882 -470C 907 -471 917 -481 921 -494Z",[0.192,0.707]]],"bbox":{"top":-855,"bottom":95,"left":7,"right":989},"hadv":1000}],"text":"拉","hadv":1000,"breakAfter":true},{"chars":[{"char":"松","components":[["M 289 -584L 289 -600L 151 -600C 130 -439 85 -257 11 -132L 22 -122C 159 -242 251 -397 289 -584Z",[0.285,0.701]],["M 357 -702L 295 -600L 22 -600L 30 -572L 437 -572C 452 -572 462 -577 465 -588C 428 -632 357 -702 357 -702Z",[0.751,0.08]],["M 341 -836L 164 -853L 164 95L 192 95C 245 95 304 67 304 56L 304 -807C 332 -811 339 -821 341 -836Z",[0.004,0.849]],["M 293 -471L 284 -466C 310 -416 335 -346 338 -282C 443 -189 566 -395 293 -471Z",[-0.2,0.384]],["M 784 -396L 596 -480C 578 -363 497 -157 444 -100C 432 -90 400 -82 400 -82L 450 92C 488 80 521 30 529 -61L 456 -61L 456 -47C 560 -120 694 -282 756 -392L 724 -384C 759 -373 778 -383 784 -396Z",[0.362,0.678]],["M 690 -765L 499 -812C 489 -656 455 -485 415 -369L 426 -362C 528 -451 601 -579 650 -742C 674 -743 686 -752 690 -765Z",[0.236,0.645]],["M 430 -82L 472 67C 655 4 797 -59 873 -97L 873 -108C 689 -94 504 -84 430 -82Z",[0.689,0.147]],["M 726 -263L 716 -258C 761 -162 806 -46 817 62C 960 188 1085 -106 726 -263Z",[-0.235,0.47]],["M 826 -812L 736 -858L 725 -854C 744 -585 791 -439 904 -339C 915 -393 956 -455 987 -483L 989 -495C 894 -542 797 -647 757 -799L 763 -752C 791 -775 813 -795 826 -812Z",[-0.241,0.628]]],"bbox":{"top":-858,"bottom":188,"left":11,"right":1085},"hadv":1000}],"text":"松","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>今天跑了海淀马拉松！是今年第一次马拉松，就在家门口还是很方便，<del>那么近那么美周末去永丰</del>。</p>\n<p><a href=\"https://www.strava.com/activities/16112067077\">Strava</a></p>\n<p>今天下半年报的各种路跑比赛基本都是为了明年重马破三做训练准备的<small>以及出去玩</small>，主要缺乏的还是耐力，客观来说今天的表现也达成了目标：从 C 区追上 3:00 的 Pacer，然后至少跟到 28km (2/3)。不过这样说就很无聊，还是写一点抽象的感想比较有趣。</p>\n<p>跑马拉松中一个可能经常出现的现象是在跑道上做梦：明明知道自己的耐力无法达到均速 3:00，但是根据前半程的发挥忽然又感觉自己行了。这一现象的存在可能和跑步的时候大脑缺氧导致的降智相关。</p>\n<p>与之相关的另一个常见现象是，The five stage of grief 通常在长跑最后一段忽然掉速时发生：</p>\n<ul>\n<li>Denial: 一开始配速只掉几秒钟，感觉还能顶一顶</li>\n<li>Anger: 忽然就关节疼/抽筋/呼吸跟不上，很气</li>\n<li>Bargining: 感觉就算掉一点速度也还可以 PB 把，肯定能把肯定能把肯定能把</li>\n<li>Depression: 报名费 -120</li>\n<li>Acceptance: 在水站吃香蕉</li>\n</ul>\n<p>如何避免这个情况呢？只要多跑崩，获得了习得性无助，那么就不会瞎想，可以直接跳过前面四步，开始走路。摆烂是一种良好的精神状态，也是<a href=\"/tag/%E9%92%BB%E8%8D%89%E4%B8%9B\">跑定向</a>的人常见的状态。</p>\n<p>比较有喜剧效果的一件事情是，到 34km 左右开始抽筋，最后 8km 基本是走下来的，还是 PB 了，非常松弛。只能说之前的 PB （去年天马）实在是太烂了，当时是 24km 膝盖出了问题。好消息是今天虽然也不算完全跑下来了，但至少耐力比关节受伤要更好准备/训练一点，感觉又有一些信心了呢。喜剧的内核是悲剧，不过还是要从悲剧中找到一些开心的事情来，要不不就成了纯惨了吗？</p>\n<h2>赛事组织</h2>\n<p>典中典北京银行赞助的这些马拉松，要绑手环，本来想取完物洗个澡，结果带个手环直接懒了。导致的后果是穿了不合适的贴身衣物，还是挺磨的。</p>\n<p>赛事组织的各个方面算是四平八稳吧，本身人数也不多，所以也没有出现太混乱的情况。因为只有全程一个项目，所以路线设计和赛道布置都简单很多，冲线是直接反向经过起点的，直接跑回了集结区里，所以存衣不需要转运，这样就非常简单。</p>\n<p>有点想吐槽的一点是，全程只有 35km 一个地方有盐丸，结果正好今天抽筋了，所以是真的在水站站着吃了香蕉作为盐丸代餐。没有什么效果（笑）。</p>\n<p>参赛包里的拖鞋已经攒了好几双了，不过穿的很舒服，所以可以送给亲戚家人。熬夜写这个流水帐的时候正在吃发的两碗泡面，善恶相抵了一波。</p>\n<h2>What’s next?</h2>\n<p>跑完之后赶紧回学校帮忙办了 <a href=\"https://tuna.moe/event/2025/jetbrains/\">TUNA 的活动</a>。一路上搬物料的时候腿抖抖的。</p>\n<p>最近定向比赛比较多：马杯，首高，全国锦标赛，各个级别都覆盖全了。下一场路跑是半个月后的天津马拉松，希望能和今天一样关节不出问题吧！</p>\n","plain":"今天跑了海淀马拉松！是今年第一次马拉松，就在家门口还是很方便，那么近那么美周末去永丰。\nStrava\n今天下半年报的各种路跑比赛基本都是为了明年重马破三做训练准备的以及出去玩，主要缺乏的还是耐力，客观来说今天的表现也达成了目标：从 C 区追上 3:00 的 Pacer，然后至少跟到 28km (2/3)。不过这样说就很无聊，还是写一点抽象的感想比较有趣。\n跑马拉松中一个可能经常出现的现象是在跑道上做梦：明明知道自己的耐力无法达到均速 3:00，但是根据前半程的发挥忽然又感觉自己行了。这一现象的存在可能和跑步的时候大脑缺氧导致的降智相关。\n与之相关的另一个常见现象是，The five stage of grief 通常在长跑最后一段忽然掉速时发生：\n- Denial: 一开始配速只掉几秒钟，感觉还能顶一顶\n- Anger: 忽然就关节疼/抽筋/呼吸跟不上，很气\n- Bargining: 感觉就算掉一点速度也还可以 PB 把，肯定能把肯定能把肯定能把\n- Depression: 报名费 -120\n- Acceptance: 在水站吃香蕉\n如何避免这个情况呢？只要多跑崩，获得了习得性无助，那么就不会瞎想，可以直接跳过前面四步，开始走路。摆烂是一种良好的精神状态，也是跑定向的人常见的状态。\n比较有喜剧效果的一件事情是，到 34km 左右开始抽筋，最后 8km 基本是走下来的，还是 PB 了，非常松弛。只能说之前的 PB （去年天马）实在是太烂了，当时是 24km 膝盖出了问题。好消息是今天虽然也不算完全跑下来了，但至少耐力比关节受伤要更好准备/训练一点，感觉又有一些信心了呢。喜剧的内核是悲剧，不过还是要从悲剧中找到一些开心的事情来，要不不就成了纯惨了吗？\n\n赛事组织\n典中典北京银行赞助的这些马拉松，要绑手环，本来想取完物洗个澡，结果带个手环直接懒了。导致的后果是穿了不合适的贴身衣物，还是挺磨的。\n赛事组织的各个方面算是四平八稳吧，本身人数也不多，所以也没有出现太混乱的情况。因为只有全程一个项目，所以路线设计和赛道布置都简单很多，冲线是直接反向经过起点的，直接跑回了集结区里，所以存衣不需要转运，这样就非常简单。\n有点想吐槽的一点是，全程只有 35km 一个地方有盐丸，结果正好今天抽筋了，所以是真的在水站站着吃了香蕉作为盐丸代餐。没有什么效果（笑）。\n参赛包里的拖鞋已经攒了好几双了，不过穿的很舒服，所以可以送给亲戚家人。熬夜写这个流水帐的时候正在吃发的两碗泡面，善恶相抵了一波。\n\nWhat’s next?\n跑完之后赶紧回学校帮忙办了 TUNA 的活动。一路上搬物料的时候腿抖抖的。\n最近定向比赛比较多：马杯，首高，全国锦标赛，各个级别都覆盖全了。下一场路跑是半个月后的天津马拉松，希望能和今天一样关节不出问题吧！\n"},{"metadata":{"id":"post-scam-migration","lang":"zh-CN","title":"在 2025 年被电信诈骗","tags":["灵车"],"publish_time":"2025-10-10T06:03:25+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"年","components":[["M 26 -184L 34 -156L 946 -156C 961 -156 973 -161 976 -172C 921 -217 832 -283 832 -283L 753 -184Z",[0.915,0.041]],["M 262 -867C 209 -696 112 -523 26 -419L 35 -411C 183 -487 314 -601 417 -775C 441 -773 455 -781 460 -794Z",[0.406,0.562]],["M 194 -461L 194 -165L 348 -165L 348 -461L 362 -461L 194 -522Z",[-0.026,0.535]],["M 283 -691L 269 -663L 932 -663C 947 -663 959 -668 961 -679C 905 -726 818 -789 818 -789L 739 -691Z",[0.824,0.035]],["M 280 -461L 280 -433L 897 -433C 912 -433 923 -438 926 -449C 875 -491 791 -553 791 -553L 717 -461Z",[0.904,0.05]],["M 501 -691L 501 94L 531 94C 613 94 659 63 660 54L 660 -691Z",[0.007,0.781]]],"bbox":{"top":-867,"bottom":94,"left":26,"right":976},"hadv":1000}],"text":"年","hadv":1000,"breakAfter":true},{"chars":[{"char":"被","components":[["M 214 -637L 225 -637C 193 -499 108 -334 7 -227L 15 -216C 182 -305 302 -449 362 -592C 385 -594 394 -597 400 -608L 283 -706Z",[0.392,0.633]],["M 306 -637L 27 -637L 36 -609L 306 -609Z",[0.776,0.001]],["M 98 -857L 91 -852C 120 -814 148 -755 154 -700C 275 -610 398 -839 98 -857Z",[-0.151,0.267]],["M 260 55L 260 -447L 130 -340L 130 95L 154 95C 218 95 260 63 260 55Z",[0.03,0.736]],["M 245 -397L 235 -392C 264 -346 297 -279 305 -221C 400 -147 496 -331 245 -397Z",[-0.273,0.417]],["M 417 -699L 417 -441C 417 -262 405 -68 283 85L 292 92C 531 -45 548 -268 548 -442L 548 -689L 568 -689L 417 -741Z",[0.107,0.8]],["M 454 -435L 338 -505C 322 -454 302 -401 285 -368L 297 -359C 339 -375 379 -399 413 -424C 433 -419 448 -425 454 -435Z",[0.319,0.317]],["M 760 -456L 773 -456C 734 -217 616 -22 370 86L 376 97C 707 20 849 -164 915 -403C 939 -406 949 -409 956 -421L 833 -529Z",[0.434,0.628]],["M 863 -456L 483 -456L 483 -428L 863 -428Z",[0.7,0.064]],["M 880 -689L 491 -689L 491 -661L 880 -661Z",[0.537,0.091]],["M 591 -452L 578 -446C 611 -140 697 -10 863 93C 886 26 930 -17 989 -28L 991 -39C 801 -101 641 -198 591 -452Z",[-0.436,0.51]],["M 786 -833L 614 -847L 614 -439L 749 -439L 749 -804C 777 -809 784 -819 786 -833Z",[0.027,0.657]],["M 807 -689L 818 -689C 816 -647 808 -577 799 -529L 807 -523C 856 -550 913 -598 946 -635C 967 -636 977 -639 985 -648L 871 -755Z",[0.117,0.298]]],"bbox":{"top":-857,"bottom":97,"left":7,"right":991},"hadv":1000}],"text":"被","hadv":1000,"breakAfter":true},{"chars":[{"char":"电","components":[["M 245 -182L 245 -644L 793 -644L 793 -672L 255 -672L 97 -733L 97 -133L 119 -133C 181 -133 245 -167 245 -182Z",[0.219,0.312]],["M 778 -469L 188 -469L 188 -441L 778 -441Z",[0.85,0.01]],["M 778 -263L 188 -263L 188 -235L 778 -235Z",[0.893,0.008]],["M 575 -836L 392 -855L 392 -75C 392 43 446 66 580 66L 700 66C 919 66 979 39 979 -30C 979 -57 965 -75 920 -93L 916 -249L 906 -249C 879 -174 857 -120 840 -98C 829 -86 816 -82 799 -80C 779 -79 749 -78 714 -78L 599 -78C 557 -78 539 -87 539 -118L 539 -807C 564 -811 574 -823 575 -836Z",[-0.216,0.531]],["M 686 -672L 696 -672L 696 -155L 721 -155C 772 -155 845 -182 846 -191L 846 -621C 867 -625 879 -634 885 -642L 752 -745Z",[0.018,0.701]]],"bbox":{"top":-855,"bottom":66,"left":97,"right":979},"hadv":1000}],"text":"电","hadv":1000,"breakAfter":true},{"chars":[{"char":"信","components":[["M 392 -803L 193 -859C 162 -659 89 -447 16 -312L 27 -305C 169 -413 276 -567 351 -781C 375 -781 388 -790 392 -803Z",[0.303,0.665]],["M 309 -554L 188 -598L 135 -528L 135 95L 162 95C 218 95 276 65 278 54L 278 -534C 298 -538 306 -544 309 -554Z",[0.012,0.786]],["M 863 -759L 793 -663L 314 -663L 322 -635L 960 -635C 974 -635 985 -640 988 -651C 942 -694 863 -759 863 -759Z",[0.771,0.07]],["M 810 -611L 746 -523L 374 -523L 382 -495L 896 -495C 911 -495 922 -500 924 -511C 882 -551 810 -611 810 -611Z",[0.764,0.079]],["M 808 -464L 744 -376L 382 -376L 390 -348L 895 -348C 909 -348 920 -353 923 -364C 881 -404 808 -464 808 -464Z",[0.819,0.074]],["M 528 50L 528 -219L 825 -219L 825 -247L 535 -247L 386 -304L 386 94L 406 94C 465 94 528 63 528 50Z",[0.179,0.286]],["M 830 -23L 469 -23L 469 5L 830 5Z",[0.924,0.001]],["M 520 -860L 514 -855C 550 -815 583 -752 590 -692C 722 -600 843 -853 520 -860Z",[-0.09,0.194]],["M 739 -247L 749 -247L 749 81L 774 81C 823 81 893 53 894 44L 894 -196C 915 -200 927 -210 933 -218L 803 -316Z",[0.022,0.556]]],"bbox":{"top":-860,"bottom":95,"left":16,"right":988},"hadv":1000}],"text":"信","hadv":1000,"breakAfter":true},{"chars":[{"char":"诈","components":[["M 248 -584L 35 -584L 44 -556L 248 -556Z",[-0.806,0.008]],["M 243 -559L 136 -559L 136 -156C 136 -132 127 -120 74 -89L 181 64C 211 43 244 -16 215 -105L 146 -48L 278 -105L 278 -538Z",[0.05,0.747]],["M 102 -848L 94 -843C 131 -794 174 -724 190 -659C 316 -576 420 -816 102 -848Z",[-0.262,0.328]],["M 109 -84L 188 45C 299 -68 382 -174 422 -228L 418 -237C 292 -170 162 -107 109 -84Z",[0.497,0.398]],["M 138 -584L 136 -584L 136 -504L 278 -504L 278 -541L 268 -532C 302 -534 314 -543 321 -551L 204 -648Z",[0.031,0.077]],["M 634 -791L 441 -855C 408 -692 342 -520 278 -413L 288 -406C 413 -487 515 -607 593 -771C 616 -770 630 -779 634 -791Z",[0.334,0.6]],["M 850 -749L 780 -654L 474 -654L 474 -626L 945 -626C 960 -626 971 -631 974 -642C 928 -685 850 -749 850 -749Z",[0.789,0.082]],["M 675 57L 675 -655L 525 -655L 525 95L 553 95C 630 95 675 66 675 57Z",[0.001,0.803]],["M 831 -319L 761 -220L 600 -220L 600 -192L 927 -192C 941 -192 952 -197 955 -208C 910 -252 831 -319 831 -319Z",[0.673,0.118]],["M 820 -529L 757 -439L 600 -439L 600 -411L 906 -411C 920 -411 931 -416 934 -427C 892 -468 820 -529 820 -529Z",[0.739,0.06]]],"bbox":{"top":-855,"bottom":95,"left":35,"right":974},"hadv":1000}],"text":"诈","hadv":1000,"breakAfter":true},{"chars":[{"char":"骗","components":[["M 215 -632L 74 -658C 73 -590 57 -425 44 -354L 72 -392C 53 -385 29 -371 15 -358L 118 -297L 158 -346L 150 -346C 161 -420 175 -566 179 -629L 170 -608C 200 -606 212 -619 215 -632Z",[0.092,0.669]],["M 16 -208L 77 -58C 89 -61 100 -72 105 -85C 177 -152 228 -204 257 -238L 256 -247C 158 -229 58 -213 16 -208Z",[0.374,0.217]],["M 320 -759L 31 -759L 40 -731L 320 -731Z",[0.737,0.003]],["M 343 -374L 97 -374L 97 -346L 343 -346Z",[-0.941,0.009]],["M 267 -374L 278 -374C 271 -152 259 -59 236 -38C 229 -31 221 -29 208 -29C 191 -29 156 -31 134 -32L 134 -19C 162 -12 179 -1 190 15C 201 30 203 57 203 90C 250 90 286 79 315 55C 363 16 380 -68 388 -328C 409 -331 421 -337 428 -345L 326 -431Z",[0.153,0.705]],["M 239 -759L 249 -759C 243 -660 228 -489 209 -362C 261 -353 297 -357 323 -372C 338 -475 353 -628 359 -711C 380 -714 394 -722 401 -730L 285 -817Z",[0.087,0.733]],["M 432 -724L 432 -508C 432 -320 426 -93 338 90L 349 97C 536 -71 547 -332 547 -508L 547 -714L 565 -714L 432 -761Z",[0.087,0.838]],["M 848 -542L 502 -542L 502 -514L 848 -514Z",[0.732,0.049]],["M 867 -714L 502 -714L 502 -686L 867 -686Z",[0.641,0.076]],["M 599 67L 599 -410L 612 -410L 515 -448L 515 94L 530 94C 572 94 599 73 599 67Z",[-0.003,0.83]],["M 886 -242L 568 -242L 568 -214L 886 -214Z",[0.846,0.03]],["M 889 -410L 571 -410L 571 -382L 889 -382Z",[0.783,0.044]],["M 598 -862L 590 -857C 613 -826 635 -776 637 -729C 743 -646 864 -845 598 -862Z",[0.045,0.333]],["M 705 1L 705 -396L 636 -396L 636 20L 647 20C 682 20 704 5 705 1Z",[-0.001,0.839]],["M 809 -48L 809 -396L 742 -396L 742 -29L 753 -29C 787 -29 809 -44 809 -48Z",[0.008,0.82]],["M 834 -410L 843 -410L 843 -24C 843 -13 840 -7 828 -7C 814 -7 766 -11 766 -11L 766 3C 796 8 808 19 817 31C 825 44 828 66 829 93C 934 84 947 51 947 -17L 947 -370C 963 -373 975 -380 980 -386L 879 -461Z",[0.039,0.743]],["M 802 -714L 811 -714L 811 -465L 831 -465C 868 -465 927 -486 928 -493L 928 -672C 944 -675 955 -683 960 -689L 853 -768Z",[-0.06,0.562]]],"bbox":{"top":-862,"bottom":97,"left":15,"right":980},"hadv":1000}],"text":"骗","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/migration-2025-dmesg.jpg"},"html":"<p>2025 年还能被电信诈骗，实在是非常丢人。不过更搞笑的是之后的损管和恢复过程，自己的灵车 Infra 真的是随便戳一下就轰然倒塌，最后整个国庆假期都花在这上了。</p>\n<h2>What happened?</h2>\n<p>以管理员权限运行了一个恶意软件。</p>\n<p>这个恶意软件伪装成了一个会议软件的客户端 (https://weconne.app)，但是其实是扫描 AppData 里面的文件，并且应该有 Keylogger，是用来骗钱包私钥的。</p>\n<p>互联网实在是太坏了。</p>\n<h2>Then?</h2>\n<p>还好我这台电脑上没装钱包。不过这台系统是肯定要重装了。然而在重装过程中发生了巨量神秘倒闭事件。</p>\n<h3>数据移动</h3>\n<p>目前这个系统是一个 Linux Host 上运行的 Windows Guest，正好顺便把 Host 也挪动到一个更大的硬盘上。Host 的 rootfs 放在一个 2.5 寸 SATA SSD 硬盘上，拿了另外一个挂在易驱线上开始 <code>dd</code>。</p>\n<p>然后发现 <code>dmesg</code> 偶尔会报写入失败。由于这次是在 x86 上，所以肯定不是上次 <a href=\"/post/usb-uas-quirks-on-mtk\">MTK Chipset 上的驱动问题</a>。比较遗憾的是 <code>dmesg</code> 消息已经被刷掉了，没有留下记录，所以有可能是 <code>UAS</code> 驱动的问题，但更有可能是线本身受干扰比较严重。比较神秘的是之后用这根线挂 HDD 就没出现过问题，所以也可能是供电问题？</p>\n<p>总之，交换了源盘和目标盘，目标盘挂在主板 SATA 上，源盘挂在易驱线上，读写就都正常了。As a reference，这根线用的芯片是 <code>174c:55aa</code>，需要遇到类似情况的网友帮帮忙来定位问题了。</p>\n<h3>重新安装 GRUB</h3>\n<p>复制之后直接尝试启动，发现启动不起来。和群友学习了一下 GRUB EFI 的工作原理，得知需要重新 <code>grub-install</code> 一下，原因是虽然 rootfs 分区 UUID 没有变，但是 Disk UUID 变了，所以需要把新的 EFI executable path 写到 NVRAM 里面，要不然 BIOS 不知道。</p>\n<h3>打包数据</h3>\n<p>为什么上面这个 <code>dmesg</code> 没有存档呢？因为后续在 rsync Windows 数据到 NAS 备份盘的时候，发现了更加惊悚的一幕：</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/migration-2025-dmesg.jpg\" class=\"preview\">\n  <figcaption>dmesg</figcaption>\n</figure>\n<p>第一反应是线又坏了：前往小米之家购买了高级本命红颜色数据线，并且从 <code>ntfs3g</code> 更换为 <code>ntfs3</code>，还是爆炸，并且炸的更加严重，<code>rsync</code> 会直接彻底卡死。多次运行后注意到坏掉的 sector 稳定，所以真的是坏道了，而且 <code>ntfs3</code> 遇到坏道以后状态会直接爆炸，后续没办法再处理任何读取：</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/migration-2025-ntfs3.jpg\" class=\"preview\">\n  <figcaption>dmesg</figcaption>\n</figure>\n<p>所以为了至少救一点数据出来，换回了 <code>ntfs3g</code>。还好只有一个文件坏了，而且做了 <a href=\"https://wiki.archlinux.org/title/Parchive\">Parchive</a>，所以可以修回来，不过还是挺哈人的…</p>\n<p>SMART 信息如下，应该已经坏了很久了。这台机器的 SMART 通知用的 SMTP 服务器挂了（自建 SMTP 服务器 TLS 证书过期，Certbot 没有正确执行 Hook 把 maddy 重启），所以没收到通知…</p>\n<pre><code>SMART Attributes Data Structure revision number: 10\nVendor Specific SMART Attributes with Thresholds:\nID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE\n  1 Raw_Read_Error_Rate     0x010f   084   062   ---    Pre-fail  Always       -       601824\n  3 Spin_Up_Time            0x0103   088   086   ---    Pre-fail  Always       -       0\n  4 Start_Stop_Count        0x0032   086   086   ---    Old_age   Always       -       14941\n  5 Reallocated_Sector_Ct   0x0133   099   099   ---    Pre-fail  Always       -       208\n  7 Seek_Error_Rate         0x000f   089   060   ---    Pre-fail  Always       -       908686414\n  9 Power_On_Hours          0x0032   051   051   ---    Old_age   Always       -       43564\n 10 Spin_Retry_Count        0x0013   100   100   ---    Pre-fail  Always       -       0\n 12 Power_Cycle_Count       0x0032   100   100   ---    Old_age   Always       -       162\n184 End-to-End_Error        0x0032   100   100   ---    Old_age   Always       -       0\n187 Reported_Uncorrect      0x0032   001   001   ---    Old_age   Always       -       137\n188 Command_Timeout         0x0032   100   001   ---    Old_age   Always       -       4522669620495\n189 High_Fly_Writes         0x003a   055   055   ---    Old_age   Always       -       45\n190 Airflow_Temperature_Cel 0x0022   059   029   ---    Old_age   Always       -       41 (Min/Max 41/71)\n191 G-Sense_Error_Rate      0x0032   100   100   ---    Old_age   Always       -       0\n192 Power-Off_Retract_Count 0x0032   100   100   ---    Old_age   Always       -       128\n193 Load_Cycle_Count        0x0032   093   093   ---    Old_age   Always       -       15979\n194 Temperature_Celsius     0x0022   041   071   ---    Old_age   Always       -       41 (0 13 0 0 0)\n195 Hardware_ECC_Recovered  0x001a   036   003   ---    Old_age   Always       -       601824\n196 Reallocated_Event_Count 0x0032   000   000   ---    Old_age   Always       -       57167\n197 Current_Pending_Sector  0x0012   100   100   ---    Old_age   Always       -       27\n198 Offline_Uncorrectable   0x0010   100   100   ---    Old_age   Offline      -       0\n199 UDMA_CRC_Error_Count    0x003e   200   200   ---    Old_age   Always       -       0\n240 Head_Flying_Hours       0x0000   100   253   ---    Old_age   Offline      -       20053 (226 47 0)\n241 Total_LBAs_Written      0x0000   100   253   ---    Old_age   Offline      -       14240009369\n242 Total_LBAs_Read         0x0000   100   253   ---    Old_age   Offline      -       1115691404091\n</code></pre>\n<h2>What else</h2>\n<p>除此之外还出现了一些搞笑情况，比如：</p>\n<ol>\n<li>在几乎同时，我工位上的工作站 990Pro 又掉盘了…我还以为是我手动为了损管给关了，结果第二天到了工位一看，怎么在 BIOS 里，Storage 空空的，这下坏了。</li>\n<li>断网检查了一圈没有恶意文件，然后网线一插，还是没网，心里一想坏了路由器上的脚本写炸了，结果排查了半天，最后发现是工位这一排的交换机电源线松了，然后是国庆所以无人注意到…欢迎报考世界一流大学计算机系.jpg</li>\n<li>学校提供的最新的 Windows 安装媒介镜像：</li>\n</ol>\n  <figure>\n    <img src=\"https://layered-assets.thu.fail/migration-2025-lang.jpg\" class=\"preview\">\n    <figcaption>English (Traditional)</figcaption>\n  </figure>\n<ol start=\"4\">\n<li>在小米之家购买 USB 线实录：</li>\n</ol>\n<blockquote>\n<p>我：咱们这有兼容 USB 3 或者 Thunerbolt 的数据线吗？ <br />\n店员：…?</p>\n<p>我：咱这儿最好的数据线是啥？ <br />\n店员：[拿来一个 A to C 的线] <br />\n我：不不不，要 C to C 的</p>\n<p>接过 C to C 的线，翻过来看规格。 <br />\n小米：规格 1A <br />\n我：…?</p>\n</blockquote>\n<ol start=\"5\">\n<li>为了在 archiso 里面跑 <code>gparted</code>，安装了一个 <code>gdm</code>。结果 <code>gdm</code> 在启动图形界面的过程（包括创建 <code>xdg</code> 目录）不会有任何其他“忙碌”指示，需要干等大概两分钟，然后 archiso 又有一个特别长的 motd，导致我一直以为是 Xorg 哪里挂了…</li>\n</ol>\n<p>The best part：如果这个时候切换 Terminal，<code>gdm</code> 会直接把 session 杀掉…</p>\n  <figure>\n    <img src=\"https://layered-assets.thu.fail/migration-2025-gdm.jpg\" class=\"preview\">\n    <figcaption>gdm</figcaption>\n  </figure>\n<ol start=\"6\">\n<li>主机是一个 NUC10，所以主板 SATA 是个排线，经过这一晚上折腾最后松了，于是：</li>\n</ol>\n  <figure>\n    <img src=\"https://layered-assets.thu.fail/migration-2025-ata.jpg\" class=\"preview\">\n    <figcaption>ata</figcaption>\n  </figure>\n<h2>Final remarks</h2>\n<p>最后在群友的建议下购入了 HBA 卡，搞正经 NAS 了。</p>\n<p>对于诈骗本身而言，有一个很大的隐患是很多 Key 都在工作机上，而恶意软件被执行的时候是有一个活跃的 SSH 连接在一个窗口上的。如果恶意软件有远控能力的话，那很容易所有服务器都被打穿了。还好后续分析了一下就是个简单币圈诈骗软件，不过还是最好推进一下用 YubiKey 登录。</p>\n<p>不过在用电视工作的时候距离电脑 USB 口好远，不知道有没有远程 USB 的设备呢？USB/IP on RaspberryPi?</p>\n","plain":"2025 年还能被电信诈骗，实在是非常丢人。不过更搞笑的是之后的损管和恢复过程，自己的灵车 Infra 真的是随便戳一下就轰然倒塌，最后整个国庆假期都花在这上了。\n\nWhat happened?\n以管理员权限运行了一个恶意软件。\n这个恶意软件伪装成了一个会议软件的客户端 (https://weconne.app)，但是其实是扫描 AppData 里面的文件，并且应该有 Keylogger，是用来骗钱包私钥的。\n互联网实在是太坏了。\n\nThen?\n还好我这台电脑上没装钱包。不过这台系统是肯定要重装了。然而在重装过程中发生了巨量神秘倒闭事件。\n\n数据移动\n目前这个系统是一个 Linux Host 上运行的 Windows Guest，正好顺便把 Host 也挪动到一个更大的硬盘上。Host 的 rootfs 放在一个 2.5 寸 SATA SSD 硬盘上，拿了另外一个挂在易驱线上开始 dd。\n然后发现 dmesg 偶尔会报写入失败。由于这次是在 x86 上，所以肯定不是上次 MTK Chipset 上的驱动问题。比较遗憾的是 dmesg 消息已经被刷掉了，没有留下记录，所以有可能是 UAS 驱动的问题，但更有可能是线本身受干扰比较严重。比较神秘的是之后用这根线挂 HDD 就没出现过问题，所以也可能是供电问题？\n总之，交换了源盘和目标盘，目标盘挂在主板 SATA 上，源盘挂在易驱线上，读写就都正常了。As a reference，这根线用的芯片是 174c:55aa，需要遇到类似情况的网友帮帮忙来定位问题了。\n\n重新安装 GRUB\n复制之后直接尝试启动，发现启动不起来。和群友学习了一下 GRUB EFI 的工作原理，得知需要重新 grub-install 一下，原因是虽然 rootfs 分区 UUID 没有变，但是 Disk UUID 变了，所以需要把新的 EFI executable path 写到 NVRAM 里面，要不然 BIOS 不知道。\n\n打包数据\n为什么上面这个 dmesg 没有存档呢？因为后续在 rsync Windows 数据到 NAS 备份盘的时候，发现了更加惊悚的一幕：\n第一反应是线又坏了：前往小米之家购买了高级本命红颜色数据线，并且从 ntfs3g 更换为 ntfs3，还是爆炸，并且炸的更加严重，rsync 会直接彻底卡死。多次运行后注意到坏掉的 sector 稳定，所以真的是坏道了，而且 ntfs3 遇到坏道以后状态会直接爆炸，后续没办法再处理任何读取：\n所以为了至少救一点数据出来，换回了 ntfs3g。还好只有一个文件坏了，而且做了 Parchive，所以可以修回来，不过还是挺哈人的…\nSMART 信息如下，应该已经坏了很久了。这台机器的 SMART 通知用的 SMTP 服务器挂了（自建 SMTP 服务器 TLS 证书过期，Certbot 没有正确执行 Hook 把 maddy 重启），所以没收到通知…\nSMART Attributes Data Structure revision number: 10\nVendor Specific SMART Attributes with Thresholds:\nID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE\n  1 Raw_Read_Error_Rate     0x010f   084   062   ---    Pre-fail  Always       -       601824\n  3 Spin_Up_Time            0x0103   088   086   ---    Pre-fail  Always       -       0\n  4 Start_Stop_Count        0x0032   086   086   ---    Old_age   Always       -       14941\n  5 Reallocated_Sector_Ct   0x0133   099   099   ---    Pre-fail  Always       -       208\n  7 Seek_Error_Rate         0x000f   089   060   ---    Pre-fail  Always       -       908686414\n  9 Power_On_Hours          0x0032   051   051   ---    Old_age   Always       -       43564\n 10 Spin_Retry_Count        0x0013   100   100   ---    Pre-fail  Always       -       0\n 12 Power_Cycle_Count       0x0032   100   100   ---    Old_age   Always       -       162\n184 End-to-End_Error        0x0032   100   100   ---    Old_age   Always       -       0\n187 Reported_Uncorrect      0x0032   001   001   ---    Old_age   Always       -       137\n188 Command_Timeout         0x0032   100   001   ---    Old_age   Always       -       4522669620495\n189 High_Fly_Writes         0x003a   055   055   ---    Old_age   Always       -       45\n190 Airflow_Temperature_Cel 0x0022   059   029   ---    Old_age   Always       -       41 (Min/Max 41/71)\n191 G-Sense_Error_Rate      0x0032   100   100   ---    Old_age   Always       -       0\n192 Power-Off_Retract_Count 0x0032   100   100   ---    Old_age   Always       -       128\n193 Load_Cycle_Count        0x0032   093   093   ---    Old_age   Always       -       15979\n194 Temperature_Celsius     0x0022   041   071   ---    Old_age   Always       -       41 (0 13 0 0 0)\n195 Hardware_ECC_Recovered  0x001a   036   003   ---    Old_age   Always       -       601824\n196 Reallocated_Event_Count 0x0032   000   000   ---    Old_age   Always       -       57167\n197 Current_Pending_Sector  0x0012   100   100   ---    Old_age   Always       -       27\n198 Offline_Uncorrectable   0x0010   100   100   ---    Old_age   Offline      -       0\n199 UDMA_CRC_Error_Count    0x003e   200   200   ---    Old_age   Always       -       0\n240 Head_Flying_Hours       0x0000   100   253   ---    Old_age   Offline      -       20053 (226 47 0)\n241 Total_LBAs_Written      0x0000   100   253   ---    Old_age   Offline      -       14240009369\n242 Total_LBAs_Read         0x0000   100   253   ---    Old_age   Offline      -       1115691404091\n\n\nWhat else\n除此之外还出现了一些搞笑情况，比如：\n- 在几乎同时，我工位上的工作站 990Pro 又掉盘了…我还以为是我手动为了损管给关了，结果第二天到了工位一看，怎么在 BIOS 里，Storage 空空的，这下坏了。\n- 断网检查了一圈没有恶意文件，然后网线一插，还是没网，心里一想坏了路由器上的脚本写炸了，结果排查了半天，最后发现是工位这一排的交换机电源线松了，然后是国庆所以无人注意到…欢迎报考世界一流大学计算机系.jpg\n- 学校提供的最新的 Windows 安装媒介镜像：\n  - 在小米之家购买 USB 线实录：\n我：咱们这有兼容 USB 3 或者 Thunerbolt 的数据线吗？ \n店员：…?\n我：咱这儿最好的数据线是啥？ \n店员：[拿来一个 A to C 的线] \n我：不不不，要 C to C 的\n接过 C to C 的线，翻过来看规格。 \n小米：规格 1A \n我：…?\n\n- 为了在 archiso 里面跑 gparted，安装了一个 gdm。结果 gdm 在启动图形界面的过程（包括创建 xdg 目录）不会有任何其他“忙碌”指示，需要干等大概两分钟，然后 archiso 又有一个特别长的 motd，导致我一直以为是 Xorg 哪里挂了…\nThe best part：如果这个时候切换 Terminal，gdm 会直接把 session 杀掉…\n  - 主机是一个 NUC10，所以主板 SATA 是个排线，经过这一晚上折腾最后松了，于是：\n  \nFinal remarks\n最后在群友的建议下购入了 HBA 卡，搞正经 NAS 了。\n对于诈骗本身而言，有一个很大的隐患是很多 Key 都在工作机上，而恶意软件被执行的时候是有一个活跃的 SSH 连接在一个窗口上的。如果恶意软件有远控能力的话，那很容易所有服务器都被打穿了。还好后续分析了一下就是个简单币圈诈骗软件，不过还是最好推进一下用 YubiKey 登录。\n不过在用电视工作的时候距离电脑 USB 口好远，不知道有没有远程 USB 的设备呢？USB/IP on RaspberryPi?\n"},{"metadata":{"id":"huairou-half-2025","lang":"zh-CN","title":"怀柔长城马拉松 2025 半马","tags":["走路猫"],"publish_time":"2025-09-21T23:32:33+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"怀","components":[["M 111 -663L 97 -663C 105 -595 76 -521 51 -491C 23 -469 9 -436 27 -404C 48 -369 102 -369 126 -403C 160 -449 166 -543 111 -663Z",[0.142,0.584]],["M 340 -837L 163 -854L 163 95L 191 95C 244 95 303 68 303 57L 303 -808C 331 -812 338 -823 340 -837Z",[0.004,0.849]],["M 314 -680L 304 -676C 326 -624 344 -553 339 -489C 437 -389 571 -586 314 -680Z",[-0.173,0.403]],["M 755 -738L 755 -754L 593 -754C 546 -565 438 -315 311 -158L 321 -150C 528 -296 684 -501 755 -738Z",[0.396,0.69]],["M 850 -849L 778 -754L 360 -754L 368 -726L 949 -726C 964 -726 975 -731 978 -742C 930 -785 850 -849 850 -849Z",[0.766,0.076]],["M 742 -520L 566 -559L 566 95L 587 94C 670 94 706 66 708 57L 708 -499C 729 -503 739 -510 742 -520Z",[0.007,0.766]],["M 749 -494L 739 -489C 784 -404 832 -296 846 -197C 978 -87 1093 -357 749 -494Z",[-0.219,0.427]]],"bbox":{"top":-854,"bottom":95,"left":9,"right":1093},"hadv":1000}],"text":"怀","hadv":1000,"breakAfter":true},{"chars":[{"char":"柔","components":[["M 357 -243C 294 -131 170 -8 17 66L 23 77C 259 19 449 -83 548 -227L 548 -243Z",[0.629,0.439]],["M 347 -598C 282 -505 164 -399 26 -334L 32 -323C 243 -373 429 -460 529 -582L 529 -598Z",[0.675,0.412]],["M 26 -243L 34 -215L 943 -215C 958 -215 969 -220 972 -231C 922 -274 840 -335 840 -335L 767 -243Z",[0.924,0.036]],["M 43 -598L 52 -570L 857 -570L 857 -598Z",[-0.949,0.002]],["M 141 -789L 150 -761L 764 -761L 764 -789Z",[-0.772,0.004]],["M 328 -732L 324 -721C 390 -693 425 -650 442 -615C 538 -510 781 -736 328 -732Z",[-0.591,0.234]],["M 477 -591L 477 -445C 477 -436 474 -429 459 -429C 438 -429 352 -435 352 -435L 352 -424C 402 -416 418 -403 431 -391C 446 -376 449 -353 451 -321C 603 -330 625 -362 625 -442L 625 -591Z",[0.139,0.329]],["M 420 -323L 420 93L 446 93C 505 93 570 70 570 61L 570 -279C 598 -283 605 -294 607 -307Z",[0.018,0.615]],["M 665 -789C 638 -751 584 -693 543 -657L 547 -651C 632 -667 753 -698 827 -727C 849 -729 859 -732 867 -741L 735 -866L 653 -789Z",[-0.603,0.011]],["M 570 -243L 561 -238C 622 -88 716 10 873 67C 888 -5 929 -54 983 -70L 985 -81C 828 -97 651 -152 570 -243Z",[-0.536,0.27]],["M 763 -598C 740 -551 690 -479 647 -433L 652 -427C 739 -450 854 -495 921 -537C 944 -538 954 -541 962 -551L 831 -675L 751 -598Z",[0.383,0.165]]],"bbox":{"top":-866,"bottom":93,"left":17,"right":985},"hadv":1000}],"text":"柔","hadv":1000,"breakAfter":true},{"chars":[{"char":"长","components":[["M 838 -543L 763 -441L 36 -441L 44 -413L 945 -413C 960 -413 971 -418 974 -429C 924 -475 838 -543 838 -543Z",[0.91,0.041]],["M 334 -782L 219 -782L 219 -132C 219 -105 211 -93 162 -60L 285 101C 316 76 349 12 315 -83L 241 -20L 372 -80L 372 -759Z",[0.022,0.815]],["M 197 -56L 291 82C 429 -9 528 -91 578 -139L 576 -147C 418 -106 265 -69 197 -56Z",[0.581,0.25]],["M 405 -836L 219 -857L 219 -737C 345 -737 367 -737 372 -737L 372 -814C 394 -817 403 -825 405 -836Z",[-0.774,0.072]],["M 854 -712L 695 -834C 617 -732 454 -581 301 -486L 307 -476C 504 -527 693 -621 814 -703C 837 -697 848 -703 854 -712Z",[0.595,0.395]],["M 498 -438L 486 -432C 542 -165 667 -27 850 71C 872 2 915 -42 976 -53L 978 -65C 779 -120 573 -222 498 -438Z",[-0.526,0.455]]],"bbox":{"top":-857,"bottom":101,"left":36,"right":978},"hadv":1000}],"text":"长","hadv":1000,"breakAfter":true},{"chars":[{"char":"城","components":[["M 13 -222L 80 -62C 93 -66 104 -78 108 -92C 232 -183 316 -256 366 -304L 363 -313C 220 -272 71 -234 13 -222Z",[0.541,0.284]],["M 28 -571L 36 -543L 348 -543C 361 -543 371 -548 374 -559C 345 -599 287 -663 287 -663L 236 -571Z",[0.842,0.09]],["M 114 -838L 114 -193L 249 -235L 249 -795C 277 -799 284 -809 286 -823Z",[0.011,0.78]],["M 335 -637L 335 -428C 335 -257 320 -68 188 82L 196 90C 445 -42 466 -264 466 -428L 466 -637L 486 -637L 335 -689L 335 -647Z",[0.126,0.781]],["M 523 -458C 520 -283 516 -205 501 -186C 497 -181 493 -180 486 -180C 473 -180 443 -181 418 -183L 418 -171C 446 -163 466 -147 476 -131C 486 -116 489 -89 489 -63C 529 -64 562 -70 588 -90C 631 -125 639 -211 643 -410C 662 -413 675 -421 681 -429L 574 -517L 513 -458Z",[0.115,0.658]],["M 430 -637L 430 -609L 950 -609C 965 -609 975 -614 978 -625C 935 -663 864 -716 864 -716L 802 -637Z",[-0.717,0.003]],["M 432 -458L 432 -430L 573 -430L 573 -458Z",[0.595,0.04]],["M 828 -524C 763 -234 652 -59 464 68L 472 82C 710 -18 846 -176 939 -454C 965 -453 975 -459 980 -472Z",[0.442,0.682]],["M 648 -841C 649 -515 658 -223 795 7C 824 55 905 117 968 78C 991 63 984 18 956 -55L 980 -234L 970 -236C 952 -193 928 -143 913 -117C 903 -100 897 -99 887 -116C 778 -275 772 -546 779 -796C 805 -799 814 -811 815 -824Z",[-0.192,0.789]],["M 795 -809L 788 -804C 809 -778 835 -733 842 -692C 949 -624 1050 -819 795 -809Z",[0.115,0.222]]],"bbox":{"top":-841,"bottom":117,"left":13,"right":1050},"hadv":1000}],"text":"城","hadv":1000,"breakAfter":true},{"chars":[{"char":"马","components":[["M 614 -297L 539 -201L 36 -201L 44 -173L 722 -173C 736 -173 748 -178 751 -189C 699 -233 614 -297 614 -297Z",[0.879,0.053]],["M 706 -797L 126 -797L 135 -769L 706 -769Z",[0.685,0.009]],["M 438 -690L 254 -725C 250 -654 220 -458 198 -374L 236 -412C 214 -404 188 -386 173 -370L 307 -299L 355 -362L 348 -362C 365 -444 393 -621 402 -689L 393 -665C 423 -664 435 -677 438 -690Z",[0.122,0.614]],["M 868 -390L 297 -390L 297 -362L 868 -362Z",[0.839,0.017]],["M 780 -390L 791 -390C 782 -198 768 -76 740 -54C 731 -47 723 -45 706 -45C 682 -45 599 -49 542 -53L 542 -43C 597 -32 640 -15 662 8C 684 28 689 57 689 97C 771 98 814 88 852 59C 909 16 929 -98 941 -336C 963 -339 975 -346 983 -355L 857 -463Z",[0.192,0.579]],["M 626 -797L 637 -797C 632 -691 618 -510 599 -374C 669 -363 719 -368 754 -388C 768 -494 783 -654 789 -744C 810 -748 823 -757 829 -765L 684 -871Z",[0.076,0.657]]],"bbox":{"top":-871,"bottom":98,"left":36,"right":983},"hadv":1000}],"text":"马","hadv":1000,"breakAfter":true},{"chars":[{"char":"拉","components":[["M 327 -839L 151 -855L 151 -91C 151 -80 146 -74 131 -74C 108 -74 7 -80 7 -80L 7 -67C 58 -56 79 -41 95 -16C 110 8 116 44 119 95C 271 80 291 24 291 -76L 291 -810C 316 -814 326 -824 327 -839Z",[0.038,0.826]],["M 18 -375L 70 -212C 83 -216 94 -228 99 -241C 253 -333 359 -409 423 -459L 421 -469C 258 -426 83 -387 18 -375Z",[0.605,0.274]],["M 329 -706L 270 -615L 20 -615L 28 -587L 404 -587C 418 -587 429 -592 431 -603C 395 -644 329 -706 329 -706Z",[0.796,0.083]],["M 851 -107L 775 -4L 333 -4L 341 24L 960 24C 975 24 986 19 989 8C 938 -38 851 -107 851 -107Z",[0.859,0.061]],["M 842 -717L 769 -620L 421 -620L 429 -592L 945 -592C 959 -592 971 -597 973 -608C 925 -652 842 -717 842 -717Z",[0.72,0.091]],["M 466 -532L 454 -527C 500 -394 496 -223 485 -119C 560 36 796 -215 466 -532Z",[-0.086,0.637]],["M 526 -854L 519 -849C 557 -801 591 -731 599 -664C 734 -563 863 -825 526 -854Z",[-0.209,0.27]],["M 921 -494L 727 -540C 718 -380 693 -146 662 19L 686 19C 772 -136 843 -338 882 -470C 907 -471 917 -481 921 -494Z",[0.192,0.707]]],"bbox":{"top":-855,"bottom":95,"left":7,"right":989},"hadv":1000}],"text":"拉","hadv":1000,"breakAfter":true},{"chars":[{"char":"松","components":[["M 289 -584L 289 -600L 151 -600C 130 -439 85 -257 11 -132L 22 -122C 159 -242 251 -397 289 -584Z",[0.285,0.701]],["M 357 -702L 295 -600L 22 -600L 30 -572L 437 -572C 452 -572 462 -577 465 -588C 428 -632 357 -702 357 -702Z",[0.751,0.08]],["M 341 -836L 164 -853L 164 95L 192 95C 245 95 304 67 304 56L 304 -807C 332 -811 339 -821 341 -836Z",[0.004,0.849]],["M 293 -471L 284 -466C 310 -416 335 -346 338 -282C 443 -189 566 -395 293 -471Z",[-0.2,0.384]],["M 784 -396L 596 -480C 578 -363 497 -157 444 -100C 432 -90 400 -82 400 -82L 450 92C 488 80 521 30 529 -61L 456 -61L 456 -47C 560 -120 694 -282 756 -392L 724 -384C 759 -373 778 -383 784 -396Z",[0.362,0.678]],["M 690 -765L 499 -812C 489 -656 455 -485 415 -369L 426 -362C 528 -451 601 -579 650 -742C 674 -743 686 -752 690 -765Z",[0.236,0.645]],["M 430 -82L 472 67C 655 4 797 -59 873 -97L 873 -108C 689 -94 504 -84 430 -82Z",[0.689,0.147]],["M 726 -263L 716 -258C 761 -162 806 -46 817 62C 960 188 1085 -106 726 -263Z",[-0.235,0.47]],["M 826 -812L 736 -858L 725 -854C 744 -585 791 -439 904 -339C 915 -393 956 -455 987 -483L 989 -495C 894 -542 797 -647 757 -799L 763 -752C 791 -775 813 -795 826 -812Z",[-0.241,0.628]]],"bbox":{"top":-858,"bottom":188,"left":11,"right":1085},"hadv":1000}],"text":"松","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"半","components":[["M 27 -271L 35 -243L 945 -243C 959 -243 971 -248 974 -259C 919 -305 829 -371 829 -371L 749 -271Z",[0.93,0.038]],["M 91 -494L 99 -466L 904 -466C 919 -466 930 -471 933 -482C 881 -525 795 -588 795 -588L 720 -494Z",[0.937,0.037]],["M 137 -806L 129 -801C 170 -734 207 -644 213 -560C 346 -448 477 -715 137 -806Z",[-0.216,0.427]],["M 420 -854L 420 95L 449 95C 507 95 573 58 573 43L 573 -807C 601 -811 608 -822 610 -836Z",[0.006,0.835]],["M 717 -820C 690 -720 652 -607 621 -539L 632 -531C 710 -579 791 -648 858 -728C 881 -726 896 -734 901 -746Z",[0.374,0.491]]],"bbox":{"top":-854,"bottom":95,"left":27,"right":974},"hadv":1000}],"text":"半","hadv":1000,"breakAfter":true},{"chars":[{"char":"马","components":[["M 614 -297L 539 -201L 36 -201L 44 -173L 722 -173C 736 -173 748 -178 751 -189C 699 -233 614 -297 614 -297Z",[0.879,0.053]],["M 706 -797L 126 -797L 135 -769L 706 -769Z",[0.685,0.009]],["M 438 -690L 254 -725C 250 -654 220 -458 198 -374L 236 -412C 214 -404 188 -386 173 -370L 307 -299L 355 -362L 348 -362C 365 -444 393 -621 402 -689L 393 -665C 423 -664 435 -677 438 -690Z",[0.122,0.614]],["M 868 -390L 297 -390L 297 -362L 868 -362Z",[0.839,0.017]],["M 780 -390L 791 -390C 782 -198 768 -76 740 -54C 731 -47 723 -45 706 -45C 682 -45 599 -49 542 -53L 542 -43C 597 -32 640 -15 662 8C 684 28 689 57 689 97C 771 98 814 88 852 59C 909 16 929 -98 941 -336C 963 -339 975 -346 983 -355L 857 -463Z",[0.192,0.579]],["M 626 -797L 637 -797C 632 -691 618 -510 599 -374C 669 -363 719 -368 754 -388C 768 -494 783 -654 789 -744C 810 -748 823 -757 829 -765L 684 -871Z",[0.076,0.657]]],"bbox":{"top":-871,"bottom":98,"left":36,"right":983},"hadv":1000}],"text":"马","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/huairou-2025-start.jpg"},"html":"<p>今天跑了怀柔长城马拉松的半马项目！非常感谢群友 <a href=\"https://harrychen.xyz/\">@Harry_Chen</a> 飙车把我送去，让我可以在起点前有余裕拍摄以下照片。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/huairou-2025-start.jpg\" class=\"preview\">\n  <figcaption>起点人群</figcaption>\n</figure>\n<h2>比赛</h2>\n<p>去年的怀柔长城半马是我第一次参加比较大规模的商业比赛，所以还是有一些亲切感的。参赛包和完赛包的内容也比较多，毛巾拖鞋甚至包本身都用到了现在，又获得了一个副本。TBH 它的完赛包是我用过最耐用的完赛包之一，过去一年常常用来装越野鞋用，直接打个结飞机托运都没问题。</p>\n<p>然而今年比赛主办感觉犯了一些奇妙失误，不知道是不是我稍微多跑了一些比赛能看出来了。最大的一个抱怨是居然起跑之后第一公里，有一个救护车和选手在同一个马路上慢慢往前开，感觉无比危险。以及稍微修改了路线（？）全马 21k 折返现在会穿过起点，正好和 1km 的位置重合，所以很多选手一开始一上来看到一个计时表就很懵，难道每 km 都要计时？几乎所有选手都跑过之后折返回去踩计时毯，非常混乱。最后，检录区要穿过起点，也不知道迟到的人怎么进去。然后进去之后又要走 3km 左右，直接热身了。</p>\n<p>关于赛道的吐槽比较多，说落差巨大，本比赛也确实因此比较知名。然而从偶尔跑定向的人角度来看，虽然一共有 130m 爬升，但是都比较缓，都可以下坡的时候把速度补回来 。只有一个大长坡在 17k 附近，大概掉配速 20s 左右，比起定向还只是洒洒水。</p>\n<h2>成绩</h2>\n<p>今天是纯摆烂，跑出了<a href=\"https://www.strava.com/activities/15882304769\">历史最菜成绩</a>，净时间都快到 135 了，但是其实主要原因是最后在 Literally 走路。</p>\n<p>本来因为最近没怎么训练，所以一开始就是冲着 130 左右跑的。不过更大的影响是昨天晚上因为喷射所以通了宵。通宵本身不是什么问题，上次通宵之后跑马拉松是今年年初石家庄马拉松，和这次就很像，都是住家里，然后身体不舒服，但是上次就跑出了 PB。更大的问题 Apparently 是肠胃还是处于爆炸的状态。到了 8km 左右的时候已经十分想吐了，按说提前一个小时吃早饭，也没吃啥东西，应该是没问题的。然而恶心了半天是一点胃酸都没吐出来，只能降速慢慢跑。这个时候还能维持 415 左右配速，然而到了 15km 的时候还是肚子疼，这就很麻烦了。随后走走停停，到了最后一公里走了八分钟，非常幽默。</p>\n<p>然而还是能从这次的表现中摘出一些感想的。到 8km 之前配速都可以稳定在 340 左右，感觉说明体能是有上升的，感觉是上个月跑的那些<a href=\"/post/o-tour-2025\">强度非常高</a>的<a href=\"/post/asjyoc2025-sr\">定向比赛</a>…但是太久没有跑这个距离了，节奏没有太掌握住。今年的目标是全马进 3, 看来耐力和配速控制是现在急须训练的东西。</p>\n<p>接下来下一场比应该是海淀全马，到时候又可以早上在家里呼呼大睡啦！</p>\n<h2>吐槽</h2>\n<p>志愿者服务特别到位，存包甚至让我存一瓶水，还是挺牛的。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/huairou-2025-bag.jpg\" class=\"preview\">\n  <figcaption>存包<ficaption>\n</figure>\n<p>跑完了直接进雁栖湖会展中心的高级厕所里蹲了 2h 坑，这下体验生活了。</p>\n<p>写这个博客的时候我已经快 48h 没睡觉了，立即精致睡眠！</p>\n","plain":"今天跑了怀柔长城马拉松的半马项目！非常感谢群友 @Harry_Chen 飙车把我送去，让我可以在起点前有余裕拍摄以下照片。\n\n比赛\n去年的怀柔长城半马是我第一次参加比较大规模的商业比赛，所以还是有一些亲切感的。参赛包和完赛包的内容也比较多，毛巾拖鞋甚至包本身都用到了现在，又获得了一个副本。TBH 它的完赛包是我用过最耐用的完赛包之一，过去一年常常用来装越野鞋用，直接打个结飞机托运都没问题。\n然而今年比赛主办感觉犯了一些奇妙失误，不知道是不是我稍微多跑了一些比赛能看出来了。最大的一个抱怨是居然起跑之后第一公里，有一个救护车和选手在同一个马路上慢慢往前开，感觉无比危险。以及稍微修改了路线（？）全马 21k 折返现在会穿过起点，正好和 1km 的位置重合，所以很多选手一开始一上来看到一个计时表就很懵，难道每 km 都要计时？几乎所有选手都跑过之后折返回去踩计时毯，非常混乱。最后，检录区要穿过起点，也不知道迟到的人怎么进去。然后进去之后又要走 3km 左右，直接热身了。\n关于赛道的吐槽比较多，说落差巨大，本比赛也确实因此比较知名。然而从偶尔跑定向的人角度来看，虽然一共有 130m 爬升，但是都比较缓，都可以下坡的时候把速度补回来 。只有一个大长坡在 17k 附近，大概掉配速 20s 左右，比起定向还只是洒洒水。\n\n成绩\n今天是纯摆烂，跑出了历史最菜成绩，净时间都快到 135 了，但是其实主要原因是最后在 Literally 走路。\n本来因为最近没怎么训练，所以一开始就是冲着 130 左右跑的。不过更大的影响是昨天晚上因为喷射所以通了宵。通宵本身不是什么问题，上次通宵之后跑马拉松是今年年初石家庄马拉松，和这次就很像，都是住家里，然后身体不舒服，但是上次就跑出了 PB。更大的问题 Apparently 是肠胃还是处于爆炸的状态。到了 8km 左右的时候已经十分想吐了，按说提前一个小时吃早饭，也没吃啥东西，应该是没问题的。然而恶心了半天是一点胃酸都没吐出来，只能降速慢慢跑。这个时候还能维持 415 左右配速，然而到了 15km 的时候还是肚子疼，这就很麻烦了。随后走走停停，到了最后一公里走了八分钟，非常幽默。\n然而还是能从这次的表现中摘出一些感想的。到 8km 之前配速都可以稳定在 340 左右，感觉说明体能是有上升的，感觉是上个月跑的那些强度非常高的定向比赛…但是太久没有跑这个距离了，节奏没有太掌握住。今年的目标是全马进 3, 看来耐力和配速控制是现在急须训练的东西。\n接下来下一场比应该是海淀全马，到时候又可以早上在家里呼呼大睡啦！\n\n吐槽\n志愿者服务特别到位，存包甚至让我存一瓶水，还是挺牛的。\n跑完了直接进雁栖湖会展中心的高级厕所里蹲了 2h 坑，这下体验生活了。\n写这个博客的时候我已经快 48h 没睡觉了，立即精致睡眠！\n"},{"metadata":{"id":"asjyoc2025-sr","lang":"zh-CN","title":"AsJYOC'25 Spectator Race","tags":["钻草丛","走路猫"],"publish_time":"2025-09-16T04:30:37+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"J","components":[["M 74 162C 131 162 194 140 248 75C 295 18 317 -49 317 -201L 317 -404C 317 -520 317 -636 321 -747L 151 -747C 154 -423 155 -298 155 -208C 155 -60 159 43 142 134L 142 142L 157 142L 157 136L 111 79C 76 40 58 33 23 33C -14 33 -42 49 -51 93C -44 142 -1 162 74 162Z",[0.111,0.745]],["M 43 -713L 204 -698L 246 -698L 409 -713L 409 -747L 43 -747Z",[-0.888,0.008]]],"bbox":{"top":-747,"bottom":162,"left":-51,"right":409},"hadv":442},{"char":"Y","components":[["M 15 -713L 174 -698L 221 -698L 361 -713L 361 -747L 15 -747Z",[-0.87,0.004]],["M 293 -250L 406 -250L 650 -747L 594 -747L 412 -348L 404 -330L 434 -330L 242 -747L 49 -747Z",[-0.142,0.172]],["M 169 -0L 545 -0L 545 -34L 378 -50L 332 -50L 169 -34Z",[-0.874,0.0]],["M 269 -0L 444 -0C 442 -105 442 -165 442 -347L 272 -347C 272 -163 272 -104 269 -0Z",[-0.001,0.51]],["M 475 -713L 585 -698L 610 -698L 709 -713L 709 -747L 475 -747Z",[-0.305,0.04]]],"bbox":{"top":-747,"bottom":0,"left":15,"right":709},"hadv":708},{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708}],"text":"AsJYOC","hadv":3926,"breakAfter":false},{"chars":[{"char":"'","components":[["M 127 -829C 78 -829 49 -801 49 -744C 49 -698 70 -628 79 -586L 111 -459L 144 -459L 177 -586C 185 -628 205 -696 205 -744C 205 -801 176 -829 127 -829Z",[-0.001,0.613]]],"bbox":{"top":-829,"bottom":-459,"left":49,"right":205},"hadv":255}],"text":"'","hadv":255,"breakAfter":false},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"25","hadv":1226,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Spectator","hadv":5034,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Race","hadv":2534,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/AsJYOC2025-SR-dist.png"},"html":"<style>\ndel {\n  opacity: .3;\n}\n</style>\n<p>前几天跟一群朋友一起去日本爱知县跑了<a href=\"https://web.archive.org/web/20250915161545/https://www.asjyoc2025.jp/spectator-races/\" title=\"考虑到日本的 IT，这链接放 Web Archive 了\">25年亚青赛的旁观者赛事</a>。</p>\n<p>其实本来要跑三场的：短接+中距+长距。结果某清提前一周才敲定博士面试的时间，只能把第一场咕咕了，机票 -1500。<small>其实当天又延迟了俩小时，差点我又没赶上飞机…</small>不过最后看图发现没亏很多——因为相比起来后两天实在太难了。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-dist.png\" class=\"preview\">\n  <figcaption>看到秩序册第一时间感想</figcaption>\n</figure>\n<p>第一天比较跑路，后两天，尤其是第三天强度是我跑过强度最高的比赛…本来以为这是好客爱知把最好的场地拿出来给最亲的国际友人，结果一看过两天的<a href=\"https://orienteering.or.jp/joc/2025/documents/\">全日本大会</a>比这还要长50%，看来是日本的一般通过全国级比赛水平？直接把国际友人都给干无效了。</p>\n<h2>Day 2 / 中距离</h2>\n<p>赛前看技术信息看的有点懵，3.8km 直距 300m 爬升，意味着也有 300m 下降，算下来平均 15% 坡度，感觉有点离谱。但是最后跑下来体感还不错，虽然挺累的但是至少相比<a href=\"o-tour-2025\">前两天遍地石头的场地</a>，至少跑爽了。总体来看地形比较明确，尤其是一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⊨</mo></mrow><annotation encoding=\"application/x-tex\">\\vDash</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6922em;\"></span><span class=\"mrel amsrm\">⊨</span></span></span></span> 形状的山脊线很明显，所以路线选择比较确定：指在特定技术水平下，选择的路线是比较显然的。我对我自己的技术不太自信，所以选择跑山脊小路比较多，比较稳。</p>\n<p>总之今天的失误比较少，跑得比较顺，还不错。</p>\n<p><a href=\"https://www.strava.com/activities/15633402951\">Strava</a>\n<a href=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day2.qrt\">QuickRoute</a></p>\n<figure class=\"raw\">\n  <a href=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day2.jpg\"><img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day2.jpg\" class=\"preview\"></a>\n</figure>\n<ul>\n<li>\n<p>0 -&gt; 1 -&gt; 2 跑大路，2 -&gt; 3 嗯爬了一个 45 度左右的坡，当时感觉这就是日本的场地吗难度上限太高了。Little did I know。</p>\n</li>\n<li>\n<p>3 -&gt; 4 是第一个失误。很神奇地看错了水沟，然而事实上从路口地上距离才跑了一半。这是第一次面对这个场地的“水渠”——它是真的有水的，不像国内的图，大多数就是个深一点的干涸冲沟。</p>\n</li>\n<li>\n<p>4 -&gt; 5 选择了一个非常保守的路线：沿着等高线慢慢溜然后走鞍部到山顶。不过还是小瞧了 5m 等高距的力量，等高线滑了半天感觉自己应该和对面山头在一个高度，然后根本没看到连过来的山头，只有峡谷对面的平地，然后往脚下一看鞍部在在底下四根的位置，我的高度正好是对面山顶所以根本没看到山。In hindsigh 最好的路线是早点下山直穿撞石堆的，不过当时还不清楚具体地形的长相。</p>\n</li>\n<li>\n<p>4 -&gt; 5 和 6 -&gt; 7 -&gt; 8 走河边灌木的一段可跑性巨差，但是面积太小了，所以一眼在图上其实看不出来。6 -&gt; 7 也许可以直接下到 7 底下的路上然后跑路，应该是更快的。</p>\n</li>\n<li>\n<p>8 画了个植被分界线。沿着山脊往上跑的过程中左看右看，哪里有植被分界线呢？实地两侧都是灌木。最后看懂了，这里是当小路用的：如果灌木中间踩出来了一个空隙，那当然是植被分界线了！对制图的理解又深入了一点点🙏。</p>\n</li>\n<li>\n<p>8 -&gt; 9 路上有个巨大的 2m 深的沟，which nobody expects，走到跟前直接被硬控 20s，得重新入图。之前老看 ACI 经常提到 <a href=\"https://en.wikipedia.org/wiki/Startle_response\">Startle effect</a>，感觉这是最接近的一次。</p>\n<p>在 9 进点附近有个日本选手脚踝力量巨好，直接滑等高线过去了，我是绕的山头，虽然这个点持平，但是三个点以内就被他甩开了，老跑山头的路线太亏爬高了。同一个选手在 10 -&gt; 11 -&gt; 12 下山以三倍于我的速度向下猛冲，感觉很难理解他们是怎么训练出来这种跑山和速降的能力的。</p>\n</li>\n<li>\n<p>11 -&gt; 12 -&gt; 13 没啥失误，就是地形很乱所以得慢慢走。看小地形找点还是很准的，可以相信地图。</p>\n</li>\n<li>\n<p>15 是我这辈子见过的路线上最陡的坡，打破了大概一个小时之前看到的 3 那个坡的记录。这也是场地里唯一一个围了蓝色警戒线的地方——主办方标记这地方可能会有 Fall hazard，真的是不能小瞧。</p>\n</li>\n</ul>\n<h2>Day 3 / 长距离</h2>\n<p>是 WRE，所以甚至有丢人 Livelox 路线回放。10.6km 625m 爬高，按爬升换算一下差不多至少是一个半马的体能消耗… 3h 有效时间只能说勉勉强强，事实上也证明在体能不充足的情况下，只要有一个大失误直接就超时无效了。</p>\n<p><a href=\"https://www.strava.com/activities/15643968750\">Strava</a>\n<a href=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3.qrt\">QuickRoute</a>\n<a href=\"https://www.livelox.com/Viewer/The-20th-anniversary-of-the-merger-of-Shitara-Town-orienteering-/M21E2?classId=1036643&amp;tab=player\">Livelox</a></p>\n<p>Livelox 上 ID 是喵喵。喜提了一个 M21E2 无效里面最快的（</p>\n<figure class=\"raw\">\n  <a href=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3.jpg\"><img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3.jpg\" class=\"preview\"></a>\n</figure>\n<ul>\n<li>\n<p>拿到图之前还在跟群友聊天，说 1:15000 10km 距离 A/B 图估计是绕两个圈把，根本不可能换图把，结果拿到图一翻面一看完全不一样，傻眼了。这 10km 是得全吃下来。</p>\n</li>\n<li>\n<p>2 -&gt; 3 没有看到别的更好的路线，只能沿着河边走了。河边非常难走，本身河床上石头比较多，两侧岸边比较高，所以经常要跨河反复横跳。到了较大的溪流上有类似河滩可以跑了，稍微好了一些。</p>\n<p>3 向上攻击点选定在靠北水渠在谷底的汇入点，一块绿林中间有一个特殊人造特征 （Charcoal burn pit，下图的黄色圈）。不过一开始跑过的时候没有看到，原因是 Charcoal burn pit 和起点处的照片不太一样，就是一个石堆，从外面跑过的话其实看不到里面是个坑，也没有烧火的痕迹。根据北侧小溪转弯以及数左侧山上下来的小溪知道自己跑过了，所以攻击点切换到下一个特殊人造特征上，以及左手侧比较密集的小溪/湿地上（下图橙色的圈），不过这个时候还只是以为自己没看到特殊人造特征，而不是根本搞错了应该找的东西，所以当然还是没找到。在附近犹豫了很久，从配速可以看出来，不过无法分辨自己的站立点是在真实位置（新的攻击点）还是偏北位置（原来的攻击点），这个时候看到前面跑过来很多人，索性直接跑 4 然后回去找 3 了。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3-3.png\" class=\"preview\">\n  <figcaption>3 号点细节</figcaption>\n</figure>\n<p>不过这样的结果是估计至少浪费了 6 分钟，这个点跑了 21 分钟。一个更合理的做法是直接根据小溪拐弯的地方打针向上攻 3 上方的山头，应该好找很多。Meanwhile 写这篇总结的时候饭 Livelox 看到本地高手直接滑等高线直穿，让我开了眼界。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3-3-alt.png\" class=\"preview\">\n  <figcaption>可我不一样，我笨笨的.jpg<figcaption>\n</figure>\n</li>\n<li>\n<p>4 -&gt; 5 路线选择还是比较满意的，最后多绕了一个圈，因为懒得爬山了。各位高手从北侧、南侧或者直穿都有，北侧感觉是比较稳妥的选择，沿两侧都是沿河谷，先上山再过一个山口鞍部然后拐弯下山就行。不过下到 5 南侧的河谷平地是真陡…非常哈人。</p>\n<p>因为进 5 看过一次了，所以 5 -&gt; 6 跑得巨快。</p>\n</li>\n<li>\n<p>7 -&gt; 8 可以很明显看到和高手之间的差距。高手全部都选择了跑山脊，最终耗时大约少 25% - 30% 左右。实际跑距应该差距不大，纯粹是节约了爬高和可跑性更好。跑山脊多过一次水站，也更好定位，需要消耗的精神集中力也更少，各个方面都是更优的选择。跑到这个时候已经走了思维惯式了，全都跑水渠，然后体能就被打爆了，后面开始严重掉速，所有点基本在相同路线下都要慢大概 20%。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3-8.png\" class=\"preview\">\n  <figcaption>7 -> 8 线路比较<figcaption>\n</figure>\n<p>说到水站，这一个 7 旁边的水站在理想路线选择上可以经过三次，设计的非常巧妙。</p>\n</li>\n<li>\n<p>12 -&gt; 13 也是类似，没有看明白 11 - 12 - 8 这条连线上的山脊，从山脊直接下回到 7 会快很多，相当于反着跑了刚刚 7 -&gt; 8 的理想路线选择。我选择的路线是先西侧下河谷（again，思维定势），然后滑等高线回到 7 这个山脊上，跑速相比之下下降很多。</p>\n</li>\n<li>\n<p>14 -&gt; 15 差点拐错了一个弯下错山脊，还好看台地形状感觉不对这山脊有点肥意识过来了。山脊真的很容易辨别不清呢！ <small><del>(Subtle foreshadowing)</del></small></p>\n</li>\n<li>\n<p>16 -&gt; 17 Livelox 上能看到两组路线选择，跑大路的比较多，跑水渠的也有，由于我对自己路跑比较自信所以跑了大路，然而上了路跑了两步就跑不动了，只能开始溜达吃<ruby>小甜嘴<rt>能量胶</rt></ruby>。</p>\n<p>在图南侧差点出图，爬到了水渠南侧的山上，因为看错了石崖。<small><del>(Another subtle foreshadowing)</del></small>。</p>\n</li>\n<li>\n<p>第二张图开始部分还是挺满意的，运气也比较好，19 和 22 都是立刻直接找到了，这两个点都藏在坑里比较难看到。20 -&gt; 21 有一点失误，那块儿地形有点太乱了，走着走着就丢失站立点了，但是也是直接撞道路上然后在根据路的走向定位即可，因为一开始去 18 的时候见过一次 21，所以这个点不会丢，只会多花大概一分钟时间。</p>\n</li>\n<li>\n<p><strong>22 -&gt; 23 是灾难到来的时刻，一击粉碎了我想在有效时间内回来的希望。</strong>22 出点时还有半个小时有效时间，到 23 路线选择比较直接，就是走山脊，出点的路线选择时撞南侧的山然后向西侧拐弯，上山脊。但是低估了南侧的山的高度 (Or vice versa，低估了 5m 等高距 again)，上到了北侧的山脊。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3-22.png\" class=\"preview\">\n  <figcaption>22 号点出点</figcaption>\n</figure>\n<p>这里我们分析估计是故意把这个山脊下方的图擦掉的，能分辨出来这个和正确路线不一样的地方在于：</p>\n<ul>\n<li>下坡远比正确路线要陡、深</li>\n<li>底下是一个河谷</li>\n</ul>\n<p>然而目标山脊南侧也有一个河谷，考虑到北侧河谷没有画，所以第一反应是走过了，下到南侧河谷里了，虽然在这个图中需要明显垂直一个山脊下山。但是真的在出图以后，重新定位的过程就是一个反复的 Confirmation bias 的过程。</p>\n<p>假设自己下方是图上的河谷的时候，选择的备选方案有两个：</p>\n<ul>\n<li>较好的情况：通过小溪的走势和水坝的位置，判断自己的位置，然后向北上山。</li>\n<li>较差的情况：走到可以看到湖的位置，这个时候应该正好在 24 正下方，然后 Backtrack</li>\n</ul>\n<p>因此有了“保底”的错误安全感，就慢慢往下游走，尝试比对水坝的方位，越比越不对劲，感觉走了好远还没看到湖也很不对，最后发现，诶，终点的大喇叭播放的流行音乐，怎么来自我的正南方呢？仔细一看图，坏了，估计是在北边一个山谷里，看到山谷有向北的水渠，判断出来里面也是个河谷。这个时候距离 22 出点已经有 15 分钟了。</p>\n<p>这个时候其实还是有机会有效的，然而从完全图外进图然后重定位是一个非常困难，或者说非常凭借运气的事情。从北侧爬山脊线是一个平均坡度大概 40 度 50m 爬升的坡，然后爬过去是基本完全不知道自己在哪里的，一度在 2 小时 48 分左右经过了 23 附近，不过这个时候无法判断自己是在 23 东侧还是西侧那个东北-西南走势的山脊上，猜了一下猜错了，走到了猜想的 23 的位置看到了一块儿空地，完成了重定位，这个流程多花了 8 分钟。最后在 24 也有一个小失误，走在了小溪的错误一边，不过这个不本质了，超时已经不可挽回。</p>\n</li>\n</ul>\n<hr />\n<p>最终抵达终点的时候超时了五分钟，还是挺可惜的。不过今天这个图的难度设置就是，在体能 Borderline 的情况下，就没有失误的容错空间。今天比较大的失误，大约只有两个：</p>\n<ul>\n<li>22 -&gt; 23 出图，大约 15 分钟。</li>\n<li>3 -&gt; 4 错失攻击点，大约 6 分钟。</li>\n</ul>\n<p>在一个最终比赛时间三小时的比赛中，不算很长的时间。</p>\n<h2>Final words</h2>\n<p>两天比赛算是提醒了喵喵存在的一些问题把。</p>\n<p>具体看 Day 3 的各个 Split 的话，在大段跑路的点我的体能还是能跟上的，然而爬升和下降比较大的点和精英选手差距较大。可能得多跑跑越野了，又可以找个理由出去玩了，嘻嘻。</p>\n<p>从技术角度，具体讨论这两张图的话，主要是大地形上，还是缺乏从纯等高线上重构地形的能力，这两天都能看出来，Day 2 即使跑得比较顺，对于目标地形高度的估计也和实际差距比较大。因为我还是从北京跑公园开始跑的，最熟悉的还是依赖植被和明显的线状特征物定位（路、河流）。比较可惜的是国内还是缺乏像这样比较靠纯等高线的地图。</p>\n<p>这场比赛如果能代表日本比赛的典型的制图水平和办赛水平的话，感觉还是挺不错的，至少比赛本身做的非常细致，图我们没有找到任何错误，小地形也都很准确，读图困难主要来自 1:15000 + 这个拧巴地形导致等高线过于密集，但是站定还是能看懂的。路线设计水平到位，Day 2 的标定爬高和我的真实爬高正好对应，Day 3 的水站设置也很合理。一个让我印象非常深刻的地方是，Day 3 在起点地方放了一个 Bulletin，特地说医疗站位置不是图上的标志正中心，原因是为了可读性挪动了标志。真正到了现场才知道为什么一定要贴个 Bulletin——从山下爬上去的过程中，在图上标志中心位置的水站是可以看到的，但是偏东北位置的真实位置得爬到山顶才能看到。这个细节我感觉是因为一定有人去验图了，并且注意到了这个细节。</p>\n<p>本来想国庆去全日本大会<del>顺便旅游</del>的。不过直到报名截止也没有找到便宜的国庆非日本往返的机票，而且也没有人一起去，最终不了了之，还是感觉比较可惜。下一场全国乱跑的比赛估计是<del>学生赛</del>学生赛现在还没一点动静十二成是没了，下一场比赛是年末的香港锦标赛，准备到时候去玩！</p>\n<h2>吐槽</h2>\n<p>本来不抱过高期待点了盒饭，但是盒饭其实非常好吃！</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day2-lunch.jpg\" class=\"preview\">\n  <figcaption>Day 2 盒饭<figcaption>\n</figure>\n<p>Day 3 因为有熊出没所以主办方必须要求有熊铃，而且距离还长，我比较怕死所以特地买了水袋和越野背包，最终第三天身上装了好多东西。</p>\n<style>\n.post .figure-line-2 img {\n  max-width: 50%;\n}\n</style>\n<figure>\n  <div class=\"figure-line-2\">\n    <img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day2-outfit.jpg\"><img src=\"https://layered-assets.thu.fail/AsJYOC2025-SR-day3-outfit.jpg\">\n  </div>\n  <figcaption>Day2 摸鱼出装 vs. Day3 怕死出装</figcaption>\n</figure>\n<p>比赛跑完了又在京都玩了三天，游记还有比赛的录像剪辑后续再补！</p>\n","plain":"前几天跟一群朋友一起去日本爱知县跑了25年亚青赛的旁观者赛事。\n其实本来要跑三场的：短接+中距+长距。结果某清提前一周才敲定博士面试的时间，只能把第一场咕咕了，机票 -1500。其实当天又延迟了俩小时，差点我又没赶上飞机…不过最后看图发现没亏很多——因为相比起来后两天实在太难了。\n第一天比较跑路，后两天，尤其是第三天强度是我跑过强度最高的比赛…本来以为这是好客爱知把最好的场地拿出来给最亲的国际友人，结果一看过两天的全日本大会比这还要长50%，看来是日本的一般通过全国级比赛水平？直接把国际友人都给干无效了。\n\nDay 2 / 中距离\n赛前看技术信息看的有点懵，3.8km 直距 300m 爬升，意味着也有 300m 下降，算下来平均 15% 坡度，感觉有点离谱。但是最后跑下来体感还不错，虽然挺累的但是至少相比前两天遍地石头的场地，至少跑爽了。总体来看地形比较明确，尤其是一个 \\vDash 形状的山脊线很明显，所以路线选择比较确定：指在特定技术水平下，选择的路线是比较显然的。我对我自己的技术不太自信，所以选择跑山脊小路比较多，比较稳。\n总之今天的失误比较少，跑得比较顺，还不错。\nStrava QuickRoute\n- 0 -> 1 -> 2 跑大路，2 -> 3 嗯爬了一个 45 度左右的坡，当时感觉这就是日本的场地吗难度上限太高了。Little did I know。\n\n- 3 -> 4 是第一个失误。很神奇地看错了水沟，然而事实上从路口地上距离才跑了一半。这是第一次面对这个场地的“水渠”——它是真的有水的，不像国内的图，大多数就是个深一点的干涸冲沟。\n\n- 4 -> 5 选择了一个非常保守的路线：沿着等高线慢慢溜然后走鞍部到山顶。不过还是小瞧了 5m 等高距的力量，等高线滑了半天感觉自己应该和对面山头在一个高度，然后根本没看到连过来的山头，只有峡谷对面的平地，然后往脚下一看鞍部在在底下四根的位置，我的高度正好是对面山顶所以根本没看到山。In hindsigh 最好的路线是早点下山直穿撞石堆的，不过当时还不清楚具体地形的长相。\n\n- 4 -> 5 和 6 -> 7 -> 8 走河边灌木的一段可跑性巨差，但是面积太小了，所以一眼在图上其实看不出来。6 -> 7 也许可以直接下到 7 底下的路上然后跑路，应该是更快的。\n\n- 8 画了个植被分界线。沿着山脊往上跑的过程中左看右看，哪里有植被分界线呢？实地两侧都是灌木。最后看懂了，这里是当小路用的：如果灌木中间踩出来了一个空隙，那当然是植被分界线了！对制图的理解又深入了一点点🙏。\n\n- 8 -> 9 路上有个巨大的 2m 深的沟，which nobody expects，走到跟前直接被硬控 20s，得重新入图。之前老看 ACI 经常提到 Startle effect，感觉这是最接近的一次。\n在 9 进点附近有个日本选手脚踝力量巨好，直接滑等高线过去了，我是绕的山头，虽然这个点持平，但是三个点以内就被他甩开了，老跑山头的路线太亏爬高了。同一个选手在 10 -> 11 -> 12 下山以三倍于我的速度向下猛冲，感觉很难理解他们是怎么训练出来这种跑山和速降的能力的。\n\n- 11 -> 12 -> 13 没啥失误，就是地形很乱所以得慢慢走。看小地形找点还是很准的，可以相信地图。\n\n- 15 是我这辈子见过的路线上最陡的坡，打破了大概一个小时之前看到的 3 那个坡的记录。这也是场地里唯一一个围了蓝色警戒线的地方——主办方标记这地方可能会有 Fall hazard，真的是不能小瞧。\n\n\nDay 3 / 长距离\n是 WRE，所以甚至有丢人 Livelox 路线回放。10.6km 625m 爬高，按爬升换算一下差不多至少是一个半马的体能消耗… 3h 有效时间只能说勉勉强强，事实上也证明在体能不充足的情况下，只要有一个大失误直接就超时无效了。\nStrava QuickRoute Livelox\nLivelox 上 ID 是喵喵。喜提了一个 M21E2 无效里面最快的（\n- 拿到图之前还在跟群友聊天，说 1:15000 10km 距离 A/B 图估计是绕两个圈把，根本不可能换图把，结果拿到图一翻面一看完全不一样，傻眼了。这 10km 是得全吃下来。\n\n- 2 -> 3 没有看到别的更好的路线，只能沿着河边走了。河边非常难走，本身河床上石头比较多，两侧岸边比较高，所以经常要跨河反复横跳。到了较大的溪流上有类似河滩可以跑了，稍微好了一些。\n3 向上攻击点选定在靠北水渠在谷底的汇入点，一块绿林中间有一个特殊人造特征 （Charcoal burn pit，下图的黄色圈）。不过一开始跑过的时候没有看到，原因是 Charcoal burn pit 和起点处的照片不太一样，就是一个石堆，从外面跑过的话其实看不到里面是个坑，也没有烧火的痕迹。根据北侧小溪转弯以及数左侧山上下来的小溪知道自己跑过了，所以攻击点切换到下一个特殊人造特征上，以及左手侧比较密集的小溪/湿地上（下图橙色的圈），不过这个时候还只是以为自己没看到特殊人造特征，而不是根本搞错了应该找的东西，所以当然还是没找到。在附近犹豫了很久，从配速可以看出来，不过无法分辨自己的站立点是在真实位置（新的攻击点）还是偏北位置（原来的攻击点），这个时候看到前面跑过来很多人，索性直接跑 4 然后回去找 3 了。\n不过这样的结果是估计至少浪费了 6 分钟，这个点跑了 21 分钟。一个更合理的做法是直接根据小溪拐弯的地方打针向上攻 3 上方的山头，应该好找很多。Meanwhile 写这篇总结的时候饭 Livelox 看到本地高手直接滑等高线直穿，让我开了眼界。\n\n- 4 -> 5 路线选择还是比较满意的，最后多绕了一个圈，因为懒得爬山了。各位高手从北侧、南侧或者直穿都有，北侧感觉是比较稳妥的选择，沿两侧都是沿河谷，先上山再过一个山口鞍部然后拐弯下山就行。不过下到 5 南侧的河谷平地是真陡…非常哈人。\n因为进 5 看过一次了，所以 5 -> 6 跑得巨快。\n\n- 7 -> 8 可以很明显看到和高手之间的差距。高手全部都选择了跑山脊，最终耗时大约少 25% - 30% 左右。实际跑距应该差距不大，纯粹是节约了爬高和可跑性更好。跑山脊多过一次水站，也更好定位，需要消耗的精神集中力也更少，各个方面都是更优的选择。跑到这个时候已经走了思维惯式了，全都跑水渠，然后体能就被打爆了，后面开始严重掉速，所有点基本在相同路线下都要慢大概 20%。\n说到水站，这一个 7 旁边的水站在理想路线选择上可以经过三次，设计的非常巧妙。\n\n- 12 -> 13 也是类似，没有看明白 11 - 12 - 8 这条连线上的山脊，从山脊直接下回到 7 会快很多，相当于反着跑了刚刚 7 -> 8 的理想路线选择。我选择的路线是先西侧下河谷（again，思维定势），然后滑等高线回到 7 这个山脊上，跑速相比之下下降很多。\n\n- 14 -> 15 差点拐错了一个弯下错山脊，还好看台地形状感觉不对这山脊有点肥意识过来了。山脊真的很容易辨别不清呢！ (Subtle foreshadowing)\n\n- 16 -> 17 Livelox 上能看到两组路线选择，跑大路的比较多，跑水渠的也有，由于我对自己路跑比较自信所以跑了大路，然而上了路跑了两步就跑不动了，只能开始溜达吃小甜嘴能量胶。\n在图南侧差点出图，爬到了水渠南侧的山上，因为看错了石崖。(Another subtle foreshadowing)。\n\n- 第二张图开始部分还是挺满意的，运气也比较好，19 和 22 都是立刻直接找到了，这两个点都藏在坑里比较难看到。20 -> 21 有一点失误，那块儿地形有点太乱了，走着走着就丢失站立点了，但是也是直接撞道路上然后在根据路的走向定位即可，因为一开始去 18 的时候见过一次 21，所以这个点不会丢，只会多花大概一分钟时间。\n\n- 22 -> 23 是灾难到来的时刻，一击粉碎了我想在有效时间内回来的希望。22 出点时还有半个小时有效时间，到 23 路线选择比较直接，就是走山脊，出点的路线选择时撞南侧的山然后向西侧拐弯，上山脊。但是低估了南侧的山的高度 (Or vice versa，低估了 5m 等高距 again)，上到了北侧的山脊。\n这里我们分析估计是故意把这个山脊下方的图擦掉的，能分辨出来这个和正确路线不一样的地方在于：\n- 下坡远比正确路线要陡、深\n- 底下是一个河谷\n然而目标山脊南侧也有一个河谷，考虑到北侧河谷没有画，所以第一反应是走过了，下到南侧河谷里了，虽然在这个图中需要明显垂直一个山脊下山。但是真的在出图以后，重新定位的过程就是一个反复的 Confirmation bias 的过程。\n假设自己下方是图上的河谷的时候，选择的备选方案有两个：\n- 较好的情况：通过小溪的走势和水坝的位置，判断自己的位置，然后向北上山。\n- 较差的情况：走到可以看到湖的位置，这个时候应该正好在 24 正下方，然后 Backtrack\n因此有了“保底”的错误安全感，就慢慢往下游走，尝试比对水坝的方位，越比越不对劲，感觉走了好远还没看到湖也很不对，最后发现，诶，终点的大喇叭播放的流行音乐，怎么来自我的正南方呢？仔细一看图，坏了，估计是在北边一个山谷里，看到山谷有向北的水渠，判断出来里面也是个河谷。这个时候距离 22 出点已经有 15 分钟了。\n这个时候其实还是有机会有效的，然而从完全图外进图然后重定位是一个非常困难，或者说非常凭借运气的事情。从北侧爬山脊线是一个平均坡度大概 40 度 50m 爬升的坡，然后爬过去是基本完全不知道自己在哪里的，一度在 2 小时 48 分左右经过了 23 附近，不过这个时候无法判断自己是在 23 东侧还是西侧那个东北-西南走势的山脊上，猜了一下猜错了，走到了猜想的 23 的位置看到了一块儿空地，完成了重定位，这个流程多花了 8 分钟。最后在 24 也有一个小失误，走在了小溪的错误一边，不过这个不本质了，超时已经不可挽回。\n\n---\n最终抵达终点的时候超时了五分钟，还是挺可惜的。不过今天这个图的难度设置就是，在体能 Borderline 的情况下，就没有失误的容错空间。今天比较大的失误，大约只有两个：\n- 22 -> 23 出图，大约 15 分钟。\n- 3 -> 4 错失攻击点，大约 6 分钟。\n在一个最终比赛时间三小时的比赛中，不算很长的时间。\n\nFinal words\n两天比赛算是提醒了喵喵存在的一些问题把。\n具体看 Day 3 的各个 Split 的话，在大段跑路的点我的体能还是能跟上的，然而爬升和下降比较大的点和精英选手差距较大。可能得多跑跑越野了，又可以找个理由出去玩了，嘻嘻。\n从技术角度，具体讨论这两张图的话，主要是大地形上，还是缺乏从纯等高线上重构地形的能力，这两天都能看出来，Day 2 即使跑得比较顺，对于目标地形高度的估计也和实际差距比较大。因为我还是从北京跑公园开始跑的，最熟悉的还是依赖植被和明显的线状特征物定位（路、河流）。比较可惜的是国内还是缺乏像这样比较靠纯等高线的地图。\n这场比赛如果能代表日本比赛的典型的制图水平和办赛水平的话，感觉还是挺不错的，至少比赛本身做的非常细致，图我们没有找到任何错误，小地形也都很准确，读图困难主要来自 1:15000 + 这个拧巴地形导致等高线过于密集，但是站定还是能看懂的。路线设计水平到位，Day 2 的标定爬高和我的真实爬高正好对应，Day 3 的水站设置也很合理。一个让我印象非常深刻的地方是，Day 3 在起点地方放了一个 Bulletin，特地说医疗站位置不是图上的标志正中心，原因是为了可读性挪动了标志。真正到了现场才知道为什么一定要贴个 Bulletin——从山下爬上去的过程中，在图上标志中心位置的水站是可以看到的，但是偏东北位置的真实位置得爬到山顶才能看到。这个细节我感觉是因为一定有人去验图了，并且注意到了这个细节。\n本来想国庆去全日本大会顺便旅游的。不过直到报名截止也没有找到便宜的国庆非日本往返的机票，而且也没有人一起去，最终不了了之，还是感觉比较可惜。下一场全国乱跑的比赛估计是学生赛学生赛现在还没一点动静十二成是没了，下一场比赛是年末的香港锦标赛，准备到时候去玩！\n\n吐槽\n本来不抱过高期待点了盒饭，但是盒饭其实非常好吃！\nDay 3 因为有熊出没所以主办方必须要求有熊铃，而且距离还长，我比较怕死所以特地买了水袋和越野背包，最终第三天身上装了好多东西。\n比赛跑完了又在京都玩了三天，游记还有比赛的录像剪辑后续再补！\n"},{"metadata":{"id":"o-tour-2025","lang":"zh-CN","title":"O-Tour 2025 长三角/盱眙","tags":["钻草丛","走路猫"],"publish_time":"2025-08-26T01:44:19+08:00","update_time":"2025-08-27T04:19:24+08:00","title_outline":{"groups":[{"chars":[{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795}],"text":"O","hadv":795,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Tour","hadv":2562,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"长","components":[["M 838 -543L 763 -441L 36 -441L 44 -413L 945 -413C 960 -413 971 -418 974 -429C 924 -475 838 -543 838 -543Z",[0.91,0.041]],["M 334 -782L 219 -782L 219 -132C 219 -105 211 -93 162 -60L 285 101C 316 76 349 12 315 -83L 241 -20L 372 -80L 372 -759Z",[0.022,0.815]],["M 197 -56L 291 82C 429 -9 528 -91 578 -139L 576 -147C 418 -106 265 -69 197 -56Z",[0.581,0.25]],["M 405 -836L 219 -857L 219 -737C 345 -737 367 -737 372 -737L 372 -814C 394 -817 403 -825 405 -836Z",[-0.774,0.072]],["M 854 -712L 695 -834C 617 -732 454 -581 301 -486L 307 -476C 504 -527 693 -621 814 -703C 837 -697 848 -703 854 -712Z",[0.595,0.395]],["M 498 -438L 486 -432C 542 -165 667 -27 850 71C 872 2 915 -42 976 -53L 978 -65C 779 -120 573 -222 498 -438Z",[-0.526,0.455]]],"bbox":{"top":-857,"bottom":101,"left":36,"right":978},"hadv":1000}],"text":"长","hadv":1000,"breakAfter":true},{"chars":[{"char":"三","components":[["M 834 -143L 751 -38L 29 -38L 37 -10L 953 -10C 968 -10 980 -15 983 -26C 927 -73 834 -143 834 -143Z",[0.913,0.042]],["M 781 -835L 700 -732L 81 -732L 89 -704L 898 -704C 913 -704 925 -709 928 -720C 873 -766 781 -835 781 -835Z",[0.788,0.056]],["M 713 -500L 634 -401L 146 -401L 154 -373L 825 -373C 840 -373 852 -378 855 -389C 801 -434 713 -500 713 -500Z",[0.893,0.053]]],"bbox":{"top":-835,"bottom":-10,"left":29,"right":983},"hadv":1000}],"text":"三","hadv":1000,"breakAfter":true},{"chars":[{"char":"角","components":[["M 184 -589L 184 -358C 184 -201 167 -38 28 89L 34 97C 302 -13 326 -204 326 -358L 326 -579L 347 -579L 207 -626Z",[0.133,0.748]],["M 504 -806L 308 -856C 258 -716 144 -557 29 -472L 35 -464C 207 -526 367 -656 463 -792C 492 -790 500 -795 504 -806Z",[0.496,0.521]],["M 759 -238L 265 -238L 265 -210L 759 -210Z",[0.917,0.004]],["M 759 -411L 265 -411L 265 -383L 759 -383Z",[0.867,0.005]],["M 759 -579L 265 -579L 265 -551L 759 -551Z",[0.762,0.015]],["M 619 -728L 326 -728L 306 -700L 619 -700Z",[0.627,0.041]],["M 589 22L 589 -571L 454 -561L 454 58L 479 58C 547 58 589 30 589 22Z",[0.002,0.798]],["M 567 -728L 579 -728C 562 -688 522 -610 488 -568L 499 -568C 576 -593 664 -640 727 -679C 748 -681 758 -684 767 -693L 641 -801Z",[0.373,0.358]],["M 712 -579L 722 -579L 722 -81C 722 -69 718 -62 703 -62C 683 -62 592 -67 592 -67L 592 -54C 640 -45 658 -29 673 -8C 687 13 692 47 695 94C 846 81 867 29 867 -65L 867 -531C 885 -535 896 -543 902 -550L 774 -648Z",[0.05,0.746]]],"bbox":{"top":-856,"bottom":97,"left":28,"right":902},"hadv":1000}],"text":"角","hadv":1000,"breakAfter":false},{"chars":[{"char":"/","components":[["M 26 181L 96 181L 399 -804L 330 -804Z",[0.277,0.894]]],"bbox":{"top":-804,"bottom":181,"left":26,"right":399},"hadv":425}],"text":"/","hadv":425,"breakAfter":true},{"chars":[{"char":"盱","components":[["M 54 -763L 54 23L 75 23C 134 23 184 -9 184 -25L 184 -735L 348 -735L 348 -763L 188 -763L 54 -819Z",[0.03,0.802]],["M 126 -351L 126 -323L 353 -323L 353 -351Z",[0.821,0.003]],["M 126 -563L 126 -535L 353 -535L 353 -563Z",[0.589,0.016]],["M 126 -135L 126 -107L 353 -107L 353 -135Z",[0.873,0.001]],["M 262 -763L 262 -23L 284 -23C 333 -23 397 -53 398 -62L 398 -714C 418 -718 431 -726 438 -735L 315 -832L 252 -763Z",[0.007,0.823]],["M 413 -425L 421 -397L 966 -397C 981 -397 992 -402 995 -413C 947 -457 866 -522 866 -522L 794 -425Z",[0.857,0.065]],["M 601 -758L 601 -93C 601 -82 596 -74 580 -74C 554 -74 436 -81 436 -81L 436 -69C 497 -58 519 -40 537 -18C 556 5 562 43 564 94C 730 83 756 12 756 -88L 756 -758Z",[0.051,0.775]],["M 437 -758L 445 -730L 933 -730C 947 -730 959 -735 961 -746C 915 -789 836 -854 836 -854L 767 -758Z",[0.81,0.059]]],"bbox":{"top":-854,"bottom":94,"left":54,"right":995},"hadv":1000}],"text":"盱","hadv":1000,"breakAfter":true},{"chars":[{"char":"眙","components":[["M 178 -5L 178 -730L 309 -730L 309 -758L 182 -758L 55 -811L 55 40L 75 40C 131 40 178 10 178 -5Z",[0.022,0.825]],["M 316 -340L 118 -340L 118 -312L 316 -312Z",[-0.848,0.017]],["M 317 -123L 119 -123L 119 -95L 317 -95Z",[-0.874,0.004]],["M 317 -553L 119 -553L 119 -525L 317 -525Z",[-0.811,0.014]],["M 250 -758L 260 -758L 260 -1L 280 -1C 325 -1 384 -29 385 -38L 385 -712C 404 -716 416 -724 422 -731L 309 -822Z",[0.006,0.839]],["M 798 -793L 599 -854C 577 -757 489 -584 430 -537C 418 -528 391 -522 391 -522L 441 -362C 475 -374 504 -417 511 -502L 444 -502L 444 -489C 554 -549 702 -683 771 -785L 738 -775C 775 -768 793 -779 798 -793Z",[0.431,0.605]],["M 423 -521L 461 -382C 646 -430 794 -479 875 -509L 875 -521C 687 -518 499 -518 423 -521Z",[0.747,0.091]],["M 454 -366L 454 95L 478 95C 545 95 585 73 585 64L 585 -285L 769 -285L 769 83L 794 83C 865 83 907 60 907 54L 907 -275C 930 -279 940 -286 947 -295L 829 -385L 765 -313L 596 -313ZM 824 -32L 545 -32L 545 -4L 824 -4Z",[0.203,0.027]],["M 740 -685L 731 -679C 785 -608 831 -508 840 -416C 975 -305 1099 -588 740 -685Z",[-0.178,0.363]]],"bbox":{"top":-854,"bottom":95,"left":55,"right":1099},"hadv":1000}],"text":"眙","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/o-tour-2025-day0.jpg"},"html":"<p>这几天去盱眙跑了今年的长三角三日赛，最后一天喜提一个崴脚。简单做一下复盘。</p>\n<h2>Day 0 / 计时赛</h2>\n<p>报道第一天有长三角传统项目计时赛，赛制 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≈</mo></mrow><annotation encoding=\"application/x-tex\">\\approx</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4831em;\"></span><span class=\"mrel\">≈</span></span></span></span> 全点积分，还是十分好玩的，可惜国内并没有很多计时赛。</p>\n<p><a href=\"https://www.strava.com/activities/15545023822\">Strava</a></p>\n<figure class=\"raw\">\n  <img src=\"https://layered-assets.thu.fail/o-tour-2025-day0.jpg\" class=\"preview\">\n</figure>\n<p>首先说路线选择。这张图上有两个比较麻烦的问题：44,49,57 没有很明显的收的办法，以及 36 爬回山上其实非常亏爬高。一开始看图的时候其实没看懂 36，50 和 45 的相对高度关系，以及粗略读图的时候直接把村子所在的谷当成基本不可穿越的了。不过碰巧这样跑的结果是把 49 和 57 收掉了，最后 44 从终点稍微绕了一点也可以拿到，所以不算特别倒闭。In hindsight, 更好的方式可能是:</p>\n<ul>\n<li>50 和 41 它们一起收</li>\n<li>直接 54 -&gt; 36 -&gt; 45 -&gt; 35，回头上路 57 -&gt; 49 -&gt; 44，穿一点绿到 31。</li>\n</ul>\n<p>一些更细节的路线选择问题:</p>\n<ul>\n<li>54 -&gt; 36 直穿滑等高线，灌木非常难走，还不如沿路到 50 下面然后再下呢。</li>\n<li>51 -&gt; 48 从山脊反面的谷进，找点比较容易，但是也是因为地面比较杂乱速度较慢，还不如翻山。</li>\n</ul>\n<p>最后是一些进点的失误：</p>\n<ul>\n<li>51 平行错误，对前进的距离估计不足，在南侧的台地转了一小会儿，其实在北侧更高的台地上。间接原因是小路不明显，以为到了小路尽头了。</li>\n<li>54 也类似，根本看不见路，但是今天场地可视性还行，而且人多，打针走了两步看到点了。</li>\n</ul>\n<h2>Day 1</h2>\n<p>三日赛跑下来最大的感觉就是三天场地的可跑性都相对较差，地上的碎石特别多，很容易崴脚，所以跑动速度上不来。以及 Day 1 &amp; 2 场地中的地形非常乱，很多小特征物在图上都没画，浅绿、白色和空地很多时候边界不明显或者没有区别，杂草生长导致小路不明显，导致丢了之后重定位和找地形以外的特征物作为攻击点都比较困难。</p>\n<p><a href=\"https://www.strava.com/activities/15552555679\">Strava</a></p>\n<figure class=\"raw\">\n  <img src=\"https://layered-assets.thu.fail/o-tour-2025-day1.jpg\">\n</figure>\n<ul>\n<li>\n<p>1 -&gt; 2 滑等高线，最后还是滑回了路上，从下方看不到点，还不如直接跑路。</p>\n</li>\n<li>\n<p>4 -&gt; 5 有平行错误，和<a href=\"https://www.strava.com/athletes/146379929\">超超</a>一起在偏东的谷里转了半天。正对着的那块儿田好像荒了，所以一时间没搞懂自己在哪儿。</p>\n</li>\n<li>\n<p>5 -&gt; 6 下 3m 高土坡指北针被刮掉了，难绷，上上下下爬了几次发现在脚底下的水沟里。</p>\n</li>\n<li>\n<p>8 号点进点的时候少上了一根等高线，以为在更高一个台阶的空地上。再加上这块儿坟墓有点多，看到有栅栏包围的坟墓时才重定位。应该在前面没有跨越小路的时候就发现的。</p>\n</li>\n<li>\n<p>9 我印象中只有最靠南的两个石墙能很明显看到，其他的基本就和碎石堆差不多。</p>\n</li>\n<li>\n<p>13 -&gt; 14 -&gt; 15 是最严重的失误。</p>\n<figure class=\"raw\">\n  <img src=\"https://layered-assets.thu.fail/o-tour-2025-day1-detail.png\">\n  <figcaption>13-14 局部细节</figcaption>\n</figure>\n<p>选择走大路我觉得没啥问题，但是没有找到向北的小路，所以一上来就偏西了，向西侧攻走到了 14，随后发生了不可思议的弱智错误：只对了点号是否存在，但是没对是不是 13 号。然后向西去找 14 的时候走到了水池才发现不对劲，和风电机的相对位置对了之后知道自己是找错点了。<del>超超和我在这里开火车，结果超超没有重新对点，直接 MP 了</del></p>\n<p>打完了 13 之后重新去 14，由于印象中 14 是在一个显著的小路上，但是 13 西侧两个绿色之间的空地和小路不明显，所以又走过头到靠西的第二个小路上了（但是其实也看不到小路，只能看到空地）。</p>\n<p>这一个序列浪费了 15 分钟左右，首先对点号这事儿实在不应该。其次在这类植被比较混乱，很多凌乱空旷地的地方，应该更注意看地形。在第一次进 13 的时候应该是一直垂直等高线爬升，看到下降应该就意识到偏西了。</p>\n</li>\n<li>\n<p>17 -&gt; 18 穿低了，其实是我以为我在灌木里，真实情况是我已经进绿了。不过好在比较好恢复。</p>\n</li>\n</ul>\n<h2>Day 2</h2>\n<p>和昨天差不多，路线更难，而且感觉图上缺的东西更多…</p>\n<p><a href=\"https://www.strava.com/activities/15563853493\">Strava</a></p>\n<figure class=\"raw\">\n  <img src=\"https://layered-assets.thu.fail/o-tour-2025-day2.jpg\">\n</figure>\n<ul>\n<li>\n<p>1 号点啥时候开始爬其实就很难确定。最后感觉最好的办法还是看到那坨绿（是一块儿竹林）之后回头。</p>\n</li>\n<li>\n<p>2 -&gt; 3 略微偏东，因为地上都是石头走着走着就偏了，不过找山背还是比较稳。</p>\n</li>\n<li>\n<p>5 -&gt; 6 选择了沿着山脊上去然后找石堆，但是其实遍地都是石堆。直穿据说可以直接看到点。</p>\n</li>\n<li>\n<p>9 -&gt; 10 最稳的跑法是沿着电线下到栅栏边上，然后从水沟向上。浪费一些爬高不过肯定不丢。事实证明半山腰石头太多了。</p>\n</li>\n<li>\n<p>11 -&gt; 12 是这场最大的失误。</p>\n<figure class=\"raw\">\n  <img src=\"https://layered-assets.thu.fail/o-tour-2025-day2-detail.png\">\n  <figcaption>11 -> 12 局部细节</figcaption>\n</figure>\n<p>一开始直穿爬升不够低了一个等高线，并且走的距离不够，丢失了站立点。随后找到了一个水坑，但是图上没有！！但是我只能以为是 12 北侧的水坑，所以向南，然后…又找到一个水坑，这次是 13 南侧的水塘。最后重新找回 13 然后打针才找到。</p>\n<p>感觉更稳的方法是正东直接去找水坑，找不到也有山脊线兜底。</p>\n</li>\n</ul>\n<h2>Day 3</h2>\n<p>可跑性稍微好了一些，但是因为稍微好了一些所以提速之后崴脚了，所以可跑性越好，可跑性越差。路略微更明显了一点，以及今天路线更简单，所以 Despite 崴脚了，发挥还不错。</p>\n<p><a href=\"https://www.strava.com/activities/15575799365\">Strava</a></p>\n<figure class=\"raw\">\n  <img src=\"https://layered-assets.thu.fail/o-tour-2025-day3.jpg\">\n</figure>\n<ul>\n<li>1 号点路上拐弯就拐错了，路明显但也没有那么明显。直接看和电塔相对位置就行，后面也有很多点都是看电塔的。</li>\n<li>6 -&gt; 7 的路线属于脑子被门挤了，一定要沿着石堆走。直穿沿着农田边界走少亏爬高，不过不知道好不好走。</li>\n<li>7 -&gt; 8 爬的有点歪，不过能爬上去就不错了，上了路跑两步基本不花时间。</li>\n<li>9 -&gt; 10 喜提崴脚，10 进点沿路走过了，10 和路之间其实有个小山脊会阻挡视线，还好看到有好多人从右面冒出来。</li>\n</ul>\n<p>还是得打保护呀，这下有理由家里躺一周了。</p>\n","plain":"这几天去盱眙跑了今年的长三角三日赛，最后一天喜提一个崴脚。简单做一下复盘。\n\nDay 0 / 计时赛\n报道第一天有长三角传统项目计时赛，赛制 \\approx 全点积分，还是十分好玩的，可惜国内并没有很多计时赛。\nStrava\n首先说路线选择。这张图上有两个比较麻烦的问题：44,49,57 没有很明显的收的办法，以及 36 爬回山上其实非常亏爬高。一开始看图的时候其实没看懂 36，50 和 45 的相对高度关系，以及粗略读图的时候直接把村子所在的谷当成基本不可穿越的了。不过碰巧这样跑的结果是把 49 和 57 收掉了，最后 44 从终点稍微绕了一点也可以拿到，所以不算特别倒闭。In hindsight, 更好的方式可能是:\n- 50 和 41 它们一起收\n- 直接 54 -> 36 -> 45 -> 35，回头上路 57 -> 49 -> 44，穿一点绿到 31。\n一些更细节的路线选择问题:\n- 54 -> 36 直穿滑等高线，灌木非常难走，还不如沿路到 50 下面然后再下呢。\n- 51 -> 48 从山脊反面的谷进，找点比较容易，但是也是因为地面比较杂乱速度较慢，还不如翻山。\n最后是一些进点的失误：\n- 51 平行错误，对前进的距离估计不足，在南侧的台地转了一小会儿，其实在北侧更高的台地上。间接原因是小路不明显，以为到了小路尽头了。\n- 54 也类似，根本看不见路，但是今天场地可视性还行，而且人多，打针走了两步看到点了。\n\nDay 1\n三日赛跑下来最大的感觉就是三天场地的可跑性都相对较差，地上的碎石特别多，很容易崴脚，所以跑动速度上不来。以及 Day 1 & 2 场地中的地形非常乱，很多小特征物在图上都没画，浅绿、白色和空地很多时候边界不明显或者没有区别，杂草生长导致小路不明显，导致丢了之后重定位和找地形以外的特征物作为攻击点都比较困难。\nStrava\n- 1 -> 2 滑等高线，最后还是滑回了路上，从下方看不到点，还不如直接跑路。\n\n- 4 -> 5 有平行错误，和超超一起在偏东的谷里转了半天。正对着的那块儿田好像荒了，所以一时间没搞懂自己在哪儿。\n\n- 5 -> 6 下 3m 高土坡指北针被刮掉了，难绷，上上下下爬了几次发现在脚底下的水沟里。\n\n- 8 号点进点的时候少上了一根等高线，以为在更高一个台阶的空地上。再加上这块儿坟墓有点多，看到有栅栏包围的坟墓时才重定位。应该在前面没有跨越小路的时候就发现的。\n\n- 9 我印象中只有最靠南的两个石墙能很明显看到，其他的基本就和碎石堆差不多。\n\n- 13 -> 14 -> 15 是最严重的失误。\n选择走大路我觉得没啥问题，但是没有找到向北的小路，所以一上来就偏西了，向西侧攻走到了 14，随后发生了不可思议的弱智错误：只对了点号是否存在，但是没对是不是 13 号。然后向西去找 14 的时候走到了水池才发现不对劲，和风电机的相对位置对了之后知道自己是找错点了。超超和我在这里开火车，结果超超没有重新对点，直接 MP 了\n打完了 13 之后重新去 14，由于印象中 14 是在一个显著的小路上，但是 13 西侧两个绿色之间的空地和小路不明显，所以又走过头到靠西的第二个小路上了（但是其实也看不到小路，只能看到空地）。\n这一个序列浪费了 15 分钟左右，首先对点号这事儿实在不应该。其次在这类植被比较混乱，很多凌乱空旷地的地方，应该更注意看地形。在第一次进 13 的时候应该是一直垂直等高线爬升，看到下降应该就意识到偏西了。\n\n- 17 -> 18 穿低了，其实是我以为我在灌木里，真实情况是我已经进绿了。不过好在比较好恢复。\n\n\nDay 2\n和昨天差不多，路线更难，而且感觉图上缺的东西更多…\nStrava\n- 1 号点啥时候开始爬其实就很难确定。最后感觉最好的办法还是看到那坨绿（是一块儿竹林）之后回头。\n\n- 2 -> 3 略微偏东，因为地上都是石头走着走着就偏了，不过找山背还是比较稳。\n\n- 5 -> 6 选择了沿着山脊上去然后找石堆，但是其实遍地都是石堆。直穿据说可以直接看到点。\n\n- 9 -> 10 最稳的跑法是沿着电线下到栅栏边上，然后从水沟向上。浪费一些爬高不过肯定不丢。事实证明半山腰石头太多了。\n\n- 11 -> 12 是这场最大的失误。\n一开始直穿爬升不够低了一个等高线，并且走的距离不够，丢失了站立点。随后找到了一个水坑，但是图上没有！！但是我只能以为是 12 北侧的水坑，所以向南，然后…又找到一个水坑，这次是 13 南侧的水塘。最后重新找回 13 然后打针才找到。\n感觉更稳的方法是正东直接去找水坑，找不到也有山脊线兜底。\n\n\nDay 3\n可跑性稍微好了一些，但是因为稍微好了一些所以提速之后崴脚了，所以可跑性越好，可跑性越差。路略微更明显了一点，以及今天路线更简单，所以 Despite 崴脚了，发挥还不错。\nStrava\n- 1 号点路上拐弯就拐错了，路明显但也没有那么明显。直接看和电塔相对位置就行，后面也有很多点都是看电塔的。\n- 6 -> 7 的路线属于脑子被门挤了，一定要沿着石堆走。直穿沿着农田边界走少亏爬高，不过不知道好不好走。\n- 7 -> 8 爬的有点歪，不过能爬上去就不错了，上了路跑两步基本不花时间。\n- 9 -> 10 喜提崴脚，10 进点沿路走过了，10 和路之间其实有个小山脊会阻挡视线，还好看到有好多人从右面冒出来。\n还是得打保护呀，这下有理由家里躺一周了。\n"},{"metadata":{"id":"about-ghost-of-tsushima","lang":"zh-CN","title":"玩了 Ghost of Tsushima","tags":["游戏屋"],"publish_time":"2025-08-21T04:30:44+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"玩","components":[["M 14 -166L 77 -7C 90 -10 101 -22 106 -35C 257 -124 358 -195 420 -244L 418 -253C 253 -213 81 -177 14 -166Z",[0.613,0.259]],["M 29 -759L 37 -731L 400 -731C 415 -731 426 -736 428 -747C 385 -789 309 -853 309 -853L 242 -759Z",[0.889,0.087]],["M 34 -475L 42 -447L 393 -447C 407 -447 417 -452 420 -463C 388 -502 328 -564 328 -564L 275 -475Z",[0.968,0.085]],["M 141 -759L 141 -129L 281 -179L 281 -759Z",[0.008,0.769]],["M 464 -495C 469 -257 448 -59 232 84L 237 94C 556 -4 609 -218 614 -495Z",[0.269,0.684]],["M 367 -495L 375 -467L 956 -467C 971 -467 982 -472 985 -483C 938 -528 857 -596 857 -596L 785 -495Z",[0.86,0.073]],["M 416 -750L 424 -722L 915 -722C 930 -722 941 -727 944 -738C 897 -782 817 -848 817 -848L 746 -750Z",[0.637,0.0]],["M 665 -494L 665 -48C 665 37 680 64 773 64L 829 64C 945 64 987 36 987 -14C 987 -39 981 -55 951 -71L 948 -234L 938 -234C 918 -167 899 -101 888 -80C 882 -69 878 -66 869 -66C 863 -66 856 -66 847 -66L 821 -66C 807 -66 804 -71 804 -84L 804 -456C 804 -466 804 -482 804 -494Z",[-0.144,0.526]]],"bbox":{"top":-853,"bottom":94,"left":14,"right":987},"hadv":1000}],"text":"玩","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"G","components":[["M 441 20C 536 20 607 -0 685 -46L 685 -95C 685 -193 687 -280 689 -367L 521 -367C 523 -275 525 -190 525 -100L 525 -9L 581 -40C 542 -26 503 -18 460 -18C 326 -18 221 -151 221 -374C 221 -614 330 -729 470 -729C 527 -729 567 -713 622 -670L 622 -712L 539 -743L 599 -530L 661 -530L 665 -713C 603 -747 534 -767 448 -767C 207 -767 43 -617 43 -376C 43 -128 204 20 441 20Z",[-0.048,0.116]],["M 416 -333L 555 -316L 624 -316L 750 -333L 750 -367L 416 -367Z",[0.82,0.005]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":750},"hadv":766},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Ghost","hadv":3021,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409}],"text":"of","hadv":1046,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599}],"text":"Tsushima","hadv":5111,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":"https://layered-assets.thu.fail/got-chat.png"},"html":"<p>又摸鱼了一整个月没写博客呢，除了线下高强度到处乱跑，其实还玩了不少游戏。出于怀旧目的重新玩了玩红警 3 的战役，Blue Prince 坐了 120h 牢，<del>推了推樱摸鱼</del>，还有终于打开了 Ghost of Tsushima。主线 + DLC 主线大约 30h，支线并没有推很多，简单写一些感想。</p>\n<h2>Vibe: 画面和演出</h2>\n<p>没有人可以忘记对马岛的 <a href=\"https://www.youtube.com/watch?v=z14No7a2ipw\">Title sequence</a> <small><del>以及 Act 3 开头导致无数玩家 PTSD 的 Cutscene</del></small>。这个游戏最大的亮点是它很酷，它很漂亮。换句话说，The Vibe. 事实证明当足够强的刻板印象和足够多的 Digital Artist 放在一起的时候，是可以做出来很 NB 的东西的。</p>\n<p>对马岛很多游戏元素的设计上都给人一种 Aesthetic 优先的感觉，比如 Ghost Stance，它在战斗系统中是有别的意义的：为达成无伤的玩家提供奖励、形成一种战斗策略。又比如 Standoff，给玩家提供一个类似 QTE 的挑战。但是我相信一开始设计这两个东西的主要原因之一，是它们可以足够酷。更明显的一些例子包括黑白电影模式。</p>\n<h2>剧情及任务设计</h2>\n<p>不太算暴论：对马岛的剧情中蒙古侵略反而是个副线。本体主线是关于武士和“荣誉”，DLC 是关于主角小时候的 PTSD 的。角色各自是复杂的，这些剧情讨论的内容也就是复杂和有趣的，对马岛的叙事也成功地将这个引人入胜的故事展现给了玩家，好看的画面额外加强了演出的效果。</p>\n<p>任务设计上，我觉得主线任务提供了足够多的多样性，一部分来自于上述剧情本身的复杂性，另外就是确实主线剧情涉及的游戏元素更多，主线上的关卡设计下了额外的功夫。不过地图上其他的内容和支线就有一点 Checklisty 的感觉了，而且难度根据玩家等级 Scale 的方式比较单一<super>[1]</super>，我有朋友两次启动对马岛都没有撑过 10h，原因是他之前玩<em>远哭</em>，一上来做了 10h 支线，直接玩自闭了。从某种角度上是 Ubisoft 导致的，对马岛的支线设计，和我这个朋友都是。</p>\n<p>不过主线 30h，质量非常高，已经完全值回票价了。因此感觉这游戏的正确玩的方式是首先推主线，然后如果觉得战斗系统或者探索好玩，再慢慢推支线，一天玩一会儿，<del>非常社畜的玩法</del>。</p>\n<div class=\"footnotes\">\n- [1] 比如 Standoff 时候的假动作，攻击力和防御力。我没有太注意这是根据玩家等级 Scale 的，还是只是单独根据所处的地图范围。\n</div>\n<h2>战斗</h2>\n<p>作为一个认为刺客信条的巅峰是 AC2 三部曲的人，我感觉我谈论 AAVG 游戏战斗系统的话语权已经被剥夺了，况且我还操作稀烂到只能去打回合制游戏，But here we are，这网站上我说了算。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/got-chat.png\" class=\"preview\">\n</figure>\n<p>战斗系统主要拆分成两部分吧，打铁循环和道具技能。不得不说只狼创造打铁有如工业革命，根据敌人动作做出反应，破坏架势，最终一次造成大量伤害，这是一个很让人享受的小循环。但是我个人认为对马岛围绕着打铁本身设计的招式动作等不是很复杂，就是老四样：轻、重、格挡、闪避，Stance 切换在战斗中的绝大多数意义是克制特定类型的敌人，其的存在让人感觉就像 Skill point dump 一样，或者故意让键鼠玩家难受的设计（虽然动画很酷就是了）。从这个角度，对马岛战斗中的直接攻击/防御还是挺简单纯粹的（和 e.g. <em>黑神话悟空</em>比）。更有趣的是道具和特殊技能的存在，以及其交互。例如镖、爆炸箭头、烟雾弹等道具是真正为玩家提供了构建其自己的玩法的东西，例如被大量敌人包围的时候，飞镖和烟雾弹各自为玩家提供了除了跑圈以外的解决方法。</p>\n<p>有一个让我在 Boss 战中偶尔感到很 Frustrating 的事情是格挡闪避的判定和前后摇。我到现在还没搞明白格挡的判定是什么情况，我从来没有在一串攻击的中间按出来过格挡，所以是第一击被击中后后面就无法再格挡了吗？翻滚时的无敌时间远小于后摇时间，如果敌人使用长矛做大范围攻击在无敌时间外基本必然命中，尤其是主线和 DLC 的最终 Boss 都有长矛范围连击这种东西，我即使通关也搞不明白应该什么节奏按翻滚，基本都是做好了吃最后一发的心理准备的。再加上这游戏有快慢刀 2.0（指出现不可防御攻击的标记到攻击真的发生的时间不定），结果就是玩的想让人砸键盘。</p>\n<p>最后，作为一个用 Moonlight 远程玩的键盘玩家，闪避机制对键盘略微有些不友好。默认键位映射下，闪避和格挡之间手指位置的差距过大 (Q vs. 方向键 + LAlt)，所以去实时反应挺困难的，最后稳定的策略只有 Manipulation 和跑圈。游戏提供了换映射的方法，不过要先按方向键再按 LAlt 这个延迟还是无法避免。当时用键盘打 <em>Sifu</em> 这个问题更严重，最后只能换了手柄。</p>\n<h2>开放世界探索</h2>\n<p>“没有滑翔伞的开放世界游戏必定度过失败的一生”，脑子被老任搞坏的人这么说，比如我。</p>\n<p>老任花了 TotK 一整个游戏尝试向玩家灌输他们是怎么（尝试）解决开放世界中的移动问题的，暂且不论其成功与否，至少说明这一问题的重要性。对马岛并无自由攀爬，没有类似滑翔伞的从 Vantage point 快速横向移动至 PoI 的手段，对探索的体验还是造成了一些影响的。对马岛成功地创造出了一个美丽的虚拟世界，在地图上放满了足够吸引人的内容（无论是温泉、神社等对角色建成有利的 PoI，还是各种小任务），然而在这个世界中穿梭的手段基本只有骑马，甚至因为移动困难我都没有什么动机去做主线外的东西了，有点令人惋惜。</p>\n<h2>额外的一些吐槽</h2>\n<p>主角名字<ruby>境井<rt>さかい</rt></ruby><ruby>仁<rt>じん</rt></ruby>我老是听成<ruby>社会人<rt>しゃかいじん</rt></ruby>，让人十分难绷。</p>\n<p>有 Standoff，有打铁，是音乐游戏（确信）</p>\n","plain":"又摸鱼了一整个月没写博客呢，除了线下高强度到处乱跑，其实还玩了不少游戏。出于怀旧目的重新玩了玩红警 3 的战役，Blue Prince 坐了 120h 牢，推了推樱摸鱼，还有终于打开了 Ghost of Tsushima。主线 + DLC 主线大约 30h，支线并没有推很多，简单写一些感想。\n\nVibe: 画面和演出\n没有人可以忘记对马岛的 Title sequence 以及 Act 3 开头导致无数玩家 PTSD 的 Cutscene。这个游戏最大的亮点是它很酷，它很漂亮。换句话说，The Vibe. 事实证明当足够强的刻板印象和足够多的 Digital Artist 放在一起的时候，是可以做出来很 NB 的东西的。\n对马岛很多游戏元素的设计上都给人一种 Aesthetic 优先的感觉，比如 Ghost Stance，它在战斗系统中是有别的意义的：为达成无伤的玩家提供奖励、形成一种战斗策略。又比如 Standoff，给玩家提供一个类似 QTE 的挑战。但是我相信一开始设计这两个东西的主要原因之一，是它们可以足够酷。更明显的一些例子包括黑白电影模式。\n\n剧情及任务设计\n不太算暴论：对马岛的剧情中蒙古侵略反而是个副线。本体主线是关于武士和“荣誉”，DLC 是关于主角小时候的 PTSD 的。角色各自是复杂的，这些剧情讨论的内容也就是复杂和有趣的，对马岛的叙事也成功地将这个引人入胜的故事展现给了玩家，好看的画面额外加强了演出的效果。\n任务设计上，我觉得主线任务提供了足够多的多样性，一部分来自于上述剧情本身的复杂性，另外就是确实主线剧情涉及的游戏元素更多，主线上的关卡设计下了额外的功夫。不过地图上其他的内容和支线就有一点 Checklisty 的感觉了，而且难度根据玩家等级 Scale 的方式比较单一[1]，我有朋友两次启动对马岛都没有撑过 10h，原因是他之前玩远哭，一上来做了 10h 支线，直接玩自闭了。从某种角度上是 Ubisoft 导致的，对马岛的支线设计，和我这个朋友都是。\n不过主线 30h，质量非常高，已经完全值回票价了。因此感觉这游戏的正确玩的方式是首先推主线，然后如果觉得战斗系统或者探索好玩，再慢慢推支线，一天玩一会儿，非常社畜的玩法。\n\n战斗\n作为一个认为刺客信条的巅峰是 AC2 三部曲的人，我感觉我谈论 AAVG 游戏战斗系统的话语权已经被剥夺了，况且我还操作稀烂到只能去打回合制游戏，But here we are，这网站上我说了算。\n战斗系统主要拆分成两部分吧，打铁循环和道具技能。不得不说只狼创造打铁有如工业革命，根据敌人动作做出反应，破坏架势，最终一次造成大量伤害，这是一个很让人享受的小循环。但是我个人认为对马岛围绕着打铁本身设计的招式动作等不是很复杂，就是老四样：轻、重、格挡、闪避，Stance 切换在战斗中的绝大多数意义是克制特定类型的敌人，其的存在让人感觉就像 Skill point dump 一样，或者故意让键鼠玩家难受的设计（虽然动画很酷就是了）。从这个角度，对马岛战斗中的直接攻击/防御还是挺简单纯粹的（和 e.g. 黑神话悟空比）。更有趣的是道具和特殊技能的存在，以及其交互。例如镖、爆炸箭头、烟雾弹等道具是真正为玩家提供了构建其自己的玩法的东西，例如被大量敌人包围的时候，飞镖和烟雾弹各自为玩家提供了除了跑圈以外的解决方法。\n有一个让我在 Boss 战中偶尔感到很 Frustrating 的事情是格挡闪避的判定和前后摇。我到现在还没搞明白格挡的判定是什么情况，我从来没有在一串攻击的中间按出来过格挡，所以是第一击被击中后后面就无法再格挡了吗？翻滚时的无敌时间远小于后摇时间，如果敌人使用长矛做大范围攻击在无敌时间外基本必然命中，尤其是主线和 DLC 的最终 Boss 都有长矛范围连击这种东西，我即使通关也搞不明白应该什么节奏按翻滚，基本都是做好了吃最后一发的心理准备的。再加上这游戏有快慢刀 2.0（指出现不可防御攻击的标记到攻击真的发生的时间不定），结果就是玩的想让人砸键盘。\n最后，作为一个用 Moonlight 远程玩的键盘玩家，闪避机制对键盘略微有些不友好。默认键位映射下，闪避和格挡之间手指位置的差距过大 (Q vs. 方向键 + LAlt)，所以去实时反应挺困难的，最后稳定的策略只有 Manipulation 和跑圈。游戏提供了换映射的方法，不过要先按方向键再按 LAlt 这个延迟还是无法避免。当时用键盘打 Sifu 这个问题更严重，最后只能换了手柄。\n\n开放世界探索\n“没有滑翔伞的开放世界游戏必定度过失败的一生”，脑子被老任搞坏的人这么说，比如我。\n老任花了 TotK 一整个游戏尝试向玩家灌输他们是怎么（尝试）解决开放世界中的移动问题的，暂且不论其成功与否，至少说明这一问题的重要性。对马岛并无自由攀爬，没有类似滑翔伞的从 Vantage point 快速横向移动至 PoI 的手段，对探索的体验还是造成了一些影响的。对马岛成功地创造出了一个美丽的虚拟世界，在地图上放满了足够吸引人的内容（无论是温泉、神社等对角色建成有利的 PoI，还是各种小任务），然而在这个世界中穿梭的手段基本只有骑马，甚至因为移动困难我都没有什么动机去做主线外的东西了，有点令人惋惜。\n\n额外的一些吐槽\n主角名字境井さかい仁じん我老是听成社会人しゃかいじん，让人十分难绷。\n有 Standoff，有打铁，是音乐游戏（确信）\n"},{"metadata":{"id":"isca2025-pt2","lang":"zh-CN","title":"ISCA 2025 流水账 Part.2","tags":["学术蝗虫"],"publish_time":"2025-07-22T06:49:39+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761}],"text":"ISCA","hadv":2518,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"流","components":[["M 30 -613L 23 -608C 55 -568 91 -507 103 -451C 224 -371 328 -599 30 -613Z",[-0.266,0.29]],["M 95 -217C 84 -217 49 -217 49 -217L 49 -199C 70 -197 88 -192 102 -182C 127 -166 130 -65 109 43C 120 83 149 96 174 96C 230 96 271 60 273 5C 276 -87 229 -118 227 -177C 226 -202 234 -239 242 -271C 254 -321 313 -516 348 -621L 333 -625C 154 -273 154 -273 129 -237C 116 -217 112 -217 95 -217Z",[0.123,0.738]],["M 117 -842L 110 -837C 141 -793 177 -730 189 -670C 315 -584 429 -820 117 -842Z",[-0.291,0.293]],["M 538 -376L 377 -391L 377 -286C 377 -171 365 -19 254 86L 261 94C 468 12 502 -159 505 -284L 505 -350C 529 -353 536 -363 538 -376Z",[0.197,0.688]],["M 848 -781L 779 -687L 319 -687L 327 -659L 941 -659C 956 -659 967 -664 970 -675C 925 -718 848 -781 848 -781Z",[0.83,0.066]],["M 721 -621L 534 -684C 511 -635 427 -538 366 -515C 353 -509 334 -505 334 -505L 377 -368C 406 -377 433 -410 440 -489L 383 -489L 383 -478C 486 -501 629 -560 700 -613L 663 -607C 699 -598 717 -607 721 -621Z",[0.542,0.411]],["M 357 -500L 395 -379C 575 -427 722 -475 804 -504L 804 -518C 617 -507 433 -500 357 -500Z",[0.766,0.117]],["M 525 -857L 518 -852C 545 -817 566 -762 565 -710C 686 -612 825 -839 525 -857Z",[-0.109,0.162]],["M 704 -379L 550 -393L 550 64L 573 64C 619 64 676 42 676 33L 676 -357C 697 -360 703 -368 704 -379Z",[0.012,0.713]],["M 717 -608L 709 -602C 750 -551 798 -476 817 -408C 939 -328 1033 -563 717 -608Z",[-0.297,0.346]],["M 881 -379L 725 -392L 725 -34C 725 42 734 68 814 68L 854 68C 941 68 982 40 982 -7C 982 -29 977 -44 951 -58L 948 -179L 937 -179C 922 -129 906 -79 898 -64C 892 -55 888 -54 881 -53C 878 -53 874 -53 870 -53L 860 -53C 852 -53 850 -57 850 -68L 850 -353C 870 -356 879 -366 881 -379Z",[-0.12,0.528]]],"bbox":{"top":-857,"bottom":96,"left":23,"right":1033},"hadv":1000}],"text":"流","hadv":1000,"breakAfter":true},{"chars":[{"char":"水","components":[["M 262 -555C 237 -357 164 -145 16 -13L 24 -3C 255 -114 359 -307 405 -506C 428 -508 437 -512 444 -523L 320 -628L 250 -555Z",[0.328,0.695]],["M 42 -555L 51 -527L 317 -527L 317 -555Z",[-0.823,0.006]],["M 573 -809C 599 -813 606 -822 608 -836L 425 -854L 425 -83C 425 -71 419 -65 402 -65C 376 -65 250 -73 250 -73L 250 -60C 311 -49 334 -33 354 -11C 374 12 381 45 385 93C 550 79 573 26 573 -73Z",[0.043,0.811]],["M 573 -692L 566 -689C 603 -317 689 -146 848 -5C 868 -72 912 -124 972 -136L 977 -147C 806 -224 629 -365 573 -692Z",[-0.376,0.582]],["M 802 -692C 769 -617 695 -486 631 -401L 639 -392C 745 -444 852 -518 924 -574C 949 -571 959 -577 964 -587Z",[0.439,0.429]]],"bbox":{"top":-854,"bottom":93,"left":16,"right":977},"hadv":1000}],"text":"水","hadv":1000,"breakAfter":true},{"chars":[{"char":"账","components":[["M 343 -633L 206 -662C 206 -265 216 -62 25 71L 37 87C 311 -24 298 -238 305 -610C 328 -610 339 -620 343 -633Z",[0.152,0.809]],["M 68 -801L 68 -215L 87 -215C 144 -215 178 -236 178 -244L 178 -727L 331 -727L 331 -239L 351 -239C 408 -239 446 -262 446 -268L 446 -717C 469 -721 480 -728 487 -737L 382 -819L 327 -755L 189 -755Z",[0.032,0.18]],["M 269 -220L 259 -215C 297 -152 337 -64 346 13C 457 104 562 -119 269 -220Z",[-0.274,0.482]],["M 845 -518L 778 -427L 453 -427L 461 -399L 939 -399C 953 -399 964 -404 967 -415C 922 -457 845 -518 845 -518Z",[0.797,0.082]],["M 633 -780L 532 -780L 532 -117C 532 -90 525 -80 481 -50L 591 94C 619 73 649 14 618 -70L 553 -14L 666 -66L 666 -760Z",[0.018,0.831]],["M 506 -41L 601 80C 671 -2 725 -80 748 -120L 745 -128C 649 -90 550 -55 506 -41Z",[0.412,0.26]],["M 701 -836L 532 -855L 532 -735C 642 -735 662 -735 666 -735L 666 -813C 690 -817 699 -825 701 -836Z",[-0.53,0.066]],["M 953 -680L 792 -775C 765 -697 702 -568 640 -484L 648 -475C 752 -526 850 -604 914 -667C 938 -664 948 -670 953 -680Z",[0.42,0.499]],["M 736 -418L 724 -414C 736 -168 768 -43 859 70C 882 4 925 -37 979 -46L 981 -57C 867 -125 767 -220 736 -418Z",[-0.257,0.534]]],"bbox":{"top":-855,"bottom":104,"left":25,"right":981},"hadv":1000}],"text":"账","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Part","hadv":2215,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613}],"text":"2","hadv":613,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>ISCA 已经开完快一个月了，虽说是最终补完<a href=\"isca2025-pt1\">上次没有写完的流水账</a>，但是总感觉已经是在写很久之前的事情，记忆已经有点模模糊糊了。</p>\n<p>继续首先提一下有趣的论文。居然 ISCA 也有一群做 Neuromorphic 的论文，其中有一个用 Analog latency 去 encode arithmetic 的，虽然 in hindsight 想法挺简单，但是解决加法的办法其实非常巧妙，感觉可以偷来做 DSA。韩国之前做 Neuromorphic accelerator 的组现在已经 All-in BCI 了，这次还是带来了针对 BCI 的专用加速器件，感觉有一些想法可以用到图挖掘上，等开学了打算和组里的学长博后聊聊。韩国组里的几个人居然还都认识我，看来社交不是完全失败？</p>\n<p>Cache policy 的相关论文也令人印象深刻，两篇关于 LLC policy w.r.t. instruction-heavy workload 的论文感觉都有很多可以借鉴的地方。</p>\n<p>其他的论文更多在我印象中就只有零零散散的片段了，就像我相册里不知所云的单独一两张照片。最搞笑的是其中一张明显在说 Coherence protocol 的感觉非常硬核，靠 EXIF 信息找到了当时是哪个论文，一看是 CORD，想起来为啥只拍了一张了：和现在总线的设计发展完全是相反的，让我觉得结果非常 Surprising，看了两页就觉得跟不上了，拍无可拍。</p>\n<p>一个月过去了，uArch 相关的论文忘光光，只记得 Best paper candidates。客观来说原因可能是因为我 Day 4 - Day 5 熬到了后半夜，不过还是得复习一下 Proceeding 了。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-waseda-cat-cafe.jpg\">\n  <figcaption>Venue 路对面的猫咖 @ Day4</figcaption>\n</figure>\n<h2>爽吃</h2>\n<p>Day4 Banquet 秉持着学术蝗虫的精神继续吃。中国人多的可以说中文社交，虽然对 I 人友好，但是本质上和参加 ChinaSys 区别不大（笑）</p>\n<style>\n.post .figure-line-2 img {\n  max-width: 50%;\n}\n</style>\n<figure>\n  <div class=\"figure-line-2\">\n    <img src=\"https://layered-assets.thu.fail/isca2025-banquet-1.jpg\"><img src=\"https://layered-assets.thu.fail/isca2025-banquet-2.jpg\">\n  </div>\n  <figcaption>Banquet @ Day4</figcaption>\n</figure>\n<p><em>Japanese Garden Walk (finding Japanese Fireflies)</em> 倒是 Walk 了，不过比较抽象，萤火虫都关在玻璃笼子里，奄奄一息的，勉勉强强挤出一点力气冲着看客们稍微发点光，<del>跟笼子外面的博士生们别无二致</del>。高级酒店的 Garden 倒是确实很大，疯狂迷路。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-garden.jpg\">\n  <figcaption>Garden @ Day4</figcaption>\n</figure>\n<h2>背🧻</h2>\n<p>Day 5 结束后继续每次 qrb 的定番，搬运厕纸回国。区别是这次我总算能看懂了，但是也没有时间和情绪看了，于是只买了最近觉得还不错，又正好在架上的。东京的 Animate 比大阪那边厕纸少，当然也可能是最近日轻倒闭严重的问题。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-book-1.jpg\">\n  <figcaption>新的一卷没有在新刊书架上找到，遗憾</figcaption>\n</figure>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-book-2.jpg\">\n  <figcaption>最新最热</figcaption>\n</figure>\n<p>很可惜，最后也没有遇到令人心动的塑料小人，于是🧻就是唯一购入的二刺螈物品了，颇有中年上班男性用户画像的感觉。随后真的挤了下班电车去找群友<em>打电动</em>去了（指双人成行）。</p>\n<h2>回家</h2>\n<p>发现 JAL 的选座可以直接选应急出口的座位，结果在机场转悠的时候忽然被登机口叫了，还以为唐突 last call，狂奔到远机位登机口，发现是要确认我是不是 able-bodied. 稍微斟酌一下之后还是确认自我感觉是健康人士。随后返回楼上的免税店，入手了一个猫猫。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-cat.jpg\">\n  <figcaption>🐱</figcaption>\n</figure>\n<p>JAL 的飞机餐很好吃，而且有草莓冰淇淋！不过因为前一天熬夜太累了，稍微眯了一会儿眼睛，然后冰淇淋还没有开盖就被收走了，难过！</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-jal-food.jpg\">\n  <figcaption>JAL 飞机餐</figcaption>\n</figure>\n<p>第二天熬夜时发现包里还有一罐没吃完的杯面，正好用来填肚子了，算不算行程延后结束了一天呢？</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-cup-noodle.jpg\">\n  <figcaption>7/11 杯面</figcaption>\n</figure>","plain":"ISCA 已经开完快一个月了，虽说是最终补完上次没有写完的流水账，但是总感觉已经是在写很久之前的事情，记忆已经有点模模糊糊了。\n继续首先提一下有趣的论文。居然 ISCA 也有一群做 Neuromorphic 的论文，其中有一个用 Analog latency 去 encode arithmetic 的，虽然 in hindsight 想法挺简单，但是解决加法的办法其实非常巧妙，感觉可以偷来做 DSA。韩国之前做 Neuromorphic accelerator 的组现在已经 All-in BCI 了，这次还是带来了针对 BCI 的专用加速器件，感觉有一些想法可以用到图挖掘上，等开学了打算和组里的学长博后聊聊。韩国组里的几个人居然还都认识我，看来社交不是完全失败？\nCache policy 的相关论文也令人印象深刻，两篇关于 LLC policy w.r.t. instruction-heavy workload 的论文感觉都有很多可以借鉴的地方。\n其他的论文更多在我印象中就只有零零散散的片段了，就像我相册里不知所云的单独一两张照片。最搞笑的是其中一张明显在说 Coherence protocol 的感觉非常硬核，靠 EXIF 信息找到了当时是哪个论文，一看是 CORD，想起来为啥只拍了一张了：和现在总线的设计发展完全是相反的，让我觉得结果非常 Surprising，看了两页就觉得跟不上了，拍无可拍。\n一个月过去了，uArch 相关的论文忘光光，只记得 Best paper candidates。客观来说原因可能是因为我 Day 4 - Day 5 熬到了后半夜，不过还是得复习一下 Proceeding 了。\n\n爽吃\nDay4 Banquet 秉持着学术蝗虫的精神继续吃。中国人多的可以说中文社交，虽然对 I 人友好，但是本质上和参加 ChinaSys 区别不大（笑）\nJapanese Garden Walk (finding Japanese Fireflies) 倒是 Walk 了，不过比较抽象，萤火虫都关在玻璃笼子里，奄奄一息的，勉勉强强挤出一点力气冲着看客们稍微发点光，跟笼子外面的博士生们别无二致。高级酒店的 Garden 倒是确实很大，疯狂迷路。\n\n背🧻\nDay 5 结束后继续每次 qrb 的定番，搬运厕纸回国。区别是这次我总算能看懂了，但是也没有时间和情绪看了，于是只买了最近觉得还不错，又正好在架上的。东京的 Animate 比大阪那边厕纸少，当然也可能是最近日轻倒闭严重的问题。\n很可惜，最后也没有遇到令人心动的塑料小人，于是🧻就是唯一购入的二刺螈物品了，颇有中年上班男性用户画像的感觉。随后真的挤了下班电车去找群友打电动去了（指双人成行）。\n\n回家\n发现 JAL 的选座可以直接选应急出口的座位，结果在机场转悠的时候忽然被登机口叫了，还以为唐突 last call，狂奔到远机位登机口，发现是要确认我是不是 able-bodied. 稍微斟酌一下之后还是确认自我感觉是健康人士。随后返回楼上的免税店，入手了一个猫猫。\nJAL 的飞机餐很好吃，而且有草莓冰淇淋！不过因为前一天熬夜太累了，稍微眯了一会儿眼睛，然后冰淇淋还没有开盖就被收走了，难过！\n第二天熬夜时发现包里还有一罐没吃完的杯面，正好用来填肚子了，算不算行程延后结束了一天呢？\n"},{"metadata":{"id":"self-signed-x509-chain","lang":"en-US","title":"Self-signed X.509 certificate chains w/ ECC","tags":["开发"],"publish_time":"2025-07-08T02:06:13+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409}],"text":"Self","hadv":1973,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"signed","hadv":3438,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"X","components":[["M 10 -0L 253 -0L 253 -34L 147 -50L 121 -50L 10 -34Z",[0.806,0.001]],["M 19 -713L 167 -698L 220 -698L 368 -713L 368 -747L 19 -747Z",[-0.791,0.001]],["M 493 -0L 680 -0L 246 -747L 59 -747Z",[-0.426,0.698]],["M 67 -0L 127 -0L 340 -347L 360 -382L 366 -382L 337 -401Z",[0.49,0.755]],["M 370 -0L 727 -0L 727 -34L 579 -50L 530 -50L 370 -34Z",[0.867,0.001]],["M 402 -395L 634 -747L 579 -747L 395 -444L 376 -410L 370 -410Z",[0.484,0.763]],["M 457 -713L 559 -699L 586 -699L 695 -713L 695 -747L 457 -747Z",[-0.19,0.031]]],"bbox":{"top":-747,"bottom":0,"left":10,"right":727},"hadv":739}],"text":"X","hadv":739,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"9","components":[["M 107 20C 385 -31 572 -206 572 -445C 572 -645 474 -764 299 -764C 159 -764 39 -679 39 -511C 39 -370 133 -290 263 -290C 349 -290 410 -326 437 -372L 448 -372L 425 -380C 395 -350 367 -337 326 -337C 247 -337 198 -410 198 -533C 198 -671 246 -730 303 -730C 365 -730 409 -665 409 -467C 409 -218 321 -84 101 -9Z",[-0.042,0.21]]],"bbox":{"top":-764,"bottom":20,"left":39,"right":572},"hadv":614}],"text":"509","hadv":1839,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"certificate","hadv":5386,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"chains","hadv":3445,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893}],"text":"w","hadv":893,"breakAfter":false},{"chars":[{"char":"/","components":[["M 26 181L 96 181L 399 -804L 330 -804Z",[0.277,0.894]]],"bbox":{"top":-804,"bottom":181,"left":26,"right":399},"hadv":425}],"text":"/","hadv":425,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"E","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 634 -0L 632 -207L 576 -207L 519 -1L 605 -39L 218 -39Z",[0.604,0.185]],["M 218 -363L 467 -363L 467 -399L 218 -399Z",[-0.86,0.001]],["M 554 -548L 612 -548L 613 -747L 218 -747L 218 -708L 583 -708L 499 -747Z",[-0.58,0.193]],["M 454 -263L 504 -263L 504 -505L 454 -505L 438 -395L 438 -374Z",[0.007,0.742]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":634},"hadv":674},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708}],"text":"ECC","hadv":2090,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>Recently I need to generate a few X.509 certificates for connection authentication in QUIC. A custom root trust anchors is used to sign certificates for each nodes, and these certificates will be presented as client and server certificates during QUIC handshake.</p>\n<p>Ideally, we want a short certificate, so ECDSA p256 is chosen as the signature algorithm. Additionally, modern TLS implementations use the <code>serverAltName</code> extension (SAN) for host verification instead of common names (see <a href=\"https://www.rfc-editor.org/info/rfc6125\">[rfc6125]</a>), so we have to place our node identifiers there. Fortunately we can use non-existent but valid domain names in SAN.</p>\n<p>The following commands are tested with OpenSSL 3.4.1.</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#586e75;\"># Generate trust anchor&#39;s key\n</span><span style=\"color:#b58900;\">openssl</span><span style=\"color:#839496;\"> ecparam</span><span style=\"color:#268bd2;\"> -out</span><span style=\"color:#839496;\"> ca.key.pem</span><span style=\"color:#268bd2;\"> -name</span><span style=\"color:#839496;\"> prime256v1</span><span style=\"color:#268bd2;\"> -genkey\n</span><span style=\"color:#586e75;\"># Generate trust anchor&#39;s certificate, valid for 10yr.\n</span><span style=\"color:#586e75;\"># No SAN is needed here.\n</span><span style=\"color:#b58900;\">openssl</span><span style=\"color:#839496;\"> req</span><span style=\"color:#268bd2;\"> -new -key</span><span style=\"color:#839496;\"> ca.key.pem</span><span style=\"color:#268bd2;\"> -x509 -nodes -days</span><span style=\"color:#839496;\"> 3650 </span><span style=\"color:#dc322f;\">\\\n</span><span style=\"color:#268bd2;\">  -out</span><span style=\"color:#839496;\"> ca.pem</span><span style=\"color:#268bd2;\"> -subj </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">/CN=ca</span><span style=\"color:#839496;\">&quot;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># Generate node&#39;s key\n</span><span style=\"color:#b58900;\">openssl</span><span style=\"color:#839496;\"> ecparam</span><span style=\"color:#268bd2;\"> -out</span><span style=\"color:#839496;\"> node.key.pem</span><span style=\"color:#268bd2;\"> -name</span><span style=\"color:#839496;\"> prime256v1</span><span style=\"color:#268bd2;\"> -genkey\n</span><span style=\"color:#586e75;\"># Generate node&#39;s certificate signing request (CSR)\n</span><span style=\"color:#b58900;\">openssl</span><span style=\"color:#839496;\"> req</span><span style=\"color:#268bd2;\"> -sha256 -new -nodes -key</span><span style=\"color:#839496;\"> node.key.pem </span><span style=\"color:#dc322f;\">\\\n</span><span style=\"color:#268bd2;\">  -out</span><span style=\"color:#839496;\"> node.csr</span><span style=\"color:#268bd2;\"> -subj </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">/CN=node</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#dc322f;\">\\\n</span><span style=\"color:#268bd2;\">  -addext </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">subjectAltName=DNS:node.foo.bar</span><span style=\"color:#839496;\">&quot;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># Sign a certificate, valid for 1yr.\n</span><span style=\"color:#586e75;\"># Note that we need to tell OpenSSL to copy extensions from\n</span><span style=\"color:#586e75;\">#   CSR into the resulting cert\n</span><span style=\"color:#b58900;\">openssl</span><span style=\"color:#839496;\"> x509</span><span style=\"color:#268bd2;\"> -req -days</span><span style=\"color:#839496;\"> 365</span><span style=\"color:#268bd2;\"> -in</span><span style=\"color:#839496;\"> node.csr</span><span style=\"color:#268bd2;\"> -out</span><span style=\"color:#839496;\"> node.pem </span><span style=\"color:#dc322f;\">\\\n</span><span style=\"color:#268bd2;\">  -CA</span><span style=\"color:#839496;\"> ./ca.pem</span><span style=\"color:#268bd2;\"> -CAkey</span><span style=\"color:#839496;\"> ./ca.key.pem </span><span style=\"color:#dc322f;\">\\\n</span><span style=\"color:#268bd2;\">  -CAcreateserial -copy_extensions</span><span style=\"color:#839496;\"> copy\n</span><span style=\"color:#586e75;\"># Outputs:\n</span><span style=\"color:#586e75;\"># &gt; Certificate request self-signature ok\n</span><span style=\"color:#586e75;\"># &gt; subject=CN=node\n</span></code></pre>\n</div>\n<p>You can use <code>openssl x509 -noout -text -in node.pem</code> to check the resulting certificate.</p>\n","plain":"Recently I need to generate a few X.509 certificates for connection authentication in QUIC. A custom root trust anchors is used to sign certificates for each nodes, and these certificates will be presented as client and server certificates during QUIC handshake.\nIdeally, we want a short certificate, so ECDSA p256 is chosen as the signature algorithm. Additionally, modern TLS implementations use the serverAltName extension (SAN) for host verification instead of common names (see [rfc6125]), so we have to place our node identifiers there. Fortunately we can use non-existent but valid domain names in SAN.\nThe following commands are tested with OpenSSL 3.4.1.\n# Generate trust anchor's key\nopenssl ecparam -out ca.key.pem -name prime256v1 -genkey\n# Generate trust anchor's certificate, valid for 10yr.\n# No SAN is needed here.\nopenssl req -new -key ca.key.pem -x509 -nodes -days 3650 \\\n  -out ca.pem -subj \"/CN=ca\"\n\n# Generate node's key\nopenssl ecparam -out node.key.pem -name prime256v1 -genkey\n# Generate node's certificate signing request (CSR)\nopenssl req -sha256 -new -nodes -key node.key.pem \\\n  -out node.csr -subj \"/CN=node\" \\\n  -addext \"subjectAltName=DNS:node.foo.bar\"\n\n# Sign a certificate, valid for 1yr.\n# Note that we need to tell OpenSSL to copy extensions from\n#   CSR into the resulting cert\nopenssl x509 -req -days 365 -in node.csr -out node.pem \\\n  -CA ./ca.pem -CAkey ./ca.key.pem \\\n  -CAcreateserial -copy_extensions copy\n# Outputs:\n# > Certificate request self-signature ok\n# > subject=CN=node\n\nYou can use openssl x509 -noout -text -in node.pem to check the resulting certificate.\n"},{"metadata":{"id":"view-timeline-pause","lang":"en-US","title":"pause() is not enough for scroll-driven animations","tags":["开发","前端"],"publish_time":"2025-06-30T02:28:35+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"pause","hadv":3077,"breakAfter":false},{"chars":[{"char":"(","components":[["M 206 -315C 206 -504 242 -638 376 -803L 352 -825C 180 -684 86 -529 86 -315C 86 -101 180 53 352 195L 376 173C 249 12 206 -126 206 -315Z",[-0.002,0.755]]],"bbox":{"top":-825,"bottom":195,"left":86,"right":376},"hadv":418}],"text":"(","hadv":418,"breakAfter":false},{"chars":[{"char":")","components":[["M 212 -315C 212 -126 176 8 42 173L 66 195C 238 54 332 -101 332 -315C 332 -529 238 -683 66 -825L 42 -803C 169 -642 212 -504 212 -315Z",[-0.001,0.755]]],"bbox":{"top":-825,"bottom":195,"left":42,"right":332},"hadv":418}],"text":")","hadv":418,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"is","hadv":870,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"not","hadv":1740,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"enough","hadv":3923,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"for","hadv":1566,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366}],"text":"scroll","hadv":2980,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"driven","hadv":3427,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"animations","hadv":5888,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>When doing navigation in SPA, the scroll position would often experience a sudden change, either done intentionally to return to the top of the newly accessed page, or inadvertently as a side effect from the change of scrollable content’s height. If the scroller is shared between the exiting and entering content (e.g. scroller being the root viewport), then the exiting content would also be scrolled abruptly. An easy mitigation for this maybe unwanted visual side effect is to change the positioning of the exiting content to <code>position: fixed</code>, essentially fixing the exiting content’s position at the moment of the navigation. However, if the exiting content contains scroll-driven animations, we would also have to somehow fix them too.</p>\n<h2>Pausing is not enough</h2>\n<p>One obvious choice is add <code>animation-play-state: paused</code>, or to call <code>Animation.pause()</code> if using WebAnimation. However, these approachs suffers from the fact that the pausing of the animation is <strong>not synchronous</strong>, at least as implemented currently in Blink (the only implementation of scroll-driven animation as of right now), so even after the pausing is initiated, changing the scroll position may still affect the animation progress. Even worse is that both changing CSS or calling <code>Animation.pause()</code> provides no signal of completion. So we can’t even reliably delay the scrolling until the pausing is done.</p>\n<p>The specification is somewhat outdated and contradictory regarding scroll-driven animations. The current CSSWG draft spec for web animations <a href=\"https://drafts.csswg.org/web-animations-1/#pausing-an-animation-section\">[web-animation-1]</a> on paper would categorize scroll-driven animation as “has finite timeline”, but that’s obviously not the intention here. Based on the steps below, “has finite timeline” should only be applicable to animations with finite iterations. The newer (unfinished) draft [web-animation-2], which incorporates scroll-driven animations, is apparantly incomplete, because the <em>hold time</em> is never set to <em>current time</em>. Also, according to <a href=\"https://github.com/w3c/csswg-drafts/issues/11469#issuecomment-2634876248\">a issue in csswg-drafts</a>, Blink’s implementation has already diverge from the draft.</p>\n<h2>A temporary workaround for WebAnimation</h2>\n<p>Luckily, for web animations, we can easily <em>sychronously</em> apply the current computed style according to a <code>Animation</code> by using <a href=\"https://drafts.csswg.org/web-animations-1/#dom-animation-commitstyles\"><code>Animation.commitStyles()</code></a>.</p>\n<p>So instead of doing:</p>\n<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#839496;\">animation.</span><span style=\"color:#b58900;\">pause</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>One would need:</p>\n<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#839496;\">animation.</span><span style=\"color:#b58900;\">commitStyles</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">animation.</span><span style=\"color:#b58900;\">cancel</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>Notice that <code>Animation.cancel()</code> instead of <code>Animation.pause()</code> is used here. Because animated values take precedence over all static values, even those defined in the element’s style property, so we have to cancel the animation all together to avoid further timeline updates overriding our committed styles. This piece of code works in Blink as of right now, and is used in the <a href=\"https://github.com/CircuitCoder/layered/blob/148c2590a3885d0048455586534fb6d6a21d2d74/web/src/main.tsx#L1047-L1053\">frontend of the page you’re watching</a>.</p>\n<p>For pure CSS animations, one may need to manually call <code>getComputedStyle</code> and apply animated properties one-by-one.</p>\n","plain":"When doing navigation in SPA, the scroll position would often experience a sudden change, either done intentionally to return to the top of the newly accessed page, or inadvertently as a side effect from the change of scrollable content’s height. If the scroller is shared between the exiting and entering content (e.g. scroller being the root viewport), then the exiting content would also be scrolled abruptly. An easy mitigation for this maybe unwanted visual side effect is to change the positioning of the exiting content to position: fixed, essentially fixing the exiting content’s position at the moment of the navigation. However, if the exiting content contains scroll-driven animations, we would also have to somehow fix them too.\n\nPausing is not enough\nOne obvious choice is add animation-play-state: paused, or to call Animation.pause() if using WebAnimation. However, these approachs suffers from the fact that the pausing of the animation is not synchronous, at least as implemented currently in Blink (the only implementation of scroll-driven animation as of right now), so even after the pausing is initiated, changing the scroll position may still affect the animation progress. Even worse is that both changing CSS or calling Animation.pause() provides no signal of completion. So we can’t even reliably delay the scrolling until the pausing is done.\nThe specification is somewhat outdated and contradictory regarding scroll-driven animations. The current CSSWG draft spec for web animations [web-animation-1] on paper would categorize scroll-driven animation as “has finite timeline”, but that’s obviously not the intention here. Based on the steps below, “has finite timeline” should only be applicable to animations with finite iterations. The newer (unfinished) draft [web-animation-2], which incorporates scroll-driven animations, is apparantly incomplete, because the hold time is never set to current time. Also, according to a issue in csswg-drafts, Blink’s implementation has already diverge from the draft.\n\nA temporary workaround for WebAnimation\nLuckily, for web animations, we can easily sychronously apply the current computed style according to a Animation by using Animation.commitStyles().\nSo instead of doing:\nanimation.pause();\n\nOne would need:\nanimation.commitStyles();\nanimation.cancel();\n\nNotice that Animation.cancel() instead of Animation.pause() is used here. Because animated values take precedence over all static values, even those defined in the element’s style property, so we have to cancel the animation all together to avoid further timeline updates overriding our committed styles. This piece of code works in Blink as of right now, and is used in the frontend of the page you’re watching.\nFor pure CSS animations, one may need to manually call getComputedStyle and apply animated properties one-by-one.\n"},{"metadata":{"id":"vector-pca","lang":"en-US","title":"Determining the \"direction\" of a vector shape","tags":["开发"],"publish_time":"2025-06-28T04:35:43+08:00","update_time":"2025-06-29T04:30:47+08:00","title_outline":{"groups":[{"chars":[{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"Determining","hadv":6644,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"the","hadv":1692,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"\"","components":[["M 127 -829C 78 -829 49 -801 49 -744C 49 -698 70 -628 79 -586L 111 -459L 144 -459L 177 -586C 185 -628 205 -696 205 -744C 205 -801 176 -829 127 -829Z",[-0.001,0.613]],["M 356 -829C 307 -829 278 -801 278 -744C 278 -698 299 -628 308 -586L 340 -459L 373 -459L 406 -586C 414 -628 434 -696 434 -744C 434 -801 404 -829 356 -829Z",[0.012,0.613]]],"bbox":{"top":-829,"bottom":-459,"left":49,"right":434},"hadv":484}],"text":"\"","hadv":484,"breakAfter":false},{"chars":[{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"direction","hadv":4814,"breakAfter":false},{"chars":[{"char":"\"","components":[["M 127 -829C 78 -829 49 -801 49 -744C 49 -698 70 -628 79 -586L 111 -459L 144 -459L 177 -586C 185 -628 205 -696 205 -744C 205 -801 176 -829 127 -829Z",[-0.001,0.613]],["M 356 -829C 307 -829 278 -801 278 -744C 278 -698 299 -628 308 -586L 340 -459L 373 -459L 406 -586C 414 -628 434 -696 434 -744C 434 -801 404 -829 356 -829Z",[0.012,0.613]]],"bbox":{"top":-829,"bottom":-459,"left":49,"right":434},"hadv":484}],"text":"\"","hadv":484,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409}],"text":"of","hadv":1046,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599}],"text":"a","hadv":599,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"vector","hadv":3321,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"shape","hadv":3086,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>Edited 06-29: updated how to compute the length of the direction vector. See the end of this post.</p>\n<p>Intuitively, the Chinese stroke <ruby>“㇐”<rt>U+31D0</rt></ruby> has a <em>horizontal</em> direction, while <ruby>“㇓”<rt>U+31D3</rt></ruby> has a <em>mostly top-right to bottom-left</em> direction. How do we determine the “direction” of a stroke?</p>\n<p>First we need to figure out what is a stroke and what is a “direction”. Since we are working in a 2D plane, we can instead use a method for any <strong>closed loop without self-intersection</strong>. Most frequently, these shapes are represented in piecewise parametric curves<sup>[1]</sup>, which is also the case for font-shapped characters from free-type fonts. One possible definition of “direction” is the main axis of the smallest bounding ellipsis. Computing the smallest bounding ellipsis is hard to do analytically, but we can deal with another form of ellipsis much more easily: statistics has given us a tool for dealing with <em>fitted</em> ellipsis: principal component analysis (PCA).</p>\n<p>In practice, PCA is always used with samples, but instead we can abuse it to compute the ellipsis fitted to a multivariate distribution with known PDF. In our case, we can define the “direction” of a shape <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span> to be the main axis of the ellipsis fitted to the uniform distribution over the internal of <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span>.</p>\n<h1>What do we need</h1>\n<p>First, the PDF of the distribution over the internal of some shape closed <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span> with internal <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">int(L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">in</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span> and area <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">A(L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span> is:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>f</mi><mo stretchy=\"false\">(</mo><mi mathvariant=\"bold\">p</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mrow><mo fence=\"true\">{</mo><mtable rowspacing=\"0.36em\" columnalign=\"left left\" columnspacing=\"1em\"><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mi mathvariant=\"bold\">p</mi><mo mathvariant=\"normal\">∉</mo><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo><mo separator=\"true\">,</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mfrac><mn>1</mn><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mi mathvariant=\"bold\">p</mi><mo>∈</mo><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo><mo separator=\"true\">,</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding=\"application/x-tex\">\nf(\\mathbf{p}) = \\begin{cases} 0&amp; \\mathbf{p} \\notin int(L),\\\\ 1 \\over A(L) &amp; \\mathbf{p} \\in int(L), \\end{cases}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mopen\">(</span><span class=\"mord mathbf\">p</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:3em;vertical-align:-1.25em;\"></span><span class=\"minner\"><span class=\"mopen delimcenter\" style=\"top:0em;\"><span class=\"delimsizing size4\">{</span></span><span class=\"mord\"><span class=\"mtable\"><span class=\"col-align-l\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.734em;\"><span style=\"top:-3.734em;\"><span class=\"pstrut\" style=\"height:3.008em;\"></span><span class=\"mord\"><span class=\"mord\">0</span></span></span><span style=\"top:-2.294em;\"><span class=\"pstrut\" style=\"height:3.008em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.234em;\"><span></span></span></span></span></span><span class=\"arraycolsep\" style=\"width:1em;\"></span><span class=\"col-align-l\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.734em;\"><span style=\"top:-3.734em;\"><span class=\"pstrut\" style=\"height:3.008em;\"></span><span class=\"mord\"><span class=\"mord mathbf\">p</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mord\"><span class=\"mrel\">∈</span></span><span class=\"mord vbox\"><span class=\"thinbox\"><span class=\"llap\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"inner\"><span class=\"mord\"><span class=\"mord\">/</span><span class=\"mspace\" style=\"margin-right:0.0556em;\"></span></span></span><span class=\"fix\"></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\">in</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span><span class=\"mpunct\">,</span></span></span><span style=\"top:-2.294em;\"><span class=\"pstrut\" style=\"height:3.008em;\"></span><span class=\"mord\"><span class=\"mord mathbf\">p</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\">in</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span><span class=\"mpunct\">,</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.234em;\"><span></span></span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p>So first, we need to compute the area of <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span>. Another subtle thing that needs to be determine is the orientation of <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span>, because it’s not guaranteed that it has conter-clockwise orientation. Both of these can be computed in a single step by first assuming <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span> has the correct orientation, compute the area <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">A(L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span> as-is, and then judge the orientation by the sign of <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">A(L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span>.</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo><mo>=</mo><msub><mo>∬</mo><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></msub><mi>d</mi><mi>A</mi><mo>=</mo><msub><mo>∮</mo><mi>L</mi></msub><mi>x</mi><mi>d</mi><mi>y</mi></mrow><annotation encoding=\"application/x-tex\">\nA(L) = \\iint_{int(L)} dA = \\oint_L x dy\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.4467em;vertical-align:-1.0867em;\"></span><span class=\"mop\"><span class=\"mop op-symbol large-op\" style=\"margin-right:0.44445em;position:relative;top:-0.001em;\">∬</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:-0.3867em;\"><span style=\"top:-1.7883em;margin-left:-0.4445em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">in</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.0867em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.2719em;vertical-align:-0.9119em;\"></span><span class=\"mop\"><span class=\"mop op-symbol large-op\" style=\"margin-right:0.44445em;position:relative;top:-0.0011em;\">∮</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:-0.4336em;\"><span style=\"top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">L</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.9119em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span></span></span></span></span></p>\n<p>Now with the PDF fully defined, we need to compute the covariance matrix of this distribution. This in turn requires the following values:</p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>V</mi><mi>a</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">Var(x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">Va</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span> and <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>V</mi><mi>a</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>y</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">Var(y)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">Va</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><mi>o</mi><mi>v</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo separator=\"true\">,</mo><mi>y</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>C</mi><mi>o</mi><mi>v</mi><mo stretchy=\"false\">(</mo><mi>y</mi><mo separator=\"true\">,</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">Cov(x, y) = Cov(y, x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n<p>Since <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>V</mi><mi>a</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>E</mi><mo stretchy=\"false\">(</mo><msup><mi>x</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo><mo>−</mo><mi>E</mi><mo stretchy=\"false\">(</mo><mi>x</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">Var(x) = E(x^2) - E(x)^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">Va</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span> and <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>V</mi><mi>a</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>y</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>E</mi><mo stretchy=\"false\">(</mo><msup><mi>y</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo><mo>−</mo><mi>E</mi><mo stretchy=\"false\">(</mo><mi>y</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">Var(y) = E(y^2) - E(y)^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">Va</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span>, so we need the first and second central moment of x and y, which are:</p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>E</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mfrac><mn>1</mn><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∬</mo><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></msub><mi>x</mi><mi>d</mi><mi>A</mi><mo>=</mo><mfrac><mn>1</mn><mrow><mn>2</mn><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∮</mo><mi>L</mi></msub><msup><mi>x</mi><mn>2</mn></msup><mi>d</mi><mi>y</mi></mrow><annotation encoding=\"application/x-tex\">E(x) = \\frac{1}{A(L)} \\iint_{int(L)} x dA = \\frac{1}{2A(L)} \\oint_L x^2 dy</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3758em;vertical-align:-0.5307em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0005em;\">∬</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1693em;\"><span style=\"top:-2.3443em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">in</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.5307em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3651em;vertical-align:-0.52em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">2</span><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0006em;\">∮</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1225em;\"><span style=\"top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">L</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3558em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>E</mi><mo stretchy=\"false\">(</mo><mi>y</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mfrac><mn>1</mn><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∬</mo><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></msub><mi>y</mi><mi>d</mi><mi>A</mi><mo>=</mo><mo>−</mo><mfrac><mn>1</mn><mrow><mn>2</mn><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∮</mo><mi>L</mi></msub><msup><mi>y</mi><mn>2</mn></msup><mi>d</mi><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">E(y) = \\frac{1}{A(L)} \\iint_{int(L)} y dA = - \\frac{1}{2A(L)} \\oint_L y^2 dx</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3758em;vertical-align:-0.5307em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0005em;\">∬</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1693em;\"><span style=\"top:-2.3443em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">in</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.5307em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3651em;vertical-align:-0.52em;\"></span><span class=\"mord\">−</span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">2</span><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0006em;\">∮</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1225em;\"><span style=\"top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">L</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3558em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">x</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>E</mi><mo stretchy=\"false\">(</mo><msup><mi>x</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo><mo>=</mo><mfrac><mn>1</mn><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∬</mo><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></msub><msup><mi>x</mi><mn>2</mn></msup><mi>d</mi><mi>A</mi><mo>=</mo><mfrac><mn>1</mn><mrow><mn>3</mn><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∮</mo><mi>L</mi></msub><msup><mi>x</mi><mn>3</mn></msup><mi>d</mi><mi>y</mi></mrow><annotation encoding=\"application/x-tex\">E(x^2) = \\frac{1}{A(L)} \\iint_{int(L)} x^2 dA = \\frac{1}{3A(L)} \\oint_L x^3 dy</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3758em;vertical-align:-0.5307em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0005em;\">∬</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1693em;\"><span style=\"top:-2.3443em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">in</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.5307em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3651em;vertical-align:-0.52em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">3</span><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0006em;\">∮</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1225em;\"><span style=\"top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">L</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3558em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>E</mi><mo stretchy=\"false\">(</mo><msup><mi>y</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo><mo>=</mo><mfrac><mn>1</mn><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∬</mo><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></msub><msup><mi>y</mi><mn>2</mn></msup><mi>d</mi><mi>A</mi><mo>=</mo><mo>−</mo><mfrac><mn>1</mn><mrow><mn>3</mn><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∮</mo><mi>L</mi></msub><msup><mi>y</mi><mn>3</mn></msup><mi>d</mi><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">E(y^2) = \\frac{1}{A(L)} \\iint_{int(L)} y^2 dA = - \\frac{1}{3A(L)} \\oint_L y^3 dx</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3758em;vertical-align:-0.5307em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0005em;\">∬</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1693em;\"><span style=\"top:-2.3443em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">in</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.5307em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.3651em;vertical-align:-0.52em;\"></span><span class=\"mord\">−</span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">3</span><span class=\"mord mathnormal mtight\">A</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"margin-right:0.19445em;position:relative;top:-0.0006em;\">∮</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1225em;\"><span style=\"top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">L</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3558em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">x</span></span></span></span></li>\n</ul>\n<p>And for the covariance:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>C</mi><mi>o</mi><mi>v</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo separator=\"true\">,</mo><mi>y</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mfrac><mn>1</mn><mrow><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∬</mo><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></msub><mi>x</mi><mi>y</mi><mi>d</mi><mi>A</mi><mo>=</mo><mfrac><mn>1</mn><mrow><mn>4</mn><mi>A</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow></mfrac><msub><mo>∮</mo><mi>L</mi></msub><msup><mi>x</mi><mn>2</mn></msup><mi>y</mi><mi>d</mi><mi>y</mi><mo>−</mo><msup><mi>y</mi><mn>2</mn></msup><mi>x</mi><mi>d</mi><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">\nCov(x, y) = \\frac{1}{A(L)} \\iint_{int(L)} x y dA = \\frac{1}{4A(L)} \\oint_L x^2 y dy - y^2 x dx\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.4467em;vertical-align:-1.0867em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3214em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.936em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol large-op\" style=\"margin-right:0.44445em;position:relative;top:-0.001em;\">∬</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:-0.3867em;\"><span style=\"top:-1.7883em;margin-left:-0.4445em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">in</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">L</span><span class=\"mclose mtight\">)</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.0867em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.296em;vertical-align:-0.936em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3214em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">4</span><span class=\"mord mathnormal\">A</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.936em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\"><span class=\"mop op-symbol large-op\" style=\"margin-right:0.44445em;position:relative;top:-0.0011em;\">∮</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:-0.4336em;\"><span style=\"top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">L</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.9119em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0585em;vertical-align:-0.1944em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">x</span></span></span></span></span></p>\n<p>Finally, compute the largest eigenvector &amp; eigenvalue for the covariance matrix:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo fence=\"true\">[</mo><mtable rowspacing=\"0.16em\" columnalign=\"center center\" columnspacing=\"1em\"><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mi>V</mi><mi>a</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mi>C</mi><mi>o</mi><mi>v</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo separator=\"true\">,</mo><mi>y</mi><mo stretchy=\"false\">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mi>C</mi><mi>o</mi><mi>v</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo separator=\"true\">,</mo><mi>y</mi><mo stretchy=\"false\">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mi>V</mi><mi>a</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>y</mi><mo stretchy=\"false\">)</mo></mrow></mstyle></mtd></mtr></mtable><mo fence=\"true\">]</mo></mrow><annotation encoding=\"application/x-tex\">\n\\begin{bmatrix}\nVar(x) &amp; Cov(x, y) \\\\\nCov(x, y) &amp; Var(y)\n\\end{bmatrix}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.4em;vertical-align:-0.95em;\"></span><span class=\"minner\"><span class=\"mopen delimcenter\" style=\"top:0em;\"><span class=\"delimsizing size3\">[</span></span><span class=\"mord\"><span class=\"mtable\"><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.45em;\"><span style=\"top:-3.61em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">Va</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span><span style=\"top:-2.41em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.95em;\"><span></span></span></span></span></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.45em;\"><span style=\"top:-3.61em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span></span></span><span style=\"top:-2.41em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">Va</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.95em;\"><span></span></span></span></span></span></span></span><span class=\"mclose delimcenter\" style=\"top:0em;\"><span class=\"delimsizing size3\">]</span></span></span></span></span></span></span></p>\n<p>Since this is a symmetric matrix, a real eigenvalue &amp; eigenvector is guaranteed.</p>\n<h1>Computation</h1>\n<p>In practice, all curves are SVG paths. We first preprocess the paths to split them into non-overlapping components that do not self-intersect.</p>\n<p>Then we can use the <a href=\"https://docs.rs/lyon_algorithms/latest/lyon_algorithms/\"><code>lyon_algorithms</code></a> crate for sampling along a SVG path. Extra caution should be taken for the left-over segment at the end of the integration.</p>\n<p>For computing the eigenvalue and eigenvector, we used two tricks for 2x2 matrices, <a href=\"https://www.youtube.com/watch?v=e50Bj7jn9IQ\">one from 3b1b (YouTube)</a>, and <a href=\"https://math.stackexchange.com/questions/395698/fast-way-to-calculate-eigen-of-2x2-matrix-using-a-formula\">another one from math stackexchange</a>. For the following matrix:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><mo>=</mo><mrow><mo fence=\"true\">[</mo><mtable rowspacing=\"0.16em\" columnalign=\"center center\" columnspacing=\"1em\"><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mi>a</mi></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mi>b</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mi>c</mi></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mi>d</mi></mstyle></mtd></mtr></mtable><mo fence=\"true\">]</mo></mrow></mrow><annotation encoding=\"application/x-tex\">\nA = \\begin{bmatrix}\na &amp; b \\\\\nc &amp; d\n\\end{bmatrix}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.4em;vertical-align:-0.95em;\"></span><span class=\"minner\"><span class=\"mopen delimcenter\" style=\"top:0em;\"><span class=\"delimsizing size3\">[</span></span><span class=\"mord\"><span class=\"mtable\"><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.45em;\"><span style=\"top:-3.61em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span></span></span><span style=\"top:-2.41em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">c</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.95em;\"><span></span></span></span></span></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.45em;\"><span style=\"top:-3.61em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">b</span></span></span><span style=\"top:-2.41em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">d</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.95em;\"><span></span></span></span></span></span></span></span><span class=\"mclose delimcenter\" style=\"top:0em;\"><span class=\"delimsizing size3\">]</span></span></span></span></span></span></span></p>\n<p>Recall that the sum of eigenvalues <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>λ</mi><mn>1</mn></msub><mo>+</mo><msub><mi>λ</mi><mn>2</mn></msub><mo>=</mo><mi>t</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\lambda_1 + \\lambda_2 = tr(A)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span></span></span></span>, and the product of eigenvalues <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>λ</mi><mn>1</mn></msub><msub><mi>λ</mi><mn>2</mn></msub><mo>=</mo><mi>d</mi><mi>e</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\lambda_1 \\lambda_2 = det(A)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span></span></span></span>. So we can directly solve for the larger eigenvalue <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>λ</mi><mn>1</mn></msub><mo>=</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mi>t</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>+</mo><msqrt><mrow><mfrac><mn>1</mn><mn>4</mn></mfrac><mi>t</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>A</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup><mo>−</mo><mi>d</mi><mi>e</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo></mrow></msqrt></mrow><annotation encoding=\"application/x-tex\">\\lambda_1 = \\frac{1}{2} tr(A) + \\sqrt{\\frac{1}{4} tr(A)^2 - det(A)}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.1901em;vertical-align:-0.345em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">2</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.84em;vertical-align:-0.6049em;\"></span><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.2351em;\"><span class=\"svg-align\" style=\"top:-3.8em;\"><span class=\"pstrut\" style=\"height:3.8em;\"></span><span class=\"mord\" style=\"padding-left:1em;\"><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em;\"><span style=\"top:-2.655em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">4</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7401em;\"><span style=\"top:-2.989em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span></span></span><span style=\"top:-3.1951em;\"><span class=\"pstrut\" style=\"height:3.8em;\"></span><span class=\"hide-tail\" style=\"min-width:1.02em;height:1.88em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width='400em' height='1.88em' viewBox='0 0 400000 1944' preserveAspectRatio='xMinYMin slice'><path d='M983 90\nl0 -0\nc4,-6.7,10,-10,18,-10 H400000v40\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM1001 80h400000v40h-400000z'/></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6049em;\"><span></span></span></span></span></span></span></span></span>.</p>\n<p>Then, we can compute the (unnormalized) eigenvector corresponding to <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>λ</mi><mn>1</mn></msub></mrow><annotation encoding=\"application/x-tex\">\\lambda_1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> to be:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo fence=\"false\" stretchy=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">(</mo><mtable rowspacing=\"0.16em\" columnalign=\"center\" columnspacing=\"1em\"><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mi>b</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><msub><mi>λ</mi><mn>1</mn></msub><mo>−</mo><mi>a</mi></mrow></mstyle></mtd></mtr></mtable><mo fence=\"false\" stretchy=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">)</mo></mrow><annotation encoding=\"application/x-tex\">\n\\big(\n\\begin{matrix}\nb \\\\\n\\lambda_1 - a\n\\end{matrix}\n\\big)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.4em;vertical-align:-0.95em;\"></span><span class=\"mord\"><span class=\"delimsizing size1\">(</span></span><span class=\"mord\"><span class=\"mtable\"><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.45em;\"><span style=\"top:-3.61em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">b</span></span></span><span style=\"top:-2.41em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">a</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.95em;\"><span></span></span></span></span></span></span></span><span class=\"mord\"><span class=\"delimsizing size1\">)</span></span></span></span></span></span></p>\n<p>BTW, since we are dealing with a symmetric real matrix (<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mo>=</mo><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">b = c</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">c</span></span></span></span>), it’s guaranteed that:</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mtable rowspacing=\"0.25em\" columnalign=\"right left\" columnspacing=\"0em\"><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mrow></mrow><mo stretchy=\"false\">(</mo><mi>a</mi><mo>−</mo><mi>d</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup><mo>≥</mo><mn>0</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mrow></mrow><mo stretchy=\"false\">(</mo><mi>a</mi><mo>+</mo><mi>d</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup><mo>≥</mo><mn>4</mn><mi>a</mi><mi>d</mi><mo>≥</mo><mn>4</mn><mi>a</mi><mi>d</mi><mo>−</mo><mn>4</mn><mi>b</mi><mi>c</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mrow></mrow><mfrac><mn>1</mn><mn>4</mn></mfrac><mi>t</mi><mi>r</mi><mo stretchy=\"false\">(</mo><mi>A</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup><mo>=</mo><mfrac><mn>1</mn><mn>4</mn></mfrac><mo stretchy=\"false\">(</mo><mi>a</mi><mo>+</mo><mi>d</mi><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup><mo>≥</mo><mi>a</mi><mi>d</mi><mo>−</mo><mi>b</mi><mi>c</mi><mo>=</mo><mi>d</mi><mi>e</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding=\"application/x-tex\">\n\\begin{aligned}\n&amp; (a - d)^2 \\geq 0 \\\\\n\\implies &amp; (a + d)^2 \\geq 4 a d \\geq 4 a d - 4 b c \\\\\n\\implies &amp; \\frac{1}{4} tr(A)^2 = \\frac{1}{4} (a + d)^2 \\geq ad - bc = det(A)\n\\end{aligned}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:5.3557em;vertical-align:-2.4278em;\"></span><span class=\"mord\"><span class=\"mtable\"><span class=\"col-align-r\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.9278em;\"><span style=\"top:-5.3852em;\"><span class=\"pstrut\" style=\"height:3.3214em;\"></span><span class=\"mord\"></span></span><span style=\"top:-3.8611em;\"><span class=\"pstrut\" style=\"height:3.3214em;\"></span><span class=\"mord\"><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span></span><span style=\"top:-1.8796em;\"><span class=\"pstrut\" style=\"height:3.3214em;\"></span><span class=\"mord\"><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.4278em;\"><span></span></span></span></span></span><span class=\"col-align-l\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.9278em;\"><span style=\"top:-5.3852em;\"><span class=\"pstrut\" style=\"height:3.3214em;\"></span><span class=\"mord\"><span class=\"mord\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≥</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\">0</span></span></span><span style=\"top:-3.8611em;\"><span class=\"pstrut\" style=\"height:3.3214em;\"></span><span class=\"mord\"><span class=\"mord\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≥</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\">4</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">d</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≥</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\">4</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">d</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">4</span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">c</span></span></span><span style=\"top:-1.8796em;\"><span class=\"pstrut\" style=\"height:3.3214em;\"></span><span class=\"mord\"><span class=\"mord\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3214em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">4</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3214em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">4</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≥</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">d</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">c</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.4278em;\"><span></span></span></span></span></span></span></span></span></span></span></span></p>\n<p>Finally, we scale the eigenvector to have the length <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msqrt><msub><mi>λ</mi><mn>1</mn></msub></msqrt></mrow><annotation encoding=\"application/x-tex\">\\sqrt{\\lambda_1}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.04em;vertical-align:-0.1828em;\"></span><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8572em;\"><span class=\"svg-align\" style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\" style=\"padding-left:0.833em;\"><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span><span style=\"top:-2.8172em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"hide-tail\" style=\"min-width:0.853em;height:1.08em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width='400em' height='1.08em' viewBox='0 0 400000 1080' preserveAspectRatio='xMinYMin slice'><path d='M95,702\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl0 -0\nc5.3,-9.3,12,-14,20,-14\nH400000v40H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM834 80h400000v40h-400000z'/></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1828em;\"><span></span></span></span></span></span></span></span></span>, because now it repersent the “standard derivation” along that axis.</p>\n<h1>Result</h1>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/pca-scale.png\">\n  <figcaption>\n    Title from <a href=\"/post/isca2025-pt1\">the last post</a>\n  </figcaption>\n</figure>\n<p>The above figure shows the computed direction vector scaled by 10. Because the length of the original vector is the standard derivation along the principal axis, it’s almost always being covered by the stroke itself.</p>\n<p>Also because of this, the length of the vector does not directly reflect the “outer dimension” of the stroke. The distribution of thickness along the axis will affect the length of the vector. One may argue this is not a good indicator of the dimension of a shape. In that case, a distribution along the boundary of the shape may be used instead of the internal of the shape.</p>\n<p>But for me, this is good enough™, and does reflect the optical heaviness of the various part of a stroke, so I’m settling with this.</p>\n<hr />\n<p>Edit 06/29: We noticed a problem with the aforementioned approach to compute the length of direction vectors. When the primary and secondary component has similar derivation, the direction of the primary component alone may not actually suggest the shape of the original distribution. An example is the dot in the figure above.</p>\n<p>Instead, we choose to scale the direction vector based on the ratio between the derivations along primary and secondary component (square root of the two eigenvalues):</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>L</mi><mo>=</mo><mn>1</mn><mo>−</mo><msqrt><mrow><mo stretchy=\"false\">∣</mo><mfrac><msub><mi>λ</mi><mn>2</mn></msub><msub><mi>λ</mi><mn>1</mn></msub></mfrac><mo stretchy=\"false\">∣</mo></mrow></msqrt></mrow><annotation encoding=\"application/x-tex\">\nL = 1 - \\sqrt{\\lvert \\frac{\\lambda_2}{\\lambda_1} \\rvert}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.44em;vertical-align:-0.8384em;\"></span><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.6016em;\"><span class=\"svg-align\" style=\"top:-4.4em;\"><span class=\"pstrut\" style=\"height:4.4em;\"></span><span class=\"mord\" style=\"padding-left:1em;\"><span class=\"mopen\">∣</span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3714em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.836em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mclose\">∣</span></span></span><span style=\"top:-3.5616em;\"><span class=\"pstrut\" style=\"height:4.4em;\"></span><span class=\"hide-tail\" style=\"min-width:1.02em;height:2.48em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width='400em' height='2.48em' viewBox='0 0 400000 2592' preserveAspectRatio='xMinYMin slice'><path d='M424,2478\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl0 -0c4,-6.7,10,-10,18,-10 H400000\nv40H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M1001 80\nh400000v40h-400000z'/></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8384em;\"><span></span></span></span></span></span></span></span></span></span></p>\n<p>This mapping has the property that if <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>λ</mi><mn>1</mn></msub><mo>≈</mo><msub><mi>λ</mi><mn>2</mn></msub></mrow><annotation encoding=\"application/x-tex\">\\lambda_1 \\approx \\lambda_2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>, then <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">L = 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0</span></span></span></span>, effectively suggests that the shape has <em>no direction</em>. The more eccentric the fitted ellipsis is, the closer <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span> is to 1. One can also just the use ellipsis eccentricity.</p>\n<p>Numerically, <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>λ</mi><mn>1</mn></msub><mo>≈</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">\\lambda_1 \\approx 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">λ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0</span></span></span></span> indicates a small vector shape. A good fallback is to just return <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">L = 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0</span></span></span></span>.</p>\n<hr />\n<div class=\"footnotes\">\n- [1]: more concretely, SVG paths, or bezier curve segments with various orders.\n</div>","plain":"Edited 06-29: updated how to compute the length of the direction vector. See the end of this post.\nIntuitively, the Chinese stroke “㇐”U+31D0 has a horizontal direction, while “㇓”U+31D3 has a mostly top-right to bottom-left direction. How do we determine the “direction” of a stroke?\nFirst we need to figure out what is a stroke and what is a “direction”. Since we are working in a 2D plane, we can instead use a method for any closed loop without self-intersection. Most frequently, these shapes are represented in piecewise parametric curves[1], which is also the case for font-shapped characters from free-type fonts. One possible definition of “direction” is the main axis of the smallest bounding ellipsis. Computing the smallest bounding ellipsis is hard to do analytically, but we can deal with another form of ellipsis much more easily: statistics has given us a tool for dealing with fitted ellipsis: principal component analysis (PCA).\nIn practice, PCA is always used with samples, but instead we can abuse it to compute the ellipsis fitted to a multivariate distribution with known PDF. In our case, we can define the “direction” of a shape L to be the main axis of the ellipsis fitted to the uniform distribution over the internal of L.\n\nWhat do we need\nFirst, the PDF of the distribution over the internal of some shape closed L with internal int(L) and area A(L) is:\n\nf(\\mathbf{p}) = \\begin{cases} 0& \\mathbf{p} \\notin int(L),\\\\ 1 \\over A(L) & \\mathbf{p} \\in int(L), \\end{cases}\n\nSo first, we need to compute the area of L. Another subtle thing that needs to be determine is the orientation of L, because it’s not guaranteed that it has conter-clockwise orientation. Both of these can be computed in a single step by first assuming L has the correct orientation, compute the area A(L) as-is, and then judge the orientation by the sign of A(L).\n\nA(L) = \\iint_{int(L)} dA = \\oint_L x dy\n\nNow with the PDF fully defined, we need to compute the covariance matrix of this distribution. This in turn requires the following values:\n- Var(x) and Var(y)\n- Cov(x, y) = Cov(y, x)\nSince Var(x) = E(x^2) - E(x)^2 and Var(y) = E(y^2) - E(y)^2, so we need the first and second central moment of x and y, which are:\n- E(x) = \\frac{1}{A(L)} \\iint_{int(L)} x dA = \\frac{1}{2A(L)} \\oint_L x^2 dy\n- E(y) = \\frac{1}{A(L)} \\iint_{int(L)} y dA = - \\frac{1}{2A(L)} \\oint_L y^2 dx\n- E(x^2) = \\frac{1}{A(L)} \\iint_{int(L)} x^2 dA = \\frac{1}{3A(L)} \\oint_L x^3 dy\n- E(y^2) = \\frac{1}{A(L)} \\iint_{int(L)} y^2 dA = - \\frac{1}{3A(L)} \\oint_L y^3 dx\nAnd for the covariance:\n\nCov(x, y) = \\frac{1}{A(L)} \\iint_{int(L)} x y dA = \\frac{1}{4A(L)} \\oint_L x^2 y dy - y^2 x dx\n\nFinally, compute the largest eigenvector & eigenvalue for the covariance matrix:\n\n\\begin{bmatrix}\nVar(x) & Cov(x, y) \\\\\nCov(x, y) & Var(y)\n\\end{bmatrix}\n\nSince this is a symmetric matrix, a real eigenvalue & eigenvector is guaranteed.\n\nComputation\nIn practice, all curves are SVG paths. We first preprocess the paths to split them into non-overlapping components that do not self-intersect.\nThen we can use the lyon_algorithms crate for sampling along a SVG path. Extra caution should be taken for the left-over segment at the end of the integration.\nFor computing the eigenvalue and eigenvector, we used two tricks for 2x2 matrices, one from 3b1b (YouTube), and another one from math stackexchange. For the following matrix:\n\nA = \\begin{bmatrix}\na & b \\\\\nc & d\n\\end{bmatrix}\n\nRecall that the sum of eigenvalues \\lambda_1 + \\lambda_2 = tr(A), and the product of eigenvalues \\lambda_1 \\lambda_2 = det(A). So we can directly solve for the larger eigenvalue \\lambda_1 = \\frac{1}{2} tr(A) + \\sqrt{\\frac{1}{4} tr(A)^2 - det(A)}.\nThen, we can compute the (unnormalized) eigenvector corresponding to \\lambda_1 to be:\n\n\\big(\n\\begin{matrix}\nb \\\\\n\\lambda_1 - a\n\\end{matrix}\n\\big)\n\nBTW, since we are dealing with a symmetric real matrix (b = c), it’s guaranteed that:\n\n\\begin{aligned}\n& (a - d)^2 \\geq 0 \\\\\n\\implies & (a + d)^2 \\geq 4 a d \\geq 4 a d - 4 b c \\\\\n\\implies & \\frac{1}{4} tr(A)^2 = \\frac{1}{4} (a + d)^2 \\geq ad - bc = det(A)\n\\end{aligned}\n\nFinally, we scale the eigenvector to have the length \\sqrt{\\lambda_1}, because now it repersent the “standard derivation” along that axis.\n\nResult\nThe above figure shows the computed direction vector scaled by 10. Because the length of the original vector is the standard derivation along the principal axis, it’s almost always being covered by the stroke itself.\nAlso because of this, the length of the vector does not directly reflect the “outer dimension” of the stroke. The distribution of thickness along the axis will affect the length of the vector. One may argue this is not a good indicator of the dimension of a shape. In that case, a distribution along the boundary of the shape may be used instead of the internal of the shape.\nBut for me, this is good enough™, and does reflect the optical heaviness of the various part of a stroke, so I’m settling with this.\n---\nEdit 06/29: We noticed a problem with the aforementioned approach to compute the length of direction vectors. When the primary and secondary component has similar derivation, the direction of the primary component alone may not actually suggest the shape of the original distribution. An example is the dot in the figure above.\nInstead, we choose to scale the direction vector based on the ratio between the derivations along primary and secondary component (square root of the two eigenvalues):\n\nL = 1 - \\sqrt{\\lvert \\frac{\\lambda_2}{\\lambda_1} \\rvert}\n\nThis mapping has the property that if \\lambda_1 \\approx \\lambda_2, then L = 0, effectively suggests that the shape has no direction. The more eccentric the fitted ellipsis is, the closer L is to 1. One can also just the use ellipsis eccentricity.\nNumerically, \\lambda_1 \\approx 0 indicates a small vector shape. A good fallback is to just return L = 0.\n---\n"},{"metadata":{"id":"isca2025-pt1","lang":"zh-CN","title":"ISCA 2025 流水账 Part.1","tags":["学术蝗虫"],"publish_time":"2025-06-24T03:17:22+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761}],"text":"ISCA","hadv":2518,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"流","components":[["M 30 -613L 23 -608C 55 -568 91 -507 103 -451C 224 -371 328 -599 30 -613Z",[-0.266,0.29]],["M 95 -217C 84 -217 49 -217 49 -217L 49 -199C 70 -197 88 -192 102 -182C 127 -166 130 -65 109 43C 120 83 149 96 174 96C 230 96 271 60 273 5C 276 -87 229 -118 227 -177C 226 -202 234 -239 242 -271C 254 -321 313 -516 348 -621L 333 -625C 154 -273 154 -273 129 -237C 116 -217 112 -217 95 -217Z",[0.123,0.738]],["M 117 -842L 110 -837C 141 -793 177 -730 189 -670C 315 -584 429 -820 117 -842Z",[-0.291,0.293]],["M 538 -376L 377 -391L 377 -286C 377 -171 365 -19 254 86L 261 94C 468 12 502 -159 505 -284L 505 -350C 529 -353 536 -363 538 -376Z",[0.197,0.688]],["M 848 -781L 779 -687L 319 -687L 327 -659L 941 -659C 956 -659 967 -664 970 -675C 925 -718 848 -781 848 -781Z",[0.83,0.066]],["M 721 -621L 534 -684C 511 -635 427 -538 366 -515C 353 -509 334 -505 334 -505L 377 -368C 406 -377 433 -410 440 -489L 383 -489L 383 -478C 486 -501 629 -560 700 -613L 663 -607C 699 -598 717 -607 721 -621Z",[0.542,0.411]],["M 357 -500L 395 -379C 575 -427 722 -475 804 -504L 804 -518C 617 -507 433 -500 357 -500Z",[0.766,0.117]],["M 525 -857L 518 -852C 545 -817 566 -762 565 -710C 686 -612 825 -839 525 -857Z",[-0.109,0.162]],["M 704 -379L 550 -393L 550 64L 573 64C 619 64 676 42 676 33L 676 -357C 697 -360 703 -368 704 -379Z",[0.012,0.713]],["M 717 -608L 709 -602C 750 -551 798 -476 817 -408C 939 -328 1033 -563 717 -608Z",[-0.297,0.346]],["M 881 -379L 725 -392L 725 -34C 725 42 734 68 814 68L 854 68C 941 68 982 40 982 -7C 982 -29 977 -44 951 -58L 948 -179L 937 -179C 922 -129 906 -79 898 -64C 892 -55 888 -54 881 -53C 878 -53 874 -53 870 -53L 860 -53C 852 -53 850 -57 850 -68L 850 -353C 870 -356 879 -366 881 -379Z",[-0.12,0.528]]],"bbox":{"top":-857,"bottom":96,"left":23,"right":1033},"hadv":1000}],"text":"流","hadv":1000,"breakAfter":true},{"chars":[{"char":"水","components":[["M 262 -555C 237 -357 164 -145 16 -13L 24 -3C 255 -114 359 -307 405 -506C 428 -508 437 -512 444 -523L 320 -628L 250 -555Z",[0.328,0.695]],["M 42 -555L 51 -527L 317 -527L 317 -555Z",[-0.823,0.006]],["M 573 -809C 599 -813 606 -822 608 -836L 425 -854L 425 -83C 425 -71 419 -65 402 -65C 376 -65 250 -73 250 -73L 250 -60C 311 -49 334 -33 354 -11C 374 12 381 45 385 93C 550 79 573 26 573 -73Z",[0.043,0.811]],["M 573 -692L 566 -689C 603 -317 689 -146 848 -5C 868 -72 912 -124 972 -136L 977 -147C 806 -224 629 -365 573 -692Z",[-0.376,0.582]],["M 802 -692C 769 -617 695 -486 631 -401L 639 -392C 745 -444 852 -518 924 -574C 949 -571 959 -577 964 -587Z",[0.439,0.429]]],"bbox":{"top":-854,"bottom":93,"left":16,"right":977},"hadv":1000}],"text":"水","hadv":1000,"breakAfter":true},{"chars":[{"char":"账","components":[["M 343 -633L 206 -662C 206 -265 216 -62 25 71L 37 87C 311 -24 298 -238 305 -610C 328 -610 339 -620 343 -633Z",[0.152,0.809]],["M 68 -801L 68 -215L 87 -215C 144 -215 178 -236 178 -244L 178 -727L 331 -727L 331 -239L 351 -239C 408 -239 446 -262 446 -268L 446 -717C 469 -721 480 -728 487 -737L 382 -819L 327 -755L 189 -755Z",[0.032,0.18]],["M 269 -220L 259 -215C 297 -152 337 -64 346 13C 457 104 562 -119 269 -220Z",[-0.274,0.482]],["M 845 -518L 778 -427L 453 -427L 461 -399L 939 -399C 953 -399 964 -404 967 -415C 922 -457 845 -518 845 -518Z",[0.797,0.082]],["M 633 -780L 532 -780L 532 -117C 532 -90 525 -80 481 -50L 591 94C 619 73 649 14 618 -70L 553 -14L 666 -66L 666 -760Z",[0.018,0.831]],["M 506 -41L 601 80C 671 -2 725 -80 748 -120L 745 -128C 649 -90 550 -55 506 -41Z",[0.412,0.26]],["M 701 -836L 532 -855L 532 -735C 642 -735 662 -735 666 -735L 666 -813C 690 -817 699 -825 701 -836Z",[-0.53,0.066]],["M 953 -680L 792 -775C 765 -697 702 -568 640 -484L 648 -475C 752 -526 850 -604 914 -667C 938 -664 948 -670 953 -680Z",[0.42,0.499]],["M 736 -418L 724 -414C 736 -168 768 -43 859 70C 882 4 925 -37 979 -46L 981 -57C 867 -125 767 -220 736 -418Z",[-0.257,0.534]]],"bbox":{"top":-855,"bottom":104,"left":25,"right":981},"hadv":1000}],"text":"账","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Part","hadv":2215,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463}],"text":"1","hadv":463,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>看到 <a href=\"https://iscaconf.org/isca2025/\">ISCA 2025</a> 的注册费仅需 430 USD，于是决定前往日本公费旅游。虽然最后发现注册费这么便宜的一部分原因是会议没有午餐，能够出国参会还是很令人激动的一件事情。为了弥补上次 MICRO 2024 没有做一丁点记录的遗憾，决定在会议 Day3 晚上<del>熬夜</del>写一点感想。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-pigeon.jpg\">\n  <figcaption>早稲田大学前の鳩 @ Day3</figcaption>\n</figure>\n<h2>ISCA 2025</h2>\n<p>ISCA 作为传统体系结构最后的堡垒之一，Microarchitecture 也只能凑出两个会场了，ML Accelerator 都有三个，听的人也没有 LLM 会场的人多。不过 Best paper candidates 里还是有一个做硬核 Cache 压缩的和一个做内存序的，这两篇论文令我印象非常深刻，还是略微令人唏嘘。</p>\n<p>投稿总体而言，最大的印象是 PGO 的投稿数量非常多，相比于 MICRO 上的论文更多是在做微架构 Runtime 抓信息做各种优化，ISCA 看上去更能接受 AoT 方法，包括程序分析插 Hint 或者 PGO。</p>\n<p>决定来 ISCA 的很大一部分原因来自于 Session 1C 第一个 Pre <a href=\"https://dl.acm.org/doi/10.1145/3695053.3731011\"><em>Heliostat: Harnessing Ray Tracing Accelerators for Page Table Walks</em></a>，这个看上去就很神秘的题目。没想到坐到现场，发现还不止这一个，DSA Session 那边还有一个 <a href=\"https://dl.acm.org/doi/10.1145/3695053.3731072\"><em>RTSpMSpM: Harnessing Ray Tracing for Efficient Sparse Matrix Computations\n</em></a>，以及还有两篇做 Ray Tracing 自己的优化的，这难道是最新最热 Arch 话题吗？？</p>\n<p>ISCA 2025 本质美食节，虽然没有午餐令人精神萎靡，但是有不限量全天候免费供应的面包和饮料，又很好地弥补了这一点。三种面包都很好吃，唯一美中不足的是放在签到和 Poster 的楼里，距离几个 Venue 均有几分钟路程，逼迫大家在会场昏昏欲睡和休息室大吃大喝之间二选一，根本不可能去好好听 Pre 的。前两天甚至午饭发剩下的盒饭还分给各位没有报名 Workshop 的蹭会同学，也十分好吃。</p>\n<p>Reception 晚宴也狂吃，喝了大量果汁，I 人不可能去 Social 的，都是被抓来 Social。第一次参会 MICRO 的 Reception 晚宴没去，躲在房间里肝 Slide，这次出来没有 Pre，无事一身轻。明天晚上的 Banquet 有神秘 <em>Japanese Garden Walk (finding Japanese Fireflies)</em> 活动，当时 MICRO 的 Banquet 是一个黑灯瞎火的露天 BBQ，软饮甚至限量，体验十分不好。考虑到这三天都吃的非常开心，还是挺期待明晚的 Banquet。</p>\n<h2>早大</h2>\n<p>从早稻田大学的地铁站走到早稻田大学的樱花线电车站，中间可以经过一个公交站，叫作早大正门，位于<ruby>早大<rt>そうだい</rt></ruby>通り上。会议主会场就围绕在这个公交站/路两侧，然而在这附近转了三天，我还是没有成功找到早大真正的正门。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-venue.jpg\">\n  <figcaption>会场之一 - 大隈讲堂 @ Day3</figcaption>\n</figure>\n<p>即使考虑到是开放式校园，早稻田大学的占地面积惊人的小，从最南端走到最北端只需三分钟，可能只是包含了核心区域。另一个令人吃惊的地方是并没有看到多少实验室和教学楼，不知道学生都待在哪里呢？</p>\n<p>Day2 晚上的 Reception 晚宴结束后，被群友带着坐了樱电，晚上始发站停着的电车有一种温馨而神秘的感觉，让人ワクワク的。剩下两天会议的通勤打算从坐地铁改成樱电，希望这种特殊的感觉不要被阳光赶跑呢。</p>\n<figure>\n  <video controls>\n    <source src=\"https://layered-assets.thu.fail/isca2025-sakuraline.mp4\">\n  </video>\n  <figcaption>Warning: 30+MB Video w/ Sound! 都電荒川線 @ Day3</figcaption>\n</figure>\n<h2>酒店</h2>\n<p>酒店住的是池袋的<a href=\"https://www.tokyustay.co.jp/\">東急ステイ</a>，主要原因是有洗衣机。目前体验非常良好，房间里设施很够用，用得最多的除了洗衣机以外，主要是冰箱还有浴缸。第一天逛 711 购买了第一次见到的杯面口味还有 2L 宝矿力扔到冰箱里，今天才把刚消灭掉。房间里还有微波炉和餐具，是为早餐准备的。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-noodle.jpg\">\n  <figcaption>杯面 @ Day3</figcaption>\n</figure>\n<p>早餐有两类可选，一类是冷冻面包/饭团，可以拿到屋子里热着吃，还有一类是现场煲的咖喱，作为社恐人不想跟别人抢炊具所以没有体验<small>（其实是面包很好吃一下子就跑到局部最小里了）</small>。令人感动的是酒店早餐有早晚两场，甚至早餐券可以在日期当天之后三个月内使用，所以即使早上起晚了或者急着出门，之后也可以拿到，事实上这三天只正点吃了一次早饭。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-breakfast.jpg\">\n  <figcaption>早餐 @ Day1。其实还可以接一杯麦片，里面有草莓干哦</figcaption>\n</figure>\n<p>屋子里有一个智能电视 Powered by Android，虽然我鼓捣半天还是没有搞明白有没有办法随便投屏，不过躺在床上可以看 YouTube 还是很舒服的。</p>\n<p>大约 16000 JPY 每天的价格对于东京市中心来说还是平价，如果我有钱下次来东京的话一定还住。没钱咋办呢？希望有群友收留我把。</p>\n<h2>遛弯</h2>\n<p>最后写一些这两天的其他零零散散四处游玩感想。虽说是四处游玩，最后还是跑了两天秋叶原，令人难绷。</p>\n<p>入境的时候第一次体验 Visit Japan Web，电子申报实在是太现代了，不过我走到海关门口才知道要如何操作，结果多被关在里面十几分钟。</p>\n<p>Day1 晚上被居住在調布市的群友邀请至家中玩，吃了中华料理。经她介绍租住在这里主要就是为了每天在多摩川遛弯，并带我们执行了一个溜。傍晚的河边日落好看到能让人忘记所有焦虑，只可惜我的手机镜头太菜，根本拍不出来。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-river.jpg\">\n  <figcaption>多摩川 @ Day1</figcaption>\n</figure>\n<p>之后两天每天都在秋叶原中古店乱逛，希望能偶遇动心的塑料小人，不过感觉因为步入中年，绝大多数时间内心如一片死水（可能只是因为不认识人了），反而是来来回回的路上偶遇了一些很好看的景色，强行尝试手机拍照半天最后迟到了 Reception 晚宴。也许这才是“偶遇”的精髓呢。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-station.jpg\">\n  <figcaption>饭田桥 @ Day2</figcaption>\n</figure>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-station-2.jpg\">\n  <figcaption>早稻田 @ Day2</figcaption>\n</figure>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-station-3.jpg\">\n  <figcaption>饭田桥 @ Day3</figcaption>\n</figure>\n<p>数了一下，目前打算买的，最后大概有一个手办，还有几本厕纸，仅此而已。列出来以后甚至觉得有点浪费 JAL 的行李额，不过也很有满足感了；生活中能有这样一小点的非日常，就像草莓味的可尔必思一样，大概的确是十分幸运的事情。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-figure.jpg\">\n  <figcaption>塑料小人 @ Day3</figcaption>\n</figure>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/isca2025-milk.jpg\">\n  <figcaption>🍓 @ Day1</figcaption>\n</figure>","plain":"看到 ISCA 2025 的注册费仅需 430 USD，于是决定前往日本公费旅游。虽然最后发现注册费这么便宜的一部分原因是会议没有午餐，能够出国参会还是很令人激动的一件事情。为了弥补上次 MICRO 2024 没有做一丁点记录的遗憾，决定在会议 Day3 晚上熬夜写一点感想。\n\nISCA 2025\nISCA 作为传统体系结构最后的堡垒之一，Microarchitecture 也只能凑出两个会场了，ML Accelerator 都有三个，听的人也没有 LLM 会场的人多。不过 Best paper candidates 里还是有一个做硬核 Cache 压缩的和一个做内存序的，这两篇论文令我印象非常深刻，还是略微令人唏嘘。\n投稿总体而言，最大的印象是 PGO 的投稿数量非常多，相比于 MICRO 上的论文更多是在做微架构 Runtime 抓信息做各种优化，ISCA 看上去更能接受 AoT 方法，包括程序分析插 Hint 或者 PGO。\n决定来 ISCA 的很大一部分原因来自于 Session 1C 第一个 Pre Heliostat: Harnessing Ray Tracing Accelerators for Page Table Walks，这个看上去就很神秘的题目。没想到坐到现场，发现还不止这一个，DSA Session 那边还有一个 RTSpMSpM: Harnessing Ray Tracing for Efficient Sparse Matrix Computations ，以及还有两篇做 Ray Tracing 自己的优化的，这难道是最新最热 Arch 话题吗？？\nISCA 2025 本质美食节，虽然没有午餐令人精神萎靡，但是有不限量全天候免费供应的面包和饮料，又很好地弥补了这一点。三种面包都很好吃，唯一美中不足的是放在签到和 Poster 的楼里，距离几个 Venue 均有几分钟路程，逼迫大家在会场昏昏欲睡和休息室大吃大喝之间二选一，根本不可能去好好听 Pre 的。前两天甚至午饭发剩下的盒饭还分给各位没有报名 Workshop 的蹭会同学，也十分好吃。\nReception 晚宴也狂吃，喝了大量果汁，I 人不可能去 Social 的，都是被抓来 Social。第一次参会 MICRO 的 Reception 晚宴没去，躲在房间里肝 Slide，这次出来没有 Pre，无事一身轻。明天晚上的 Banquet 有神秘 Japanese Garden Walk (finding Japanese Fireflies) 活动，当时 MICRO 的 Banquet 是一个黑灯瞎火的露天 BBQ，软饮甚至限量，体验十分不好。考虑到这三天都吃的非常开心，还是挺期待明晚的 Banquet。\n\n早大\n从早稻田大学的地铁站走到早稻田大学的樱花线电车站，中间可以经过一个公交站，叫作早大正门，位于早大そうだい通り上。会议主会场就围绕在这个公交站/路两侧，然而在这附近转了三天，我还是没有成功找到早大真正的正门。\n即使考虑到是开放式校园，早稻田大学的占地面积惊人的小，从最南端走到最北端只需三分钟，可能只是包含了核心区域。另一个令人吃惊的地方是并没有看到多少实验室和教学楼，不知道学生都待在哪里呢？\nDay2 晚上的 Reception 晚宴结束后，被群友带着坐了樱电，晚上始发站停着的电车有一种温馨而神秘的感觉，让人ワクワク的。剩下两天会议的通勤打算从坐地铁改成樱电，希望这种特殊的感觉不要被阳光赶跑呢。\n\n酒店\n酒店住的是池袋的東急ステイ，主要原因是有洗衣机。目前体验非常良好，房间里设施很够用，用得最多的除了洗衣机以外，主要是冰箱还有浴缸。第一天逛 711 购买了第一次见到的杯面口味还有 2L 宝矿力扔到冰箱里，今天才把刚消灭掉。房间里还有微波炉和餐具，是为早餐准备的。\n早餐有两类可选，一类是冷冻面包/饭团，可以拿到屋子里热着吃，还有一类是现场煲的咖喱，作为社恐人不想跟别人抢炊具所以没有体验（其实是面包很好吃一下子就跑到局部最小里了）。令人感动的是酒店早餐有早晚两场，甚至早餐券可以在日期当天之后三个月内使用，所以即使早上起晚了或者急着出门，之后也可以拿到，事实上这三天只正点吃了一次早饭。\n屋子里有一个智能电视 Powered by Android，虽然我鼓捣半天还是没有搞明白有没有办法随便投屏，不过躺在床上可以看 YouTube 还是很舒服的。\n大约 16000 JPY 每天的价格对于东京市中心来说还是平价，如果我有钱下次来东京的话一定还住。没钱咋办呢？希望有群友收留我把。\n\n遛弯\n最后写一些这两天的其他零零散散四处游玩感想。虽说是四处游玩，最后还是跑了两天秋叶原，令人难绷。\n入境的时候第一次体验 Visit Japan Web，电子申报实在是太现代了，不过我走到海关门口才知道要如何操作，结果多被关在里面十几分钟。\nDay1 晚上被居住在調布市的群友邀请至家中玩，吃了中华料理。经她介绍租住在这里主要就是为了每天在多摩川遛弯，并带我们执行了一个溜。傍晚的河边日落好看到能让人忘记所有焦虑，只可惜我的手机镜头太菜，根本拍不出来。\n之后两天每天都在秋叶原中古店乱逛，希望能偶遇动心的塑料小人，不过感觉因为步入中年，绝大多数时间内心如一片死水（可能只是因为不认识人了），反而是来来回回的路上偶遇了一些很好看的景色，强行尝试手机拍照半天最后迟到了 Reception 晚宴。也许这才是“偶遇”的精髓呢。\n数了一下，目前打算买的，最后大概有一个手办，还有几本厕纸，仅此而已。列出来以后甚至觉得有点浪费 JAL 的行李额，不过也很有满足感了；生活中能有这样一小点的非日常，就像草莓味的可尔必思一样，大概的确是十分幸运的事情。\n"},{"metadata":{"id":"changchun-marathon","lang":"zh-CN","title":"长春马拉松","tags":["走路猫"],"publish_time":"2025-06-06T18:16:56+08:00","update_time":"2025-06-24T03:17:22+08:00","title_outline":{"groups":[{"chars":[{"char":"长","components":[["M 838 -543L 763 -441L 36 -441L 44 -413L 945 -413C 960 -413 971 -418 974 -429C 924 -475 838 -543 838 -543Z",[0.91,0.041]],["M 334 -782L 219 -782L 219 -132C 219 -105 211 -93 162 -60L 285 101C 316 76 349 12 315 -83L 241 -20L 372 -80L 372 -759Z",[0.022,0.815]],["M 197 -56L 291 82C 429 -9 528 -91 578 -139L 576 -147C 418 -106 265 -69 197 -56Z",[0.581,0.25]],["M 405 -836L 219 -857L 219 -737C 345 -737 367 -737 372 -737L 372 -814C 394 -817 403 -825 405 -836Z",[-0.774,0.072]],["M 854 -712L 695 -834C 617 -732 454 -581 301 -486L 307 -476C 504 -527 693 -621 814 -703C 837 -697 848 -703 854 -712Z",[0.595,0.395]],["M 498 -438L 486 -432C 542 -165 667 -27 850 71C 872 2 915 -42 976 -53L 978 -65C 779 -120 573 -222 498 -438Z",[-0.526,0.455]]],"bbox":{"top":-857,"bottom":101,"left":36,"right":978},"hadv":1000}],"text":"长","hadv":1000,"breakAfter":true},{"chars":[{"char":"春","components":[["M 579 -823L 376 -857C 358 -622 287 -344 16 -158L 23 -150C 377 -279 493 -528 540 -797C 565 -798 576 -808 579 -823Z",[0.363,0.681]],["M 833 -550L 758 -456L 36 -456L 44 -428L 941 -428C 956 -428 968 -433 970 -444C 919 -487 833 -550 833 -550Z",[0.888,0.039]],["M 799 -808L 727 -717L 75 -717L 83 -689L 901 -689C 916 -689 927 -694 930 -705C 881 -747 799 -808 799 -808Z",[0.797,0.045]],["M 740 -672L 673 -588L 114 -588L 122 -560L 834 -560C 848 -560 859 -565 862 -576C 816 -615 740 -672 740 -672Z",[0.849,0.046]],["M 391 52L 391 -318L 405 -318L 268 -367L 241 -332L 241 94L 269 94C 346 94 391 62 391 52Z",[0.0,0.656]],["M 699 -4L 305 -4L 305 24L 699 24Z",[0.929,0.001]],["M 699 -318L 305 -318L 305 -290L 699 -290Z",[-0.949,0.014]],["M 699 -167L 305 -167L 305 -139L 699 -139Z",[-0.964,0.009]],["M 591 -318L 599 -318L 599 90L 627 90C 679 90 754 61 755 52L 755 -276C 769 -279 777 -285 781 -290L 655 -385Z",[0.009,0.629]],["M 668 -453L 654 -441C 701 -319 780 -216 889 -165C 894 -220 929 -265 986 -304L 988 -319C 871 -325 729 -359 668 -453Z",[-0.421,0.237]]],"bbox":{"top":-857,"bottom":94,"left":16,"right":988},"hadv":1000}],"text":"春","hadv":1000,"breakAfter":true},{"chars":[{"char":"马","components":[["M 614 -297L 539 -201L 36 -201L 44 -173L 722 -173C 736 -173 748 -178 751 -189C 699 -233 614 -297 614 -297Z",[0.879,0.053]],["M 706 -797L 126 -797L 135 -769L 706 -769Z",[0.685,0.009]],["M 438 -690L 254 -725C 250 -654 220 -458 198 -374L 236 -412C 214 -404 188 -386 173 -370L 307 -299L 355 -362L 348 -362C 365 -444 393 -621 402 -689L 393 -665C 423 -664 435 -677 438 -690Z",[0.122,0.614]],["M 868 -390L 297 -390L 297 -362L 868 -362Z",[0.839,0.017]],["M 780 -390L 791 -390C 782 -198 768 -76 740 -54C 731 -47 723 -45 706 -45C 682 -45 599 -49 542 -53L 542 -43C 597 -32 640 -15 662 8C 684 28 689 57 689 97C 771 98 814 88 852 59C 909 16 929 -98 941 -336C 963 -339 975 -346 983 -355L 857 -463Z",[0.192,0.579]],["M 626 -797L 637 -797C 632 -691 618 -510 599 -374C 669 -363 719 -368 754 -388C 768 -494 783 -654 789 -744C 810 -748 823 -757 829 -765L 684 -871Z",[0.076,0.657]]],"bbox":{"top":-871,"bottom":98,"left":36,"right":983},"hadv":1000}],"text":"马","hadv":1000,"breakAfter":true},{"chars":[{"char":"拉","components":[["M 327 -839L 151 -855L 151 -91C 151 -80 146 -74 131 -74C 108 -74 7 -80 7 -80L 7 -67C 58 -56 79 -41 95 -16C 110 8 116 44 119 95C 271 80 291 24 291 -76L 291 -810C 316 -814 326 -824 327 -839Z",[0.038,0.826]],["M 18 -375L 70 -212C 83 -216 94 -228 99 -241C 253 -333 359 -409 423 -459L 421 -469C 258 -426 83 -387 18 -375Z",[0.605,0.274]],["M 329 -706L 270 -615L 20 -615L 28 -587L 404 -587C 418 -587 429 -592 431 -603C 395 -644 329 -706 329 -706Z",[0.796,0.083]],["M 851 -107L 775 -4L 333 -4L 341 24L 960 24C 975 24 986 19 989 8C 938 -38 851 -107 851 -107Z",[0.859,0.061]],["M 842 -717L 769 -620L 421 -620L 429 -592L 945 -592C 959 -592 971 -597 973 -608C 925 -652 842 -717 842 -717Z",[0.72,0.091]],["M 466 -532L 454 -527C 500 -394 496 -223 485 -119C 560 36 796 -215 466 -532Z",[-0.086,0.637]],["M 526 -854L 519 -849C 557 -801 591 -731 599 -664C 734 -563 863 -825 526 -854Z",[-0.209,0.27]],["M 921 -494L 727 -540C 718 -380 693 -146 662 19L 686 19C 772 -136 843 -338 882 -470C 907 -471 917 -481 921 -494Z",[0.192,0.707]]],"bbox":{"top":-855,"bottom":95,"left":7,"right":989},"hadv":1000}],"text":"拉","hadv":1000,"breakAfter":true},{"chars":[{"char":"松","components":[["M 289 -584L 289 -600L 151 -600C 130 -439 85 -257 11 -132L 22 -122C 159 -242 251 -397 289 -584Z",[0.285,0.701]],["M 357 -702L 295 -600L 22 -600L 30 -572L 437 -572C 452 -572 462 -577 465 -588C 428 -632 357 -702 357 -702Z",[0.751,0.08]],["M 341 -836L 164 -853L 164 95L 192 95C 245 95 304 67 304 56L 304 -807C 332 -811 339 -821 341 -836Z",[0.004,0.849]],["M 293 -471L 284 -466C 310 -416 335 -346 338 -282C 443 -189 566 -395 293 -471Z",[-0.2,0.384]],["M 784 -396L 596 -480C 578 -363 497 -157 444 -100C 432 -90 400 -82 400 -82L 450 92C 488 80 521 30 529 -61L 456 -61L 456 -47C 560 -120 694 -282 756 -392L 724 -384C 759 -373 778 -383 784 -396Z",[0.362,0.678]],["M 690 -765L 499 -812C 489 -656 455 -485 415 -369L 426 -362C 528 -451 601 -579 650 -742C 674 -743 686 -752 690 -765Z",[0.236,0.645]],["M 430 -82L 472 67C 655 4 797 -59 873 -97L 873 -108C 689 -94 504 -84 430 -82Z",[0.689,0.147]],["M 726 -263L 716 -258C 761 -162 806 -46 817 62C 960 188 1085 -106 726 -263Z",[-0.235,0.47]],["M 826 -812L 736 -858L 725 -854C 744 -585 791 -439 904 -339C 915 -393 956 -455 987 -483L 989 -495C 894 -542 797 -647 757 -799L 763 -752C 791 -775 813 -795 826 -812Z",[-0.241,0.628]]],"bbox":{"top":-858,"bottom":188,"left":11,"right":1085},"hadv":1000}],"text":"松","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>5月23日去了长春，跑了上半年最后一场半马！长春真的是很有趣的城市，这两天玩的很开心，还见到了群友，诶嘿。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/changchun-magnet.jpg\">\n  <figcaption>买到的冰箱贴！</figcaption>\n</figure>\n<h2>赛事</h2>\n<p>比赛组织水平还是挺在线的，跑得比较摆，全程心率 160 诚信有氧，结果比上周银川还要快一点。</p>\n<p>赛道比较拥挤，部分原因是两枪，但我觉得主要原因是我晚到起点了，嘻嘻。正好在存包车关门的时候赶上了，结果 C 区的人已经走到好前面了，只能和 D 区一起出发。完赛之后可以免费领取冰棍！但是吃了一半就化了掉到地上，GG。天气实在还是太热了。</p>\n<p>确实是只要够摆烂，就不会膝盖疼，可能以后尝试全马的时候配速的保持到 &gt;410 左右。下次冲着破三跑把。</p>\n<p>赛道一起点就经过了华北师范大学，感觉这附近好熟悉，才想起来去年来过一次长春开会，甚至吃早餐的麦当劳就是当时吃过的同一个。看来以后出去玩还是要多记录一下，之后全都忘记了。</p>\n<h2>Vaporfly 3</h2>\n<p>去长春前在群友的建议下买了 Vaporfly 3, 正好当作试穿。</p>\n<p>第一感觉是真轻，比穿过所有的跑鞋都要轻。第二感觉是缓冲没有想象中的好。最近两年穿的路跑鞋都是国产堆料鞋（飞电 4C,再之前是飞燃 ST），减震效果明显要弱于国内的跑鞋。一开始还比较担心，因为我步频比较低落地比较沉，所以可能更容易受伤，不过看来半马长度还是没啥问题的。不过确实不能当作训练鞋来穿。</p>\n<p>碳板部分因为已经习惯碳板的脚感了，所以和其他的跑鞋没有明显感到的区别。等再穿一段时间再做细节评测，不过目前来看考虑到耐克鞋的寿命稍微会更长一些，还是不错的。</p>\n<h2>逛商场</h2>\n<p>最后一天和群友光速逛了这有山，设计非常有趣！一路上给群友 Yap 了半天景区设计的逻辑，实在是很不好意思（</p>\n<p>了解到这个商场是因为前一天在对面的万达吃饭，最后要还一个充电宝，结果在这有山里迷路了半个多小时。商场内部结构类似于景区或者赌场，通过不断分叉的路径、台阶还有转弯以达成让游客在其中有一种探索的感觉，鼓励游客发现之前可能并没有兴趣的店铺。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/changchun-mall1.jpg\">\n  <img src=\"https://layered-assets.thu.fail/changchun-mall2.jpg\">\n  <figcaption>商场内景</figcaption>\n</figure>\n<p>商场门口有一辆有轨电车车厢改造成的纪念品商店，经群友介绍长春现在还有运行的有轨电车，希望下次有机会再来长春还能尝试坐一次呢。北京距离长春四个小时的高铁车程，回来的路上香喷喷地睡了一觉。</p>\n<figure>\n  <img src=\"https://layered-assets.thu.fail/changchun-store.jpg\">\n  <figcaption>🐱</figcaption>\n</figure>","plain":"5月23日去了长春，跑了上半年最后一场半马！长春真的是很有趣的城市，这两天玩的很开心，还见到了群友，诶嘿。\n\n赛事\n比赛组织水平还是挺在线的，跑得比较摆，全程心率 160 诚信有氧，结果比上周银川还要快一点。\n赛道比较拥挤，部分原因是两枪，但我觉得主要原因是我晚到起点了，嘻嘻。正好在存包车关门的时候赶上了，结果 C 区的人已经走到好前面了，只能和 D 区一起出发。完赛之后可以免费领取冰棍！但是吃了一半就化了掉到地上，GG。天气实在还是太热了。\n确实是只要够摆烂，就不会膝盖疼，可能以后尝试全马的时候配速的保持到 >410 左右。下次冲着破三跑把。\n赛道一起点就经过了华北师范大学，感觉这附近好熟悉，才想起来去年来过一次长春开会，甚至吃早餐的麦当劳就是当时吃过的同一个。看来以后出去玩还是要多记录一下，之后全都忘记了。\n\nVaporfly 3\n去长春前在群友的建议下买了 Vaporfly 3, 正好当作试穿。\n第一感觉是真轻，比穿过所有的跑鞋都要轻。第二感觉是缓冲没有想象中的好。最近两年穿的路跑鞋都是国产堆料鞋（飞电 4C,再之前是飞燃 ST），减震效果明显要弱于国内的跑鞋。一开始还比较担心，因为我步频比较低落地比较沉，所以可能更容易受伤，不过看来半马长度还是没啥问题的。不过确实不能当作训练鞋来穿。\n碳板部分因为已经习惯碳板的脚感了，所以和其他的跑鞋没有明显感到的区别。等再穿一段时间再做细节评测，不过目前来看考虑到耐克鞋的寿命稍微会更长一些，还是不错的。\n\n逛商场\n最后一天和群友光速逛了这有山，设计非常有趣！一路上给群友 Yap 了半天景区设计的逻辑，实在是很不好意思（\n了解到这个商场是因为前一天在对面的万达吃饭，最后要还一个充电宝，结果在这有山里迷路了半个多小时。商场内部结构类似于景区或者赌场，通过不断分叉的路径、台阶还有转弯以达成让游客在其中有一种探索的感觉，鼓励游客发现之前可能并没有兴趣的店铺。\n商场门口有一辆有轨电车车厢改造成的纪念品商店，经群友介绍长春现在还有运行的有轨电车，希望下次有机会再来长春还能尝试坐一次呢。北京距离长春四个小时的高铁车程，回来的路上香喷喷地睡了一觉。\n"},{"metadata":{"id":"usb-uas-quirks-on-mtk","lang":"zh-CN","title":"UAS Quirks on MTK chipsets","tags":["灵车"],"publish_time":"2025-05-24T04:59:08+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"U","components":[["M 36 -713L 198 -698L 228 -698L 392 -713L 392 -747L 36 -747Z",[-0.815,0.01]],["M 417 20C 595 20 692 -84 695 -314L 699 -747L 647 -747L 651 -316C 653 -135 586 -62 470 -62C 355 -62 295 -129 295 -312L 295 -406C 295 -520 295 -634 297 -747L 121 -747C 125 -633 125 -518 125 -406L 125 -297C 125 -61 245 20 417 20Z",[-0.062,0.22]],["M 533 -713L 657 -697L 689 -697L 802 -713L 802 -747L 533 -747Z",[-0.295,0.048]]],"bbox":{"top":-747,"bottom":20,"left":36,"right":802},"hadv":829},{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612}],"text":"UAS","hadv":2202,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"Q","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]],["M 560 230C 614 230 667 216 707 193L 695 164C 667 177 645 180 616 180C 520 180 461 109 475 -5L 313 -5L 313 3C 313 125 392 230 560 230Z",[-0.487,0.331]]],"bbox":{"top":-767,"bottom":230,"left":43,"right":752},"hadv":795},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Quirks","hadv":3549,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"K","components":[["M 41 -0L 376 -0L 376 -34L 232 -50L 202 -50L 41 -34Z",[0.86,0.001]],["M 41 -713L 202 -698L 232 -698L 387 -713L 387 -747L 41 -747Z",[-0.509,0.016]],["M 130 -0L 299 -0C 296 -117 296 -230 296 -330L 296 -395C 296 -514 296 -632 299 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.781]],["M 210 -187L 680 -747L 625 -747L 256 -291L 230 -257L 208 -257Z",[0.603,0.717]],["M 556 -0L 741 -0L 466 -509L 359 -384Z",[-0.331,0.611]],["M 465 -0L 783 -0L 783 -34L 639 -50L 614 -50L 465 -34Z",[0.855,0.002]],["M 484 -713L 600 -697L 631 -698L 746 -713L 746 -747L 484 -747Z",[0.587,0.039]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":783},"hadv":786}],"text":"MTK","hadv":2514,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"chipsets","hadv":4342,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>很久之前买了一个 CMCC RAX3000M <strong>算力版</strong><sup>[1]</sup>路由器放在工位当作内网接入隧道对端（因为工位偷电放了一台共享龙芯 3A6000，从家宽打了个 Socat SSH 出去）。这台路由器正好还有一个 USB3.0 口，这不正好，在路由器上接硬盘，当然是 Network-attached Storage，所以买了条易驱线，从工位翻了块儿没人用的硬盘出来。</p>\n<p>不幸的是，路由器的 SoC 是 MT7981B。而 MTK 的 USB Host，有点<a href=\"https://github.com/openwrt/openwrt/issues/15536\">和 UAS</a> <a href=\"https://forum.gl-inet.com/t/usb-3-0-speeds-for-smb-share-on-mt2500/42939/15\">不对付</a>。</p>\n<p><img src=\"https://layered-assets.thu.fail/mtk-uas.jpg\" alt=\"dmesg\" /></p>\n<p>在我这里的现象是当写入到了一定量之后，USB Root bus 的状态可能损坏了，之后根本读写不了东西，读写很少数量就会 Soft reset，之后重新连上。由于硬盘是 ST3000VX000-1CU166 是 ST3000DM001 的马甲，我都担心盘坏了，结果换了三张盘都有问题，感觉不太对劲。硬盘盒也是刚换的，之前以为是电源或者硬盘盒坏了，整体换了一次，这次终于找到了罪魁祸首。</p>\n<p>于是只能关闭 UAS，使用 <code>usb-storage</code> 驱动，而不是 <code>usb-storage-uas</code>。</p>\n<pre><code># Disable autoload of usb-storage-uas kmod\nrm /etc/modules.d/usb-storage-uas\n\n# Manually claim the device using usb-storage\necho \"usb-storage quirks=174c:55aa:u\" &gt; /etc/modules.d/usb-storage\n</code></pre>\n<p>在线切换 Driver 的方法可以参考<a href=\"https://github.com/openwrt/openwrt/issues/15536#issuecomment-2143067555\">这个 Issue 评论</a>。</p>\n<p>事实上，一共试了两个线，一个是 ORICO 的硬盘盒，一个是绿联的典中典易驱线。前者 USB ID 是 <a href=\"linux-hardware.org/?id=usb:0080-a001\">0080:a001</a>，<code>usb-storage</code> 甚至无法带起来，只有 UAS 才能带起来。所以看起来只能在 x86 上稳定使用了。后者的 ID 是 <a href=\"https://linux-hardware.org/?id=usb:174c-55aa\">174c:55aa</a>，使用 <code>usb-storage</code> 驱动之后至少是可以用的，速度因为挂的是 HDD 所以也没看出来太大的区别。另外购买的一个绿联 USB 硬盘盒也是同一个芯片。所以如果在使用 MTK Chipset 挂 USB 硬盘的话，推荐还是用绿联的，至少 Less 灵一些。</p>\n<p>P.S. SMART 和 UAS 在有的时候<a href=\"https://www.smartmontools.org/wiki/SAT-with-UAS-Linux\">也不对付</a>。我这里看到的现象是当 Root bus 状态坏掉以后，执行任何的 SMART Self-test 也会 soft reset，dmesg 出现的内容也是类似上图中的 <code>Transfer event for unknown stream ring slot</code>，感觉也是和 SAT 命令的处理有关，不过这次是 Root hub 没有正确处理。</p>\n<hr />\n<div class=\"footnotes\">\n<ul>\n<li>[1] 一定要 show off 一下</li>\n</ul>\n</div>","plain":"很久之前买了一个 CMCC RAX3000M 算力版[1]路由器放在工位当作内网接入隧道对端（因为工位偷电放了一台共享龙芯 3A6000，从家宽打了个 Socat SSH 出去）。这台路由器正好还有一个 USB3.0 口，这不正好，在路由器上接硬盘，当然是 Network-attached Storage，所以买了条易驱线，从工位翻了块儿没人用的硬盘出来。\n不幸的是，路由器的 SoC 是 MT7981B。而 MTK 的 USB Host，有点和 UAS 不对付。\ndmesg\n在我这里的现象是当写入到了一定量之后，USB Root bus 的状态可能损坏了，之后根本读写不了东西，读写很少数量就会 Soft reset，之后重新连上。由于硬盘是 ST3000VX000-1CU166 是 ST3000DM001 的马甲，我都担心盘坏了，结果换了三张盘都有问题，感觉不太对劲。硬盘盒也是刚换的，之前以为是电源或者硬盘盒坏了，整体换了一次，这次终于找到了罪魁祸首。\n于是只能关闭 UAS，使用 usb-storage 驱动，而不是 usb-storage-uas。\n# Disable autoload of usb-storage-uas kmod\nrm /etc/modules.d/usb-storage-uas\n\n# Manually claim the device using usb-storage\necho \"usb-storage quirks=174c:55aa:u\" > /etc/modules.d/usb-storage\n\n在线切换 Driver 的方法可以参考这个 Issue 评论。\n事实上，一共试了两个线，一个是 ORICO 的硬盘盒，一个是绿联的典中典易驱线。前者 USB ID 是 0080:a001，usb-storage 甚至无法带起来，只有 UAS 才能带起来。所以看起来只能在 x86 上稳定使用了。后者的 ID 是 174c:55aa，使用 usb-storage 驱动之后至少是可以用的，速度因为挂的是 HDD 所以也没看出来太大的区别。另外购买的一个绿联 USB 硬盘盒也是同一个芯片。所以如果在使用 MTK Chipset 挂 USB 硬盘的话，推荐还是用绿联的，至少 Less 灵一些。\nP.S. SMART 和 UAS 在有的时候也不对付。我这里看到的现象是当 Root bus 状态坏掉以后，执行任何的 SMART Self-test 也会 soft reset，dmesg 出现的内容也是类似上图中的 Transfer event for unknown stream ring slot，感觉也是和 SAT 命令的处理有关，不过这次是 Root hub 没有正确处理。\n---\n- [1] 一定要 show off 一下\n"},{"metadata":{"id":"yinchuan-marathon","lang":"zh-CN","title":"银川马拉松","tags":["走路猫"],"publish_time":"2025-05-23T19:58:09+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"银","components":[["M 249 -784C 274 -787 284 -796 287 -809L 103 -858C 98 -754 67 -570 20 -463L 28 -458C 129 -540 214 -673 249 -784Z",[0.248,0.596]],["M 339 -431L 280 -346L 21 -346L 29 -318L 417 -318C 431 -318 441 -323 444 -334C 406 -373 339 -431 339 -431Z",[0.823,0.071]],["M 253 -524L 150 -524L 150 -116C 150 -94 141 -83 88 -42L 225 80C 248 54 269 -8 228 -84L 169 -24L 286 -62L 286 -504Z",[0.034,0.752]],["M 311 -610L 251 -525L 90 -525L 98 -497L 391 -497C 405 -497 415 -502 418 -513C 379 -552 311 -610 311 -610Z",[0.849,0.085]],["M 132 -61L 224 63C 326 -46 399 -148 435 -201L 431 -209C 309 -144 185 -84 132 -61Z",[0.473,0.381]],["M 332 -790L 272 -707L 134 -707L 142 -679L 411 -679C 426 -679 436 -684 439 -695C 399 -733 332 -790 332 -790Z",[0.83,0.091]],["M 540 -748L 442 -748L 442 -99C 442 -71 435 -60 395 -39L 458 99C 488 86 523 44 511 -36L 453 6L 572 -35L 572 -729Z",[0.027,0.833]],["M 430 -47L 471 82C 564 18 644 -49 681 -82L 679 -92C 577 -71 473 -53 430 -47Z",[0.499,0.263]],["M 442 -831L 442 -715C 532 -715 572 -715 572 -715L 572 -775L 586 -775Z",[-0.19,0.136]],["M 822 -603L 523 -603L 523 -575L 822 -575Z",[0.649,0.05]],["M 822 -421L 523 -421L 523 -393L 822 -393Z",[0.872,0.017]],["M 829 -775L 530 -775L 530 -747L 829 -747Z",[0.678,0.039]],["M 644 -414L 632 -410C 667 -164 737 -15 888 79C 903 14 941 -29 989 -42L 990 -53C 831 -102 697 -232 644 -414Z",[-0.423,0.553]],["M 959 -268L 821 -365C 803 -326 755 -242 718 -197L 723 -190C 796 -206 882 -241 920 -262C 939 -257 952 -258 959 -268Z",[0.457,0.257]],["M 757 -775L 767 -775L 767 -354L 789 -354C 835 -354 897 -383 898 -392L 898 -726C 918 -731 931 -739 937 -747L 816 -839Z",[0.047,0.66]]],"bbox":{"top":-858,"bottom":99,"left":20,"right":990},"hadv":1000}],"text":"银","hadv":1000,"breakAfter":true},{"chars":[{"char":"川","components":[["M 158 -801L 158 -454C 158 -260 137 -59 22 89L 30 96C 247 -19 298 -241 300 -454L 300 -756C 326 -760 334 -770 336 -784Z",[0.104,0.808]],["M 435 -747L 435 -18L 461 -18C 516 -18 577 -48 577 -60L 577 -702C 605 -706 612 -717 614 -731Z",[0.01,0.799]],["M 730 -803L 730 91L 757 91C 812 91 875 57 875 43L 875 -757C 903 -761 910 -772 912 -786Z",[0.009,0.836]]],"bbox":{"top":-803,"bottom":96,"left":22,"right":912},"hadv":1000}],"text":"川","hadv":1000,"breakAfter":true},{"chars":[{"char":"马","components":[["M 614 -297L 539 -201L 36 -201L 44 -173L 722 -173C 736 -173 748 -178 751 -189C 699 -233 614 -297 614 -297Z",[0.879,0.053]],["M 706 -797L 126 -797L 135 -769L 706 -769Z",[0.685,0.009]],["M 438 -690L 254 -725C 250 -654 220 -458 198 -374L 236 -412C 214 -404 188 -386 173 -370L 307 -299L 355 -362L 348 -362C 365 -444 393 -621 402 -689L 393 -665C 423 -664 435 -677 438 -690Z",[0.122,0.614]],["M 868 -390L 297 -390L 297 -362L 868 -362Z",[0.839,0.017]],["M 780 -390L 791 -390C 782 -198 768 -76 740 -54C 731 -47 723 -45 706 -45C 682 -45 599 -49 542 -53L 542 -43C 597 -32 640 -15 662 8C 684 28 689 57 689 97C 771 98 814 88 852 59C 909 16 929 -98 941 -336C 963 -339 975 -346 983 -355L 857 -463Z",[0.192,0.579]],["M 626 -797L 637 -797C 632 -691 618 -510 599 -374C 669 -363 719 -368 754 -388C 768 -494 783 -654 789 -744C 810 -748 823 -757 829 -765L 684 -871Z",[0.076,0.657]]],"bbox":{"top":-871,"bottom":98,"left":36,"right":983},"hadv":1000}],"text":"马","hadv":1000,"breakAfter":true},{"chars":[{"char":"拉","components":[["M 327 -839L 151 -855L 151 -91C 151 -80 146 -74 131 -74C 108 -74 7 -80 7 -80L 7 -67C 58 -56 79 -41 95 -16C 110 8 116 44 119 95C 271 80 291 24 291 -76L 291 -810C 316 -814 326 -824 327 -839Z",[0.038,0.826]],["M 18 -375L 70 -212C 83 -216 94 -228 99 -241C 253 -333 359 -409 423 -459L 421 -469C 258 -426 83 -387 18 -375Z",[0.605,0.274]],["M 329 -706L 270 -615L 20 -615L 28 -587L 404 -587C 418 -587 429 -592 431 -603C 395 -644 329 -706 329 -706Z",[0.796,0.083]],["M 851 -107L 775 -4L 333 -4L 341 24L 960 24C 975 24 986 19 989 8C 938 -38 851 -107 851 -107Z",[0.859,0.061]],["M 842 -717L 769 -620L 421 -620L 429 -592L 945 -592C 959 -592 971 -597 973 -608C 925 -652 842 -717 842 -717Z",[0.72,0.091]],["M 466 -532L 454 -527C 500 -394 496 -223 485 -119C 560 36 796 -215 466 -532Z",[-0.086,0.637]],["M 526 -854L 519 -849C 557 -801 591 -731 599 -664C 734 -563 863 -825 526 -854Z",[-0.209,0.27]],["M 921 -494L 727 -540C 718 -380 693 -146 662 19L 686 19C 772 -136 843 -338 882 -470C 907 -471 917 -481 921 -494Z",[0.192,0.707]]],"bbox":{"top":-855,"bottom":95,"left":7,"right":989},"hadv":1000}],"text":"拉","hadv":1000,"breakAfter":true},{"chars":[{"char":"松","components":[["M 289 -584L 289 -600L 151 -600C 130 -439 85 -257 11 -132L 22 -122C 159 -242 251 -397 289 -584Z",[0.285,0.701]],["M 357 -702L 295 -600L 22 -600L 30 -572L 437 -572C 452 -572 462 -577 465 -588C 428 -632 357 -702 357 -702Z",[0.751,0.08]],["M 341 -836L 164 -853L 164 95L 192 95C 245 95 304 67 304 56L 304 -807C 332 -811 339 -821 341 -836Z",[0.004,0.849]],["M 293 -471L 284 -466C 310 -416 335 -346 338 -282C 443 -189 566 -395 293 -471Z",[-0.2,0.384]],["M 784 -396L 596 -480C 578 -363 497 -157 444 -100C 432 -90 400 -82 400 -82L 450 92C 488 80 521 30 529 -61L 456 -61L 456 -47C 560 -120 694 -282 756 -392L 724 -384C 759 -373 778 -383 784 -396Z",[0.362,0.678]],["M 690 -765L 499 -812C 489 -656 455 -485 415 -369L 426 -362C 528 -451 601 -579 650 -742C 674 -743 686 -752 690 -765Z",[0.236,0.645]],["M 430 -82L 472 67C 655 4 797 -59 873 -97L 873 -108C 689 -94 504 -84 430 -82Z",[0.689,0.147]],["M 726 -263L 716 -258C 761 -162 806 -46 817 62C 960 188 1085 -106 726 -263Z",[-0.235,0.47]],["M 826 -812L 736 -858L 725 -854C 744 -585 791 -439 904 -339C 915 -393 956 -455 987 -483L 989 -495C 894 -542 797 -647 757 -799L 763 -752C 791 -775 813 -795 826 -812Z",[-0.241,0.628]]],"bbox":{"top":-858,"bottom":188,"left":11,"right":1085},"hadv":1000}],"text":"松","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>上周末去跑了银川马拉松的半程马拉松项目！虽然成绩不是很好，不过整个出行体验还是很刺激的。</p>\n<figure class=\"raw\" style=\"max-width: 400px\">\n<img src=\"https://layered-assets.thu.fail/yc-doughnut.jpg\">\n<figcaption>赛前早餐</figcaption>\n</figure>\n<h2>赛事</h2>\n<p>首先说一说赛事本身。最终枪声成绩 1:29:40 左右，当天气温实在是太热了，状态也不太好，跑了 3km 就开始摸了。最后乖乖每个水站都喝了水，所以 <a href=\"https://www.strava.com/activities/14513890790\">Strava</a> 的配速出现了非常规律的起伏。</p>\n<p>跑到 19km 左右的时候看到马拉松那边的冠军 Contender 已经折返回来了，在 25km，掐指一算差不多，他们三分配我四分配，正好。</p>\n<p>步频还是有点过慢，162spm，目标还是至少到 170spm，需要暑期多练步频。另一方面，目前穿的飞电4C虽然是国产乞丐价位神鞋，不过感觉寿命穿了接近一年也要到头了，新买了 Vaporfly 3 下周长春试试。</p>\n<p>赛事组织感觉还是略微差强人意，集结区在赛前公告上没有明确说明，参赛包里也没有相关的参赛须知，不知道是漏装了还是就没有。结果导致从赛道另一侧走到存衣车还需要 2km，因为我要赶飞机所以背了全套行李，实在是非常自闭，感觉站到起跑线上就喘得不行了。</p>\n<p>赛道前 3km 都非常拥挤，还有如下幽默路口赛道布置：</p>\n<figure>\n<svg class=\"inline-svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 412.57 378.37\"><defs><style>.cls-1{fill:#991b1e;}.cls-2{fill:#231f20;}.cls-3{fill:#0099cd;}.cls-4{fill:#991d20;}</style></defs><path class=\"cls-4\" d=\"M202.29,71.59c0,27.26,0,54.52,0,81.79,0,7.65,0,15.29,0,22.94,0,3.22,5,3.22,5,0,0-27.26,0-54.52,0-81.79,0-7.65,0-15.29,0-22.94,0-3.22-5-3.22-5,0h0Z\"/><path class=\"cls-2\" d=\"M71.86,71.59c-.74,26.33-1.48,52.66-2.22,79-.18,6.56-.37,13.12-.55,19.69-.15,5.47-.16,11.03-1.41,16.38-1.18,5.06-3.58,9.41-7.65,12.71-4.27,3.46-9.64,5.69-14.77,7.52-12.65,4.49-26.05,6.1-39.3,7.65-1.34.16-2.5,1.04-2.5,2.5,0,1.23,1.15,2.66,2.5,2.5,12.36-1.44,24.85-2.88,36.78-6.56,10.66-3.28,22.93-8.24,27.78-19.11,2.33-5.23,3.05-10.95,3.34-16.63.34-6.47.4-12.95.59-19.42.38-13.46.76-26.91,1.13-40.37.43-15.28.86-30.57,1.29-45.85.09-3.22-4.91-3.22-5,0h0Z\"/><path class=\"cls-2\" d=\"M3.11,324.43c7.71-1.92,15.54-3.41,23.44-4.36,3.94-.47,7.89-.83,11.85-1.06s7.73-.62,11.48-.08c6.6.94,11.21,6.4,14.69,11.66,3.67,5.55,6.25,11.71,7.98,18.12,1.96,7.29,2.82,14.8,2.97,22.33.06,3.21,5.06,3.22,5,0-.27-14.32-3.06-29.07-10.64-41.42-3.7-6.04-8.6-12.2-15.46-14.71-3.78-1.38-7.94-1.25-11.89-1.1-4.21.16-8.41.45-12.59.88-9.49.98-18.9,2.61-28.15,4.92-3.12.78-1.8,5.6,1.33,4.82h0Z\"/><path class=\"cls-2\" d=\"M339.15,57.51c-8.92,19.11-11.94,40.23-12.87,61.13-.23,5.14-.25,10.31.72,15.39.92,4.8,2.93,9.22,5.98,13.04,6.01,7.53,15.27,12.08,24.29,14.9,11.01,3.44,22.62,4.4,34.06,5.33,1.35.11,2.5-1.23,2.5-2.5,0-1.44-1.15-2.39-2.5-2.5-9.57-.78-19.2-1.59-28.54-3.97-8.64-2.2-17.51-5.78-23.93-12.17-3.08-3.07-5.31-6.75-6.47-10.95-1.25-4.54-1.35-9.28-1.22-13.95.27-9.85,1.13-19.75,2.79-29.46,1.86-10.91,4.81-21.7,9.5-31.75.57-1.22.34-2.7-.9-3.42-1.08-.63-2.85-.33-3.42.9h0Z\"/><path class=\"cls-2\" d=\"M330.87,353.86c-.53-8.92-.24-17.93,1.02-26.78.63-4.42,1.47-8.81,2.53-13.15.89-3.66,1.89-7.36,3.43-10.8,1.45-3.25,3.32-6.33,5.93-8.78,2.78-2.6,6.3-4.21,9.88-5.37,8.35-2.7,17.22-4.15,25.91-5.22,10.16-1.25,20.38-1.86,30.59-2.46,3.2-.19,3.22-5.19,0-5-18.71,1.11-37.87,2.07-55.98,7.29-4.07,1.17-8.16,2.73-11.58,5.27-3.19,2.37-5.74,5.44-7.67,8.92-4.1,7.4-5.92,16.15-7.31,24.42-1.77,10.45-2.37,21.07-1.75,31.65.19,3.2,5.19,3.22,5,0h0Z\"/><path class=\"cls-4\" d=\"M208,308.04c.18,17.64.07,35.29-.36,52.93-.12,4.99-.27,9.98-.43,14.98-.11,3.22,4.89,3.21,5,0,.6-17.64.89-35.28.88-52.93,0-4.99-.03-9.99-.09-14.98-.03-3.22-5.03-3.22-5,0h0Z\"/><path class=\"cls-1\" d=\"M81.23,103.18c29.33-1.21,58.69-1.71,88.05-1.48,8.29.06,16.58.19,24.87.36,3.22.07,3.22-4.93,0-5-29.35-.63-58.71-.55-88.06.26-8.29.23-16.58.51-24.86.86-3.21.13-3.22,5.13,0,5h0Z\"/><path class=\"cls-1\" d=\"M126.37,63.58c-.37,1.97-.89,3.91-1.57,5.8-.17.48-.34.97-.55,1.42.25-.54-.04.08-.07.15-.11.25-.22.5-.34.74-.43.92-.91,1.83-1.42,2.71-.65,1.13-.3,2.79.9,3.42s2.72.31,3.42-.9c2.14-3.72,3.68-7.8,4.46-12.02.24-1.28-.35-2.76-1.75-3.08-1.23-.28-2.82.37-3.08,1.75h0Z\"/><path class=\"cls-1\" d=\"M120.51,89.63c3.22,0,3.22-5,0-5s-3.22,5,0,5h0Z\"/><path class=\"cls-1\" d=\"M139.45,65.21l-1.65,11.45c-.1.69-.12,1.3.25,1.93.3.52.9,1.01,1.49,1.15,1.18.27,2.88-.36,3.08-1.75.55-3.82,1.1-7.63,1.65-11.45.1-.69.12-1.3-.25-1.93-.3-.52-.9-1.01-1.49-1.15-1.18-.27-2.88.36-3.08,1.75h0Z\"/><path class=\"cls-1\" d=\"M136.88,92.09c3.22,0,3.22-5,0-5s-3.22,5,0,5h0Z\"/><path class=\"cls-3\" d=\"M272.18,313.73c-1.13,13.62-1.73,27.28-1.79,40.95-.01,3.22,4.99,3.22,5,0,.06-13.67.65-27.33,1.79-40.95.11-1.35-1.23-2.5-2.5-2.5-1.45,0-2.39,1.15-2.5,2.5h0Z\"/><path class=\"cls-3\" d=\"M287.46,309.69l-6.91,53.14c-.17,1.34,1.27,2.5,2.5,2.5,1.5,0,2.33-1.15,2.5-2.5l6.91-53.14c.17-1.34-1.27-2.5-2.5-2.5-1.5,0-2.33,1.15-2.5,2.5h0Z\"/><path class=\"cls-3\" d=\"M275.57,297.84c-6.35,6.57-12.11,13.7-17.21,21.28-.75,1.12-.22,2.77.9,3.42,1.23.72,2.66.23,3.42-.9,4.87-7.23,10.37-14,16.43-20.27,2.24-2.31-1.29-5.85-3.54-3.54h0Z\"/><path class=\"cls-3\" d=\"M278.73,292.94c4.77,7.9,10.1,15.44,15.92,22.61.85,1.05,2.65.89,3.54,0,1.04-1.04.85-2.48,0-3.54-5.55-6.83-10.59-14.06-15.14-21.59-1.66-2.75-5.99-.24-4.32,2.52h0Z\"/><path class=\"cls-3\" d=\"M261.2,119.86c-.36,13.11.19,26.24,1.64,39.27.15,1.34,1.04,2.5,2.5,2.5,1.24,0,2.65-1.15,2.5-2.5-1.45-13.04-2-26.16-1.64-39.27.09-3.22-4.91-3.22-5,0h0Z\"/><path class=\"cls-3\" d=\"M280.25,117.4c.19,12.57-.44,25.15-1.89,37.64-.16,1.34,1.26,2.5,2.5,2.5,1.48,0,2.34-1.15,2.5-2.5,1.45-12.49,2.08-25.06,1.89-37.64-.05-3.21-5.05-3.22-5,0h0Z\"/><path class=\"cls-3\" d=\"M270.89,101.67c-5.89,8.21-12.18,16.13-18.84,23.73-.89,1.02-1,2.54,0,3.54.91.91,2.64,1.02,3.54,0,6.94-7.93,13.48-16.19,19.62-24.75.79-1.1.19-2.78-.9-3.42-1.26-.74-2.63-.2-3.42.9h0Z\"/><path class=\"cls-3\" d=\"M271.43,107.29c5.45,3.82,10.91,7.64,16.36,11.45,1.11.77,2.78.2,3.42-.9.73-1.25.21-2.64-.9-3.42-5.45-3.82-10.91-7.64-16.36-11.45-1.11-.77-2.78-.2-3.42.9-.73,1.25-.21,2.64.9,3.42h0Z\"/><path class=\"cls-3\" d=\"M269.66,267.94c-3.15-12.5-6.98-26.57-17.49-35.02-6.12-4.92-13.58-7.04-21.1-8.8-8.53-2-17.06-3.99-25.58-5.98-13.8-3.22-28.32-5.77-41.05-12.27-5.79-2.95-11.07-6.78-15.22-11.82s-6.8-11.31-8.35-17.68c-3.31-13.6-2.32-27.81-3.34-41.67-.13-1.71-.28-3.42-.47-5.12-.22-1.92-1.95-3.06-3.76-2.16-3.79,1.88-6.93,4.81-9.17,8.39-1.72,2.73,2.61,5.25,4.32,2.52,1.81-2.88,4.34-5.08,7.38-6.59l-3.76-2.16c1.59,14.17.57,28.53,2.89,42.64,1.1,6.73,3.09,13.39,6.52,19.32s8.25,10.88,13.88,14.76c11.27,7.77,25,11.09,38.14,14.16,8.57,2,17.13,4,25.7,6.01,4.23.99,8.46,1.95,12.68,2.97,3.67.89,7.39,1.87,10.83,3.45,6.07,2.8,10.64,7.4,13.93,13.17s5.27,12.12,6.99,18.48c.42,1.57.82,3.14,1.22,4.71.79,3.12,5.61,1.8,4.82-1.33h0Z\"/><path class=\"cls-3\" d=\"M136.07,133.75c.31.04.34.04.11.01.17.02.34.05.52.08.3.05.6.1.9.15.64.12,1.28.25,1.91.4,1.18.28,2.36.61,3.51,1.01,2.27.77,4.24,1.68,6.5,3.01,1.13.66,2.79.29,3.42-.9s.31-2.71-.9-3.42c-4.92-2.89-10.32-4.64-15.97-5.34-1.3-.16-2.56,1.27-2.5,2.5.07,1.49,1.1,2.33,2.5,2.5h0Z\"/><path class=\"cls-4\" d=\"M193.24,25.61c-6.57,3.01-10.95,9.22-13.5,15.79-3.05,7.85-3.47,16.36-5.16,24.54-.92,4.44-2.21,8.79-4.49,12.73-1.61,2.79,2.7,5.31,4.32,2.52,4.06-7.01,5.3-15.01,6.52-22.89,1.16-7.45,2.44-15.17,6.8-21.51,2.04-2.97,4.75-5.36,8.03-6.86,1.23-.56,1.53-2.34.9-3.42-.74-1.26-2.19-1.46-3.42-.9h0Z\"/><path class=\"cls-4\" d=\"M161.88,73.95l3.26,7.92c.93,2.25,1.7,5.1,4.04,6.32,2.66,1.39,5.93-.28,8.43-1.35,2.35-1.02,4.58-2.26,6.68-3.73,1.1-.77,1.62-2.19.9-3.42-.64-1.09-2.31-1.67-3.42-.9-1.78,1.24-3.65,2.34-5.62,3.26-.86.4-1.74.75-2.64,1.07-.53.19-1.06.34-1.59.52-.08.03-.3.11-.35.12-.14.04-.35-.18-.08,0,.21.14.06.06-.05-.06-.49-.55.09.18-.14-.19-.11-.18-.22-.37-.32-.56-.03-.05-.29-.62-.2-.4-.33-.74-.85-2.07-1.25-3.03l-2.83-6.89c-.51-1.25-1.66-2.13-3.08-1.75-1.18.32-2.26,1.82-1.75,3.08h0Z\"/><path class=\"cls-4\" d=\"M207.86,23.7c5.47-.27,10.92-.74,16.35-1.4,1.29-.16,2.57-1.04,2.5-2.5-.05-1.22-1.11-2.67-2.5-2.5-5.43.66-10.89,1.12-16.35,1.4-1.3.06-2.56,1.1-2.5,2.5.06,1.3,1.1,2.57,2.5,2.5h0Z\"/><path class=\"cls-4\" d=\"M209.9,4.29c.89,14.44,1.48,28.9,1.77,43.37.06,3.21,5.06,3.22,5,0-.29-14.47-.88-28.93-1.77-43.37-.2-3.2-5.2-3.22-5,0h0Z\"/><path class=\"cls-4\" d=\"M210.59,24.21l-7.18,5.91c-.47.38-.73,1.19-.73,1.77,0,.61.27,1.35.73,1.77s1.1.76,1.77.73,1.23-.29,1.77-.73l7.18-5.91c.47-.38.73-1.19.73-1.77,0-.61-.27-1.35-.73-1.77s-1.1-.76-1.77-.73-1.23.29-1.77.73h0Z\"/><path class=\"cls-4\" d=\"M212.35,29.47c.88.31,1.76.65,2.62,1.01l-.6-.25c1.31.55,2.6,1.17,3.85,1.84.59.31,1.28.43,1.93.25.58-.16,1.21-.61,1.49-1.15.61-1.16.33-2.76-.9-3.42-2.27-1.21-4.64-2.25-7.07-3.1-.59-.21-1.4-.05-1.93.25s-1.01.9-1.15,1.49c-.32,1.4.42,2.61,1.75,3.08h0Z\"/><path class=\"cls-4\" d=\"M226.63,5.35c2.57,2.95,5.75,5.42,9.24,7.19,1.17.59,2.76.35,3.42-.9.6-1.14.35-2.79-.9-3.42-.82-.41-1.62-.86-2.39-1.35-.38-.24-.75-.48-1.11-.74-.18-.13-.36-.26-.54-.39-.15-.11-.8-.64-.2-.15-1.41-1.18-2.76-2.39-3.98-3.78-.86-.99-2.67-.95-3.54,0-.97,1.05-.92,2.48,0,3.54h0Z\"/><path class=\"cls-4\" d=\"M242.56,1.82c-.35,1-.72,1.99-1.1,2.97-.19.49-.39.98-.59,1.47-.03.08-.39.94-.18.45-.1.24-.21.49-.31.73-.86,1.97-1.78,3.91-2.77,5.82-.6,1.16-.34,2.77.9,3.42,1.15.61,2.78.34,3.42-.9,2.11-4.07,3.94-8.3,5.46-12.63.43-1.24-.49-2.79-1.75-3.08-1.4-.32-2.61.42-3.08,1.75h0Z\"/><path class=\"cls-4\" d=\"M231.57,21.99c3.95-.39,7.91-.54,11.88-.45,1.31.03,2.56-1.17,2.5-2.5s-1.1-2.47-2.5-2.5c-3.97-.09-7.93.06-11.88.45-1.3.13-2.56,1.06-2.5,2.5.06,1.24,1.11,2.64,2.5,2.5h0Z\"/><path class=\"cls-4\" d=\"M236.75,31.25l3.48-1.02c.61-.18,1.17-.6,1.49-1.15.18-.29.28-.6.3-.93.07-.33.06-.66-.04-1-.2-.6-.57-1.19-1.15-1.49s-1.27-.44-1.93-.25l-3.48,1.02c-.61.18-1.17.6-1.49,1.15-.18.29-.28.6-.3.93-.07.33-.06.66.04,1,.2.6.57,1.19,1.15,1.49s1.27.44,1.93.25h0Z\"/><path class=\"cls-4\" d=\"M228.11,41.34c7.02.09,14.05.07,21.07-.08,3.21-.07,3.22-5.07,0-5-7.02.15-14.05.18-21.07.08-3.22-.04-3.22,4.96,0,5h0Z\"/><path class=\"cls-4\" d=\"M258.38,21.11c4.09,0,8.18,0,12.27,0,1.31,0,2.56-1.15,2.5-2.5s-1.1-2.5-2.5-2.5c-4.09,0-8.18,0-12.27,0-1.31,0-2.56,1.15-2.5,2.5s1.1,2.5,2.5,2.5h0Z\"/><path class=\"cls-4\" d=\"M262.01,6.75l.54,41.11c.04,3.21,5.04,3.22,5,0l-.54-41.11c-.04-3.21-5.04-3.22-5,0h0Z\"/><path class=\"cls-4\" d=\"M259.93,20.43c-1.58,3.61-3.43,7.1-5.55,10.42-.7,1.11-.27,2.81.9,3.42,1.24.65,2.67.28,3.42-.9,2.11-3.33,3.97-6.81,5.55-10.42.28-.64.45-1.23.25-1.93-.16-.58-.61-1.21-1.15-1.49-1.08-.57-2.86-.38-3.42.9h0Z\"/><path class=\"cls-4\" d=\"M266.35,26.05c2.46,1.77,5.05,3.35,7.74,4.75,1.16.6,2.77.34,3.42-.9.61-1.15.34-2.78-.9-3.42-2.69-1.39-5.28-2.98-7.74-4.75-.5-.36-1.36-.41-1.93-.25s-1.21.61-1.49,1.15c-.31.58-.46,1.28-.25,1.93s.59,1.1,1.15,1.49h0Z\"/><path class=\"cls-4\" d=\"M277.22,16.41c.67-.15,1.34-.28,2.01-.37l-.66.09c1.72-.23,3.45-.26,5.17-.09.6.06,1.36-.32,1.77-.73.43-.43.76-1.15.73-1.77s-.24-1.32-.73-1.77c-.52-.47-1.07-.66-1.77-.73-2.62-.26-5.28-.04-7.85.55-1.28.3-2.15,1.83-1.75,3.08.43,1.33,1.71,2.06,3.08,1.75h0Z\"/><path class=\"cls-4\" d=\"M267.79,33.37c8.89-1.14,17.85-1.45,26.79-.93,3.21.19,3.2-4.81,0-5-8.94-.52-17.91-.21-26.79.93-1.34.17-2.5,1.03-2.5,2.5,0,1.22,1.15,2.67,2.5,2.5h0Z\"/><path class=\"cls-4\" d=\"M277.09,19.22c.14,8.55.74,17.09,1.8,25.58.17,1.34,1.03,2.5,2.5,2.5,1.22,0,2.67-1.15,2.5-2.5-1.06-8.49-1.66-17.03-1.8-25.58-.05-3.21-5.05-3.22-5,0h0Z\"/><path class=\"cls-4\" d=\"M237.58,53.8c.61,14.68-3.22,29.35-10.86,41.9-2.15,3.53-4.58,6.86-7.3,9.97-.89,1.02-1,2.54,0,3.54.91.91,2.64,1.02,3.54,0,10.37-11.85,16.98-26.62,19.03-42.22.58-4.37.78-8.78.6-13.19-.13-3.21-5.13-3.22-5,0h0Z\"/><path class=\"cls-4\" d=\"M218.14,97.52c-.98,1.96-1.8,4.01-2.39,6.12-.31,1.12-.79,2.47-.5,3.63.41,1.64,1.92,2.12,3.3,2.67,3.94,1.59,8.01,2.84,12.15,3.75,1.27.28,2.76-.38,3.08-1.75.29-1.26-.38-2.77-1.75-3.08-2.3-.51-4.58-1.11-6.83-1.83-1.1-.35-2.2-.73-3.28-1.13-.56-.21-1.12-.42-1.68-.64-.24-.1-.48-.19-.72-.29-.16-.06-.32-.13-.48-.2.16.05.3.13.43.23l.64,1.1c-.07.85-.06,1.03.03.53.03-.16.07-.32.11-.48.07-.32.15-.64.24-.96.17-.64.36-1.27.57-1.89.49-1.44.72-1.96,1.37-3.27.58-1.17.35-2.76-.9-3.42-1.13-.6-2.8-.35-3.42.9h0Z\"/></svg>\n</figure>\n<p>结果看到有超人一跃而起从栅栏上跳过去了，看的我目瞪口呆。</p>\n<p>其他倒没有什么特别可以批评的地方，水站充足，15km 以后也有足够密度的医疗点，半程的话也不会看到收容车，所以必要的这些东西还是挺齐全的，毕竟是田协 A 类，如果这些都没有田协是要吃锅的。不过确实有很多可以做的更好的地方，比如上述的赛道布置和物料准备，只开一枪导致赛道拥挤等等，还是希望能把更多心思用到这上，而不是往参赛包里塞东西，搞马博会，参赛包里的红酒最后还是没办法带回北京，送给在终点多等了我十分钟的快车师傅。说来也奇怪，完赛包里就只有一个毛巾。</p>\n<h2>行程</h2>\n<p>这次行程搞得比较极限，7:30 发枪，订的回程机票在 10:35，银川-石家庄正定，然后再坐高铁回北京。基本就是必须跑进 1:30 要不然就赶不上飞机了，还是挺刺激的。本来打算是如果感觉跑不进 130 就提前退赛了，最后正好。完赛区放了一堆共享电动车，还是挺 Considerate 的，不过美团的电动车必须要到 P 点，我骑着车到了快车等待的地方结果不让锁车，都没有强行锁车交调度费的选项，那个按钮是“学习锁车规则”，太幽默了。最后正好路边有另一个路人要骑车回终点，直接把车交给他了，最后在高速上远程锁车的，锁车的时候还看不到车的定位，还挺担心有人正在骑，美团这个交互设计实在是太幽默了。</p>\n<p>第一次认识到春秋是不能在线值机的，也没办法使用电子登机牌，所以做在出租上的时候真的感觉赶不上了。不过可能是快车师傅收到了获赠红酒的压力，一路都是顶着 120kmph 的限速开的，然后春秋截止值机也比较晚，可能也是考虑了这件事情。</p>\n<p>石家庄正定机场的交通非常方便，机场到高铁站有免费摆渡车，车次很频繁，去程回程都是上了车三分钟内就发车了。以后可以多考虑从正定起飞的飞机。</p>\n<h2>Hello 长春!</h2>\n<p>下周还有一次长春的比赛，之后 25 上半年的马拉松赛季就正式结束了。很遗憾，即使名叫长春，还是无法抵挡夏天门口的高温，所以也不特别追求成绩了，而是作为一次出去玩的机会。这周在银川实在是太赶了，做了两天 MPC 作业，当地的吃的什么都没吃到，结果赛后在石家庄机场门口吃驴肉火烧，着实有点抽象。在长春有一个下午的时间去四处转转，希望能有更多的照片贴在博客里。</p>\n","plain":"上周末去跑了银川马拉松的半程马拉松项目！虽然成绩不是很好，不过整个出行体验还是很刺激的。\n\n赛事\n首先说一说赛事本身。最终枪声成绩 1:29:40 左右，当天气温实在是太热了，状态也不太好，跑了 3km 就开始摸了。最后乖乖每个水站都喝了水，所以 Strava 的配速出现了非常规律的起伏。\n跑到 19km 左右的时候看到马拉松那边的冠军 Contender 已经折返回来了，在 25km，掐指一算差不多，他们三分配我四分配，正好。\n步频还是有点过慢，162spm，目标还是至少到 170spm，需要暑期多练步频。另一方面，目前穿的飞电4C虽然是国产乞丐价位神鞋，不过感觉寿命穿了接近一年也要到头了，新买了 Vaporfly 3 下周长春试试。\n赛事组织感觉还是略微差强人意，集结区在赛前公告上没有明确说明，参赛包里也没有相关的参赛须知，不知道是漏装了还是就没有。结果导致从赛道另一侧走到存衣车还需要 2km，因为我要赶飞机所以背了全套行李，实在是非常自闭，感觉站到起跑线上就喘得不行了。\n赛道前 3km 都非常拥挤，还有如下幽默路口赛道布置：\n结果看到有超人一跃而起从栅栏上跳过去了，看的我目瞪口呆。\n其他倒没有什么特别可以批评的地方，水站充足，15km 以后也有足够密度的医疗点，半程的话也不会看到收容车，所以必要的这些东西还是挺齐全的，毕竟是田协 A 类，如果这些都没有田协是要吃锅的。不过确实有很多可以做的更好的地方，比如上述的赛道布置和物料准备，只开一枪导致赛道拥挤等等，还是希望能把更多心思用到这上，而不是往参赛包里塞东西，搞马博会，参赛包里的红酒最后还是没办法带回北京，送给在终点多等了我十分钟的快车师傅。说来也奇怪，完赛包里就只有一个毛巾。\n\n行程\n这次行程搞得比较极限，7:30 发枪，订的回程机票在 10:35，银川-石家庄正定，然后再坐高铁回北京。基本就是必须跑进 1:30 要不然就赶不上飞机了，还是挺刺激的。本来打算是如果感觉跑不进 130 就提前退赛了，最后正好。完赛区放了一堆共享电动车，还是挺 Considerate 的，不过美团的电动车必须要到 P 点，我骑着车到了快车等待的地方结果不让锁车，都没有强行锁车交调度费的选项，那个按钮是“学习锁车规则”，太幽默了。最后正好路边有另一个路人要骑车回终点，直接把车交给他了，最后在高速上远程锁车的，锁车的时候还看不到车的定位，还挺担心有人正在骑，美团这个交互设计实在是太幽默了。\n第一次认识到春秋是不能在线值机的，也没办法使用电子登机牌，所以做在出租上的时候真的感觉赶不上了。不过可能是快车师傅收到了获赠红酒的压力，一路都是顶着 120kmph 的限速开的，然后春秋截止值机也比较晚，可能也是考虑了这件事情。\n石家庄正定机场的交通非常方便，机场到高铁站有免费摆渡车，车次很频繁，去程回程都是上了车三分钟内就发车了。以后可以多考虑从正定起飞的飞机。\n\nHello 长春!\n下周还有一次长春的比赛，之后 25 上半年的马拉松赛季就正式结束了。很遗憾，即使名叫长春，还是无法抵挡夏天门口的高温，所以也不特别追求成绩了，而是作为一次出去玩的机会。这周在银川实在是太赶了，做了两天 MPC 作业，当地的吃的什么都没吃到，结果赛后在石家庄机场门口吃驴肉火烧，着实有点抽象。在长春有一个下午的时间去四处转转，希望能有更多的照片贴在博客里。\n"},{"metadata":{"id":"non-mca-seqcst-fences","lang":"zh-CN","title":"C++ SeqCst 在 Non-MCA 系统上的实现","tags":["微架构","Fences"],"publish_time":"2025-05-22T09:08:25+08:00","update_time":"2025-08-20T23:49:38+08:00","title_outline":{"groups":[{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708}],"text":"C","hadv":708,"breakAfter":false},{"chars":[{"char":"+","components":[["M 579 -340L 579 -395L 36 -395L 36 -340Z",[0.871,0.002]],["M 279 -87L 338 -87L 338 -642L 279 -642Z",[-0.006,0.909]]],"bbox":{"top":-642,"bottom":-87,"left":36,"right":579},"hadv":615}],"text":"+","hadv":615,"breakAfter":true},{"chars":[{"char":"+","components":[["M 579 -340L 579 -395L 36 -395L 36 -340Z",[0.871,0.002]],["M 279 -87L 338 -87L 338 -642L 279 -642Z",[-0.006,0.909]]],"bbox":{"top":-642,"bottom":-87,"left":36,"right":579},"hadv":615}],"text":"+","hadv":615,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"q","components":[["M 261 17C 335 17 400 -16 448 -84L 455 -84L 440 -95C 408 -66 380 -54 343 -54C 264 -54 208 -109 208 -270C 208 -434 264 -494 342 -494C 377 -494 409 -482 442 -450L 460 -461L 455 -465C 416 -530 356 -563 289 -563C 146 -563 35 -450 35 -267C 35 -86 133 17 261 17Z",[0.019,0.474]],["M 344 259L 646 259L 646 230L 544 219L 444 219L 344 230Z",[0.875,0.002]],["M 420 259L 586 259C 583 180 582 101 582 22L 582 -398L 586 -552L 571 -561L 420 -478L 420 -77L 424 -63L 424 22C 424 101 423 180 420 259Z",[0.007,0.803]]],"bbox":{"top":-563,"bottom":259,"left":35,"right":646},"hadv":657},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"SeqCst","hadv":3481,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"Non","hadv":2159,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761}],"text":"MCA","hadv":2483,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"系","components":[["M 399 -140L 238 -234C 201 -148 118 -26 28 51L 35 61C 167 20 285 -55 360 -127C 384 -124 393 -130 399 -140Z",[0.482,0.407]],["M 905 -726L 771 -862C 610 -806 296 -737 56 -704L 58 -689C 314 -686 632 -704 829 -730C 866 -715 892 -716 905 -726Z",[0.814,0.101]],["M 840 -549L 694 -660C 601 -565 328 -405 151 -363C 132 -357 96 -353 96 -353L 163 -205C 191 -217 212 -257 218 -334L 165 -334L 164 -325C 385 -371 693 -478 808 -551L 774 -548C 808 -530 831 -538 840 -549Z",[0.766,0.365]],["M 137 -344L 179 -225C 452 -270 665 -313 791 -345L 790 -360C 513 -350 249 -343 137 -344Z",[0.835,0.083]],["M 586 -660L 429 -747C 389 -701 266 -614 179 -595C 166 -591 140 -587 140 -587L 206 -440C 235 -453 255 -498 259 -572L 199 -572L 199 -562C 318 -576 488 -620 563 -657L 527 -655C 560 -641 580 -648 586 -660Z",[0.626,0.328]],["M 178 -572L 214 -452C 398 -492 548 -533 632 -558L 632 -572C 442 -569 256 -569 178 -572Z",[0.84,0.078]],["M 571 -48L 571 -323L 421 -323L 421 -51C 421 -42 417 -35 404 -35C 384 -35 304 -40 304 -40L 304 -29C 352 -21 368 -5 380 12C 393 30 396 60 398 101C 549 91 571 40 571 -48Z",[0.078,0.581]],["M 614 -222L 606 -215C 681 -153 758 -55 789 36C 938 122 1025 -176 614 -222Z",[-0.388,0.385]],["M 639 -459L 631 -452C 703 -395 781 -301 813 -217C 955 -140 1031 -422 639 -459Z",[-0.359,0.342]]],"bbox":{"top":-862,"bottom":122,"left":28,"right":1031},"hadv":1000}],"text":"系","hadv":1000,"breakAfter":true},{"chars":[{"char":"统","components":[["M 342 -783L 176 -848C 160 -764 97 -610 52 -564C 42 -557 17 -550 17 -550L 77 -406C 106 -419 127 -463 131 -534L 67 -534L 68 -522C 151 -576 262 -693 316 -778L 284 -770C 319 -760 337 -770 342 -783Z",[0.363,0.63]],["M 34 -108L 92 57C 105 53 116 42 121 29C 261 -53 353 -121 414 -170L 413 -179C 266 -144 104 -116 34 -108Z",[0.585,0.245]],["M 438 -577L 287 -666C 255 -564 147 -382 74 -325C 63 -317 35 -311 35 -311L 95 -166C 124 -179 145 -222 150 -293L 88 -293L 88 -281C 200 -347 347 -487 410 -577L 378 -571C 411 -557 431 -565 438 -577Z",[0.465,0.627]],["M 45 -543L 88 -422C 188 -464 276 -510 318 -534L 318 -546C 207 -543 94 -542 45 -543Z",[0.468,0.101]],["M 58 -305L 101 -174C 236 -229 347 -286 404 -318L 403 -329C 261 -316 117 -307 58 -305Z",[0.641,0.156]],["M 626 -335L 626 -451L 478 -451L 478 -334C 477 -198 443 -30 238 86L 242 94C 588 5 625 -191 626 -335Z",[0.272,0.64]],["M 868 -770L 801 -680L 359 -680L 367 -652L 959 -652C 974 -652 985 -657 988 -668C 943 -709 868 -770 868 -770Z",[0.769,0.071]],["M 733 -607L 570 -666C 546 -614 469 -514 412 -488C 401 -483 374 -479 374 -479L 434 -325C 466 -338 488 -388 493 -463L 430 -463L 430 -453C 520 -481 647 -546 710 -600L 675 -594C 710 -584 728 -594 733 -607Z",[0.483,0.477]],["M 398 -471L 449 -346C 643 -391 796 -436 881 -464L 880 -478C 677 -472 482 -470 398 -471Z",[0.785,0.083]],["M 540 -853L 533 -848C 563 -810 596 -753 606 -697C 735 -613 850 -852 540 -853Z",[-0.261,0.227]],["M 799 -461L 659 -461L 659 -49C 659 36 673 63 767 63L 823 63C 940 63 981 36 981 -15C 981 -40 975 -57 945 -72L 941 -207L 931 -207C 913 -150 895 -97 884 -80C 878 -70 873 -68 865 -67C 858 -67 850 -67 841 -67L 815 -67C 801 -67 799 -72 799 -85L 799 -424C 799 -433 799 -449 799 -461Z",[-0.152,0.506]],["M 746 -579L 737 -573C 783 -514 828 -429 841 -352C 966 -260 1073 -508 746 -579Z",[-0.227,0.348]]],"bbox":{"top":-853,"bottom":94,"left":17,"right":1073},"hadv":1000}],"text":"统","hadv":1000,"breakAfter":true},{"chars":[{"char":"上","components":[["M 25 13L 33 41L 947 41C 962 41 974 36 977 25C 920 -23 826 -94 826 -94L 742 13Z",[0.911,0.043]],["M 386 -839L 386 29L 546 29L 546 -792C 574 -796 581 -806 583 -821Z",[0.004,0.811]],["M 477 -453L 477 -425L 876 -425C 891 -425 902 -430 905 -441C 850 -489 758 -559 758 -559L 676 -453Z",[0.76,0.075]]],"bbox":{"top":-839,"bottom":41,"left":25,"right":977},"hadv":1000}],"text":"上","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"实","components":[["M 170 -743L 160 -743C 161 -704 116 -667 84 -652C 42 -634 11 -597 24 -546C 40 -492 106 -473 145 -496C 199 -528 224 -619 170 -743Z",[0.171,0.314]],["M 662 -617L 466 -634C 465 -297 489 -83 24 82L 30 95C 625 -23 616 -247 626 -589C 649 -593 660 -602 662 -617Z",[0.325,0.62]],["M 818 -365L 741 -257L 56 -257L 64 -229L 927 -229C 942 -229 954 -234 957 -245C 906 -293 818 -365 818 -365Z",[0.899,0.048]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 170 -453L 164 -448C 202 -410 240 -349 250 -290C 384 -206 491 -461 170 -453Z",[-0.27,0.26]],["M 244 -618L 237 -612C 271 -578 307 -520 316 -467C 439 -390 540 -622 244 -618Z",[-0.187,0.226]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 512 -188L 509 -178C 648 -96 756 17 795 79C 937 157 1059 -145 512 -188Z",[-0.529,0.36]],["M 780 -680L 791 -680C 790 -638 784 -567 777 -520L 783 -514C 834 -541 899 -587 937 -622C 958 -623 968 -626 976 -635L 851 -752Z",[-0.442,0.364]]],"bbox":{"top":-871,"bottom":157,"left":11,"right":1059},"hadv":1000}],"text":"实","hadv":1000,"breakAfter":true},{"chars":[{"char":"现","components":[["M 9 -125L 81 34C 94 29 104 18 108 4C 252 -91 348 -167 406 -218L 404 -227C 242 -181 75 -139 9 -125Z",[0.589,0.284]],["M 303 -838L 238 -749L 16 -749L 24 -721L 391 -721C 405 -721 416 -726 419 -737C 376 -778 303 -838 303 -838Z",[0.608,0.079]],["M 325 -541L 278 -460L 28 -460L 36 -432L 381 -432C 395 -432 404 -437 407 -448C 379 -484 325 -541 325 -541Z",[0.72,0.084]],["M 269 -746L 130 -746L 130 -90L 269 -130Z",[0.006,0.782]],["M 773 -661L 601 -676C 600 -310 627 -86 244 77L 252 91C 745 -36 729 -265 737 -633C 760 -636 770 -646 773 -661Z",[0.261,0.692]],["M 423 -827L 423 -224L 447 -224C 514 -224 554 -248 554 -257L 554 -746L 787 -746L 787 -236L 811 -236C 881 -236 925 -262 925 -269L 925 -735C 948 -739 959 -747 966 -756L 848 -848L 783 -774L 565 -774Z",[0.092,0.019]],["M 804 -326L 655 -339L 655 -30C 655 46 670 69 758 69L 822 69C 940 69 982 42 982 -5C 982 -27 977 -41 949 -54L 946 -188L 935 -188C 917 -129 901 -77 892 -60C 886 -50 882 -48 872 -47C 865 -47 852 -47 836 -47L 793 -47C 776 -47 773 -51 773 -63L 773 -301C 793 -304 802 -313 804 -326Z",[-0.198,0.323]]],"bbox":{"top":-848,"bottom":91,"left":9,"right":982},"hadv":1000}],"text":"现","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p><a href=\"seqcst-fences\"><del>昨天</del> <del>前天</del> 上周的文章</a>最后的命题伪证了：</p>\n<blockquote>\n<p>这是一个错误结论：SeqCst ld/st/AMO 存在全序 + 所有 SeqCst 操作等待/阻拦前后所有类型其他访存 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext></mrow><annotation encoding=\"application/x-tex\">\\implies</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.549em;vertical-align:-0.024em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span></span></span> C++11 SeqCst Semantics</p>\n</blockquote>\n<p>问题是 SeqCst ld/st/AMO 的全序可能和 Fence 不兼容，所以如何在 Non-MCA 系统上实现 <code>std::memory_order_seq_cst</code> 还是一个非常 Nontrivial 的事情，需要把 SeqCst ld/st/AMO 的实现方法也考虑进来。本文在上篇文章提出的设计的基础上细化一下 SeqCst ld/st/AMO 的实现，并且给出一个比较详细的证明，说明这一设计符合 C++11 SeqCst Semantics。这显然不是唯一的设计，也不是所有系统下都最自然的设计，不过可以认为是一个 MCA 系统<a href=\"mca\">不再等待所有 ProbeAck</a> 之后得到的 Non-MCA 系统一个比较直观的设计。</p>\n<details>\n<summary>各种序和符号的定义</summary>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span>: Coherence order，和 C++ 标准中的 Modification order 基本同义。</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>f</mi></mrow><annotation encoding=\"application/x-tex\">rf</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span></span></span></span>: Read-from，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to_{rf} R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 表示 R 读到了 W 的值，可以理解为 “W 早于 R”。</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>f</mi><mi>r</mi></mrow><annotation encoding=\"application/x-tex\">fr</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span></span></span></span>: From-read，部分文献称为 Read-before (<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">rb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">b</span></span></span></span>)，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">R \\to_{fr} W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 表示 R 读到了 W 在 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span> 序之前某个操作写入的值，可以理解为“R 早于 W”</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>w</mi></mrow><annotation encoding=\"application/x-tex\">sw</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span></span></span></span>: Synchronize-with，在本文中狭义解释为一个 Release 操作写入的值被一个 Acquire 操作读到。标准库中有别的 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>w</mi></mrow><annotation encoding=\"application/x-tex\">sw</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span></span></span></span> 操作，这里不做讨论。</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">cob</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span></span></span></span>: Coherence-ordered before</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi><mo separator=\"true\">,</mo><mi>r</mi><mi>a</mi><mo separator=\"true\">,</mo><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">bwcb, ra, ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">a</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> 都是本文中定义的关系，分别指 Base wall-clock before, read-after 和 partial preserved SC</li>\n</ul>\n<p>分号 (<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo separator=\"true\">;</mo></mrow><annotation encoding=\"application/x-tex\">;</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mpunct\">;</span></span></span></span>) 表示关系连接，即：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>a</mi><mo separator=\"true\">;</mo><mi>b</mi><mo>:</mo><mo>=</mo><mo stretchy=\"false\">{</mo><mo stretchy=\"false\">(</mo><mi>X</mi><mo separator=\"true\">,</mo><mi>Y</mi><mo stretchy=\"false\">)</mo><mo>∈</mo><mi>d</mi><mi>o</mi><mi>m</mi><mo stretchy=\"false\">(</mo><mi>a</mi><mo stretchy=\"false\">)</mo><mo>×</mo><mi>c</mi><mi>o</mi><mi>d</mi><mi>o</mi><mi>m</mi><mo stretchy=\"false\">(</mo><mi>b</mi><mo stretchy=\"false\">)</mo><mo>∣</mo><mi>e</mi><mi>x</mi><mi>i</mi><mi>s</mi><mi>t</mi><mi>s</mi><mi>Z</mi><mo separator=\"true\">,</mo><mi>X</mi><mi>a</mi><mi>Z</mi><mo>∧</mo><mi>Z</mi><mi>b</mi><mi>Y</mi><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">\na ; b := \\{ (X, Y) \\in dom(a) \\times codom(b) \\mid exists Z, XaZ \\land ZbY \\}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">:=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.22222em;\">Y</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">m</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">m</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">Z</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">Z</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∧</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">Z</span><span class=\"mord mathnormal\" style=\"margin-right:0.22222em;\">bY</span><span class=\"mclose\">}</span></span></span></span></span></p>\n<p>中括号 (<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">[</mo><mi>S</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">[S]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span><span class=\"mclose\">]</span></span></span></span>) 表示 S 类型的操作上的 Identity 关系，即：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo stretchy=\"false\">[</mo><mi>S</mi><mo stretchy=\"false\">]</mo><mo>:</mo><mo>=</mo><mo stretchy=\"false\">{</mo><mo stretchy=\"false\">(</mo><mi>X</mi><mo separator=\"true\">,</mo><mi>X</mi><mo stretchy=\"false\">)</mo><mo>∣</mo><mi>X</mi><mo>∈</mo><mi>S</mi><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">\n[S] := \\{ (X, X) \\mid X \\in S \\}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">:=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7224em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span><span class=\"mclose\">}</span></span></span></span></span></p>\n<p>中括号可以用于固定一个序的两端，例如 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">[F]; sb; [F]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">]</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">]</span></span></span></span> 表示 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">sb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span></span></span></span> 关系中两端都是 Fence (<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>F</mi></mrow><annotation encoding=\"application/x-tex\">F</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span></span></span></span>) 的子关系。</p>\n</details>\n<h2>The Hardware</h2>\n<p>实现很重要的一个属性是希望尽量在核心“局部”可以实现这个排序，不需要通过总线上或者其他信道上和别的核心进行访存之外的通信。很遗憾，SeqCst 的语义并不能完全在局部完成，需要的硬件功能集合包括：</p>\n<ol>\n<li>所有 SeqCst 操作会等待同一线程 sequenced-before 的所有操作完成，然后才开始本操作。等待本操作完成之后，才开始 sequenced-after 的其他操作。这里“完成”指的是全局可见之后，在硬件实现上需要核心发出的写操作对应的回应蕴含它已经全局可见了。</li>\n</ol>\n<ul>\n<li>Acquire / Release 操作也要进行类似的等待。不过 Acquire 只阻止 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>→</mo><mo>∗</mo></mrow><annotation encoding=\"application/x-tex\">R \\rightarrow *</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4653em;\"></span><span class=\"mord\">∗</span></span></span></span>，Release 只阻止 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>∗</mo><mo>→</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">* \\rightarrow W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4653em;\"></span><span class=\"mord\">∗</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span>。</li>\n<li>此外，Acquire / Release AMO 弱于 Relaxed AMO + Acquire / Release Fence，原因是 Acquire / Release AMO 只控制其绑定的 AMO 操作和其他访存操作的顺序。</li>\n</ul>\n<!-- - 额外的，需要 SeqCst st/AMO 操作的全局可见顺序一致。<sup>[2]</sup> -->\n<ol start=\"2\">\n<li>额外的，所有 SeqCst 操作结束时必须保证，该操作读取到的值必须全局可见。（对于 Fence，本线程之前所有 Load / AMO 读到的值都全局可见）。<sup>[2]</sup></li>\n</ol>\n<p>可以画一张图，横轴方向 Wall clock，每个线程一条时间轴，Fence 标记为一个点，其他访存标记为核心视角开始执行到收到回应结束执行的时刻。</p>\n<figure>\n<svg class=\"inline-svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 537 132\"><path d=\"M58.04099965,24.2125931c.01831612,2.39700308.24411632,4.78380396.65564577,7.14554487.37011111,2.12404375.802947,4.46936069,1.78459699,6.40858703,1.13087712,2.234021,3.2974553,2.67184596,5.59620868,2.59166984,2.49481719-.08701445,4.98941147-.18098224,7.48410535-.27147286,9.72933688-.35291455,19.45867378-.70582851,29.1880107-1.05874224,5.57150059-.2020959,11.14300119-.40419172,16.71450179-.60628755,3.20801233-.11636468,3.22339567-5.11692268,0-5-17.95707908.65135966-35.92195827,1.52692424-53.88555819,1.95460085-.1172196.00279076-.62255603.06974832-.76787875.00563999-.18572709-.08193249.05585847.06634112.07680309.09396291-.14822435-.19547841-.23404742-.72871135-.2934682-.92370633-.33900682-1.11248345-.62374045-2.24192328-.85815398-3.38093255-.47263724-2.29653209-.67690801-4.61563242-.69481325-6.95886395-.0245744-3.21601439-5.02463133-3.22346514-5,0h0Z\"/><path d=\"M123.54917305,25.71627823c-1.03128451,3.18371748-1.43214314,6.61611863-1.13397013,9.95022993.11617157,1.29900736,1.06661474,2.5642015,2.5,2.5,1.25466478-.05619659,2.62474984-1.10507208,2.5-2.5-.1372401-1.53459148-.12966177-3.07764058.03685816-4.60975581.00919655-.0866428.01904614-.17321213.02954876-.25970799.03516862-.27940424.02814408-.23063387-.02107363.1463111-.02518379-.1468121.05613941-.37385317.0799431-.51660737.06210037-.37242491.1332162-.74328349.21341405-1.11223578.16666532-.76674812.37491114-1.52267809.61667486-2.26903602.40320327-1.24474409-.46997527-2.7846365-1.74609855-3.07529661-1.37044825-.31214433-2.64358392.41334193-3.07529661,1.74609855h0Z\"/><path d=\"M132.54271059,33.12999448c19.45059166-.52346332,38.9106795-.64325382,58.36624153-.35928521,3.21859898.04697788,3.21987364-4.95300351,0-5-19.45556197-.28396861-38.91564981-.16417811-58.36624153.35928521-3.211205.08642143-3.22399942,5.08676576,0,5h0Z\"/><path d=\"M202.17527059,30.90478704c-.07707293-.0342412-.15037812-.07936919-.22713261-.11299686-.37501539-.16430173.22735883.09859745.22502639.190253.00068544-.02693521-.15216473-.15521727-.17268281-.17177439-.14642545-.11815841.34264127.54735148.18612641.23328872-.02844044-.05706858-.06340127-.11661302-.09684073-.17095667-.19208507-.31216422.15271216.48001825.11782718.2765627-.03134566-.18281364-.09666267-.35623136-.12259018-.54272769l.08930242.66459903c-.02492457-.24291031-.02382671-.47879825.00239722-.72155868l-.08930242.66459903c.01972507-.1375132.04393138-.27322457.08060469-.40738305.01821052-.06675021.03883784-.132745.06188195-.19798437.08903728-.23438796.04495418-.13067792-.1322493.31113011.0544322-.07724425.10544839-.18605154.15208233-.26895388.18978369-.33738323-.47888314.51619442-.06572183.10804564.06064287-.05914522.12367878-.11561899.18910772-.16942129-.34425613.2568385-.41131357.31364036-.20117232.17040557.10203269-.0534268.24032031-.11085528.32704564-.1812248-.40878603.16388143-.49258831.20017053-.25140683.1088673.07887458-.02771754.15861226-.0526781.23921302-.07488166.16288295-.04502193.32781871-.0758883.49460006-.10204446l-.66459903.08930242c.42963808-.05386757.85316021-.04884677,1.28241885.00654346l-.66459903-.08930242c.25701639.04003512.51045095.09280927.75942718.16902743.12340189.03777656.24269045.08964704.36580302.12712263-.69005776-.2100543-.29718955-.12740931-.09635125-.02474979.26021106.13300821.51102986.28427658.75244127.44885742.14171551.09661373.49673106.42170252-.03486491-.04420536.11011262.09650626.22839028.1848887.33941647.28058178.44824052.38633695.86333775.80969185,1.26489471,1.24380201.18410058.19902515.36546946.40063723.54536443.6034688.07334993.08270204.44549232.39849531.12864365.13750435-.13274233-.17812591-.14401191-.18311349-.03380875-.01496273-.13957196-.38902145-.17380484-.45763715-.10269864-.20584707l-.08930242-.66459903c.01737787.09121534.02189121.18304508.01354003.27548924l.08930242-.66459903c-.03841705.24544737-.19992487.47002468.08155191-.09257384-.16044204.32068171.14338045-.13758171.1464127-.16773555-.01510958.15025559-.45632548.45785531-.56439175.55475446-.18478501.16569009-.37659449.32183562-.56811247.47948844-.23682356.19494725.45197743-.32979349.09188891-.07564314-.12159154.08581927-.24188404.17282797-.36520892.2561997-.41055798.27755085-.8380474.53083031-1.27871348.75755997-.13222258.0680306-.26565241.1337918-.40015272.19720048-.08556497.04033866-.50070571.21431643-.10867439.05597204.40715784-.1644541-.06167062.0225787-.11426305.04290857-.13873563.05362897-.27871267.10375264-.41901444.15311126-1.23067107.43295414-2.18198389,1.72836575-1.74609855,3.07529661.39337569,1.21557166,1.75448228,2.21076539,3.07529661,1.74609855,2.09577076-.73729906,4.03806228-1.85370011,5.6417614-3.40481807,1.31943498-1.2761741,1.84208265-3.00961418.99821117-4.71590796-.45820366-.92648001-1.36922023-1.77793474-2.10240072-2.50491401-1.65207571-1.63810252-3.62998982-2.82891383-5.99191953-2.97407421-1.15236012-.07082219-2.33183691.21253871-3.34847378.75046647-1.13991682.60315823-1.91043628,1.59524801-2.37936446,2.76966505-.85043743,2.12989591-.04435174,5.15261682,2.16692582,6.13502123.63477034.28200946,1.22925555.4439989,1.9263969.25202087.57989764-.15969159,1.20833377-.60807206,1.49407768-1.14889971.57467963-1.08769644.37908814-2.85360066-.89687884-3.42047458h0Z\"/><path d=\"M216.54148535,36.96271392c18.41941386-.75837838,36.85462841-1.11827812,55.28964883-1.06862079,5.20804452.0140286,10.41592695.06146098,15.62340385.13926611,3.21861401.04808945,3.21979278-4.95189294,0-5-18.4329622-.27540766-36.87127689-.15205946-55.29866441.38070007-5.20588816.15050894-10.4107389.33440593-15.61438827.54865461-3.20611905.13200482-3.22285512,5.13269389,0,5h0Z\"/><path d=\"M299.03111105,30.24830466c-1.25569175,1.76821072-2.31523615,3.94783201-2.07768435,6.16969264.28931525,2.70601258,2.43790926,4.3177948,5.02077423,4.63214737,2.70515559.32923619,5.51379312.19219039,8.23709964.24980923,2.74758958.05813261,5.49517916.11626525,8.24276874.1743979,11.15687875.23605379,22.31375749.47210786,33.47063623.70816204,6.32778191.13388147,12.65556383.26776297,18.98334574.40164447,3.2187534.06810152,3.21820601-4.93191007,0-5-20.23225023-.42806849-40.46450046-.85613698-60.69675072-1.28420441-1.41542494-.0299471-2.83084989-.0598942-4.24627483-.0898413-1.15805023-.02450164-2.4237871.08867624-3.56431217-.11703431-.31239174-.05634447-.57710479-.2337432-.46009013-.03578419-.05319333-.08998957-.03032556-.38615214.01325946-.62052065.18122009-.97446971.83461163-1.87634765,1.39458157-2.66487306.78220214-1.10146317.19550657-2.78153988-.89687884-3.42047458-1.25357655-.73321517-2.63645764-.20713985-3.42047458.89687884h0Z\"/><path d=\"M370.01218378,27.48128814c-.28565251,2.5402118-.26793812,5.10182694.05281688,7.63784182.08705442.68828642.22137623,1.25691014.73223305,1.76776695.4336057.4336057,1.14501564.76012615,1.76776695.73223305.64655933-.02895947,1.31713952-.24134366,1.76776695-.73223305.41566084-.45279866.81321726-1.12747398.73223305-1.76776695-.32075544-2.5360184-.33846899-5.09763354-.05281688-7.63784182.06687356-.59468408-.32732545-1.36285936-.73223305-1.76776695-.4336057-.4336057-1.14501564-.76012615-1.76776695-.73223305-.64655933.02895947-1.31713952.24134366-1.76776695.73223305-.47609294.51863014-.65396592,1.07176366-.73223305,1.76776695h0Z\"/><path d=\"M381.81524851,38.4777232c20.38371814-.31738413,40.76743628-.63476826,61.15115441-.95215239,5.800245-.09031256,11.60049-.18062511,17.400735-.27093767,3.21432375-.05004854,3.2239749-5.05019881,0-5-20.38371814.31738413-40.76743628.63476826-61.15115441.95215239-5.800245.09031256-11.60049.18062511-17.400735.27093767-3.21432375.05004854-3.2239749,5.05019881,0,5h0Z\"/><path d=\"M472.01839687,35.84255081c.80573722.29581914.43250996.21458361.30514849.11845908-.00571326-.00431201.51047769.45243995.25828748.19986334-.1772498-.17752138.02598836-.11543785.18843098.26717666-.0097624-.02299418-.11944414-.17721247-.10946127-.1809113.01926462-.00713789.26073332.71223026.08248757.14309769-.03300526-.10538467-.06681483-.39140533-.00153613.06135655.0676718.46936001.03424839.11792649.02862795.00039777-.01900572-.39742693-.12165398.69967996-.00138329.11752935.07660545-.37079616-.31820946.53801631-.05171828.1447908.15491995-.22859473-.37191827.40502359-.15809369.19053055.06133025-.06152199.13184884-.12479455.18568674-.1922329.14482933-.18141589-.24309208.17507657-.24909773.17798857.11567769-.05608952.22664291-.15256136.34064455-.21513513.0473565-.02599326.20369557-.1255126.2431004-.12025966.04900142.00653224-.5504091.18951161-.27869648.12733732.1792837-.04102436.3514722-.10745912.53283565-.14487727.10503182-.02166973.42891116-.06849809.00939484-.01141174-.40437812.05502639-.14548629.01801899-.05764452.01415863.22501764-.00988878.44792267-.01946505.6732703-.00898775.11075791.00514957.67545461.06891335.19598021.00560351-.4787462-.06321369.08070101.02455902.18921962.04933881.17223721.03932968.3430028.0860257.51125235.13991521.0841962.02696763.16675309.05926601.25097621.08595048.40261153.12755968-.43931421-.20749075-.16692857-.07668535.30097916.14453662.59528758.29353178.87676995.47414979.1454402.09332421.30952759.1875208.43700238.30454026-.01769055-.01623959-.48373568-.41193708-.19440296-.14072676.08089778.07583074.16696434.14622008.24785302.22223669.23347365.2194111.49978683.46360262.67421565.73395435-.01294092-.02005747-.36277611-.52179786-.15383367-.18598587.04660539.07490412.09945086.14650241.14680558.22096298.09480869.1490772.18329202.30240331.26503085.45903568.04092439.07842152.07697547.15901523.11751774.23752679.19345561.37463377-.11091258-.23432278-.09548635-.23166515.04481656.00772098.15639843.45601916.17000351.50319978.02762586.09580285.16976149.44467196.12455465.53586706-.02298826.04637387-.0320665-.59712802-.04798061-.30973521-.0048273.08717607-.03031564.26968403-.00033508.35355868-.14348489-.40141826.12553338-.5105954.01370173-.25638455.01491949-.03391433.2870907-.5648352.07595722-.22295674.02090685-.03385347.3960035-.47320292.11502503-.19620002.04706656-.04640061.50488475-.3157519.16336819-.15047829-.09682959.04685973-.62600092.27318837-.2126852.12032844.39343953-.14550896.0252802-.01333644-.0731897.02556183-.13427838.05304358-.26892327.10515102-.40402373.15606713-1.94757487.73399409-3.97338269,1.23848687-6.03458864,1.52246655-.57388324.07906594-1.21696142.67535005-1.49407768,1.14889971-.31358395.5358674-.44643885,1.3256252-.25202087,1.9263969.19576179.60492423.5706341,1.18855359,1.14889971,1.49407768.63694467.33652691,1.22025665.34930833,1.9263969.25202087,2.31380496-.31878115,4.58275826-.9170628,6.74515851-1.80194905.75501111-.30896174,1.41649503-.59050236,2.02229643-1.15785788.77712433-.7278058,1.14939912-1.67972268,1.24446573-2.72122433.11409835-1.25000371-.32807583-2.5291758-.87555851-3.63299153-1.02653863-2.06967184-2.93440924-3.56476025-5.05654228-4.38055158-2.08554829-.8017274-4.84744059-.74560096-6.69341403.61680451-1.31857823.97316578-2.21689257,2.44040916-2.08235509,4.12988801.14592292,1.83245365,1.17066479,3.24263973,2.90549024,3.87956522,1.22972505.45148245,2.79257535-.50483024,3.07529661-1.74609855.32183211-1.4129818-.42947189-2.59190903-1.74609855-3.07529661h0Z\"/><path d=\"M22.90500728,39.1802384c5.81841141-.35992492,11.63682281-.71984983,17.45523422-1.07977475,1.34784293-.0833771,2.5-1.08933328,2.5-2.5,0-1.28882103-1.14543309-2.58379304-2.5-2.5-5.81841141.35992492-11.63682281.71984983-17.45523422,1.07977475-1.34784293.0833771-2.5,1.08933328-2.5,2.5,0,1.28882103,1.14543309,2.58379304,2.5,2.5h0Z\"/><path d=\"M492.53726385,41.3699431c8.68734954-1.09794288,17.43433148-1.61275587,26.19049394-1.54147023,3.21817663.02619981,3.22124409-4.97377522,0-5-8.75616577-.07128567-17.50314768.44352776-26.19049394,1.54147023-1.33927612.16926321-2.5,1.02785259-2.5,2.5,0,1.21947426,1.15114907,2.67047331,2.5,2.5h0Z\"/><path d=\"M19.36319162,108.19030085c20.83512651-.35942389,41.67025301-.71884777,62.50537952-1.07827166,5.89360152-.1016697,11.78720304-.20333941,17.68080456-.30500911,3.21391366-.05544278,3.22403086-5.05561731,0-5-20.83512651.35942389-41.67025301.71884777-62.50537952,1.07827166-5.89360152.1016697-11.78720304.20333941-17.68080456.30500911-3.21391366.05544278-3.22403086,5.05561731,0,5h0Z\"/><path d=\"M105.79053182,99.75850186c-.01998844,2.20209082-.30872372,4.59282696.04127701,6.77016588.44390899,2.76153804,2.85320788,3.21695716,5.21114213,3.21051279,4.72125486-.01290346,9.44250972-.02580686,14.16376458-.03871022,9.52533863-.02603309,19.05067727-.05206601,28.5760159-.07809887,5.46671605-.0149406,10.9334321-.02988117,16.40014815-.04482175,3.21685852-.0087917,3.22294641-5.00880834,0-5-10.27079987.02807017-20.54159974.05614034-30.8123996.08421065-5.13539998.01403515-10.27079996.02807034-15.40619993.04210558-2.48487098.00679125-4.96974195.0135825-7.45461293.02037377-1.32526453.00362201-2.65052905.00724403-3.97579358.01086605-.66261434.00181096-1.32528101.0061521-1.98789679.00543303-.27024318.00362944-.54045811.00254317-.81064477-.0032588.04831326.00884908.09079849-.00576876.12745569-.04385352l.89687884.89687884c-.01758802.35369166-.02447199.30160948-.02065189-.15624656l.0085862-.94592615.0128793-1.41888922.03005169-3.31074152c.02921218-3.21825449-4.97076233-3.221062-5,0h0Z\"/><path d=\"M169.33777167,96.6177761l1.97495495,10.35106969c.24560923,1.28727913,1.86206884,2.13871573,3.07529661,1.74609855,1.37378735-.44457646,2.00924605-1.6960965,1.74609855-3.07529661l-1.97495495-10.35106969c-.24560923-1.28727913-1.86206884-2.13871573-3.07529661-1.74609855-1.37378735.44457646-2.00924605,1.6960965-1.74609855,3.07529661h0Z\"/><path d=\"M184.09419894,102.60364057c22.2379562.28592703,44.4759124.57185407,66.71386859.8577811,6.30628609.08108379,12.61257217.16216757,18.91885826.24325136,3.21851164.04138238,3.22026904-4.95859503,0-5-22.2379562-.28592703-44.4759124-.57185407-66.71386859-.8577811-6.30628609-.08108379-12.61257217-.16216757-18.91885826-.24325136-3.21851164-.04138238-3.22026904,4.95859503,0,5h0Z\"/><path d=\"M280.21209981,101.75808844c-.19199615-.02719993-.37511151-.08818876-.5639309-.12124936-.31757925-.0556053.423985.23299648.1445053.07042427-.07014268-.04080171-.14589398-.07350817-.21656043-.11392045-.06737505-.03853001-.60912542-.395169-.29122486-.17954311.29752072.20180263.00386216-.01089573-.06751108-.07657043-.10459772-.09624649-.20596746-.19577829-.30455268-.2982004-.13934114-.14476422-.27251844-.29543101-.40205359-.44897528-.05565697-.0659729-.10967249-.13321785-.16485522-.19957668-.11984611-.14411842-.14276491-.32449066.07458263.09956031-.19136643-.3733611-.51852821-.70912903-.73945426-1.07108536-.10885169-.17833822-.21282233-.35973378-.30863382-.54544925-.02930812-.05680917-.12224811-.30249758-.15615573-.32038065.02016674.01063605.16055087.45061871.08413851.19130253-.05587238-.18961084-.11288335-.38474207-.17567024-.5718642-.08126546-.24219336.08827364-.24600282.00796461.17747143.0169815-.08954449-.00776879-.22758669-.01325759-.31999127-.02585644-.43529592-.08627654.53577593.02094551-.03076063.05876148-.31048207-.23807022.42891969-.05806879.16019196.14850992-.22171343-.13875677.1591026-.14290167.15832916.06903542.01288211.16963052-.24556467.25299887-.2496321.00548413-.00026756-.51984918.32243659-.07127821.07607307.21159062-.11620951.41792523-.23542023.63615536-.33985022.09051115-.04331243.18388372-.08160206.27375204-.12610323.32860205-.16271782-.38733181.14072456-.04201768.01735186.22072226-.07885893.43759868-.16786807.65981852-.24312907.47586341-.16116451.96023621-.29656548,1.45068528-.40550357.2291897-.0509074.45968099-.09096689.69004387-.13540102.14445897-.02786434.42373312-.14647088-.06826313.00155086.08976867-.02700776.20623403-.02414145.29949805-.03372411.42225023-.04338522.84750091-.07241913,1.2721893-.06173854.16003778.00402483.4290836.07306202.58171346.03780196-.00069494.00016054-.5508683-.10856661-.30204033-.04042065.06899199.01889468.14523139.02437785.2155785.03837904.18880898.03757867.37647279.08384679.56036495.14092954.06432295.01996676.13634528.05699427.20236618.0680088.28215253.04707263-.50877535-.26972357-.1457278-.0619826.1322784.07569158.27566645.17892363.41263255.23936716.20542219.09065339-.22903649-.16699939-.23897053-.1896686.01397633.03189361.15352564.14719439.19340607.18089569.30489636.25765537-.29138022-.47650468-.03057752-.03214503.02667748.0454535.05733628.14426465.09563004.17830908-.14536326-.37141069-.18648375-.45912317-.12336148-.26313745.01778455.05158915.03189156.10416449.04232104.15772602.11226546.30316075.00592696-.50354656-.02814971-.18398656.00319728.0538324.00307205.10765714-.00037567.16147423-.00951101.19575677.00629278.10860303.04741137-.26146122-.03220988.06261617-.03589037.17029185-.05399594.23944496-.07037168.26878032-.2158113.27528028.05826309-.05243032-.06487393.07756973-.24111993.59495465-.3289039.58117675-.02104744-.00330345.33494852-.37639412.13673849-.17550331-.10062858.10198957-.19182043.21316231-.29543732.31287754-.03242151.03120069-.27001297.2422811-.270429.24154417-.01388804-.02460073.41859361-.28965371.07315476-.06246951-.20316795.13361713-.40562415.26543286-.61695909.3860028-.4772856.27229901-.9763012.50416718-1.47420451.73563936-1.18944929.55296764-1.58115732,2.35910581-.89687884,3.42047458.78999647,1.22534555,2.14814871,1.48837529,3.42047458.89687884,2.58277485-1.20071611,5.07361625-3.06815691,5.19808647-6.18138448.11086152-2.77284904-2.15474001-4.87159744-4.75110291-5.32465783-2.78513674-.48600107-5.62549248.12458137-8.19041533,1.2348381-1.51997653.65793954-2.78234271,1.60802391-3.3821299,3.20783626-.51451577,1.3723679-.25326675,2.85692004.30013215,4.16827644.56820473,1.34644089,1.42755714,2.5414672,2.38591429,3.64030287.96384796,1.10513134,2.30850313,2.1122066,3.79538575,2.32285199.69468418.09841531,1.29463712.11767828,1.9263969-.25202087.51858402-.30346989,1.01315141-.89808409,1.14889971-1.49407768.26884528-1.18034675-.36135178-2.87912072-1.74609855-3.07529661h0Z\"/><path d=\"M295.90981265,101.4397384h120.27272727c3.2172614,0,3.22259025-5,0-5h-120.27272727c-3.2172614,0-3.22259025,5,0,5h0Z\"/><path d=\"M419.21667136,93.09331867c-.30863375,2.19593144-.45810535,4.36793616-.24177809,6.58136297.19629131,2.00842212.47178918,4.1407421,2.45122717,5.18165195.95923555.50442486,2.07855958.50264875,3.13521572.54356839,1.16559527.04513838,2.33119055.09027677,3.49678582.13541515,2.24793374.0870526,4.49586749.1741052,6.74380123.2611578,8.99173496.34821041,17.98346991.69642085,26.97520487,1.0446313,5.16192191.19989859,10.32384383.39979719,15.48576574.59969579,3.21780387.12461143,3.21238495-4.87559842,0-5-10.40710064-.40302137-20.81420127-.80604273-31.22130191-1.20906407-5.16192192-.19989858-10.32384385-.39979715-15.48576577-.59969571-1.24885208-.04836255-2.49770416-.09672511-3.74655624-.14508766-.66605444-.02579336-1.33210889-.05158672-1.99816333-.07738008-.33302722-.01289668-.66605444-.02579336-.99908166-.03869004-.63802482-.09786557-.53359849.04363958.313279.42451545.14168437-.12378777-.24609978-2.43318016-.25587457-2.77848906-.03381714-1.19464001.00212017-2.40962428.16863719-3.59439411.18767609-1.33531678-.32597095-2.68508622-1.74609855-3.07529661-1.17038449-.32158814-2.88617355.40048656-3.07529661,1.74609855h0Z\"/><path d=\"M476.68253993,95.39428385v9.27272727c0,1.307694,1.14988643,2.56047175,2.5,2.5,1.35450499-.06066844,2.5-1.09845912,2.5-2.5v-9.27272727c0-1.307694-1.14988643-2.56047175-2.5-2.5-1.35450499.06066844-2.5,1.09845912-2.5,2.5h0Z\"/><path d=\"M483.53796372,101.78282955c11.08758704-.44467996,22.18603589-.54070758,33.27965714-.28794712,3.21874882.07333696,3.21774993-4.9266858,0-5-11.09362154-.25276046-22.19207038-.15673283-33.27965714.28794712-3.20654419.12860201-3.22298592,5.12926142,0,5h0Z\"/></svg>\n<figcaption>\n图1: 两个线程，只包含 SeqCst 的一个时序图。t ->, 点是 Fence，范围是其他访存操作。\n</figcaption>\n</figure>\n<p>在这个图中，并且如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A \\rightarrow_{rf \\cup fr \\cup co} B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span>，那么在图上，A 的前边沿一定早于 B 的后边沿<sup>[4]</sup>。把某操作 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>X</mi></mrow><annotation encoding=\"application/x-tex\">X</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span></span></span></span> 的前边沿记作 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>t</mi><mi>a</mi><mi>r</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>X</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">start(X)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mclose\">)</span></span></span></span>，后边沿记作 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>X</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">end(X)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">X</span><span class=\"mclose\">)</span></span></span></span>，在时间上 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 时刻早于 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 时刻记作 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>≺</mo><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A \\prec B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7224em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span>。那么：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>M</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow></msub><mi>N</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>s</mi><mi>t</mi><mi>a</mi><mi>r</mi><mi>t</mi><mo stretchy=\"false\">(</mo><mi>M</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>N</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\nM \\to_{rf \\cup fr \\cup co} N \\implies start(M) \\prec end(N)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">t</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>这一事实将用于排序各个两侧的同步操作。</p>\n<h2>Sketch proof</h2>\n<p>证明的思路大概是首先构造一个关系，可以包含 SeqCst 需要保证的所有序。如果这个关系不包含环，那么做传递闭包后是一个偏序，之后可以全序化。</p>\n<p>证明大概分作两步：</p>\n<p>第一步是根据 SeqCst 的执行时序，有一个很自然的基础序：如果两个 SeqCst 操作不互相重叠，那么在时间上完全更早发生的操作，应该在所有需要保证的序中都早于另一个操作。把这个序称作 Base wall-clock before <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span>，这是一个偏序，并且限制到同一个线程内是一个全序。</p>\n<figure>\n<svg class=\"inline-svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 507.49214873 120.67295622\"><defs><style>.cls-1{fill:#319966;}</style></defs><path d=\"M44.39060769,16.86760121c.01831612,2.39700308.24411632,4.78380396.65564577,7.14554487.37011111,2.12404375.802947,4.46936069,1.78459699,6.40858703,1.13087712,2.234021,3.2974553,2.67184596,5.59620868,2.59166984,2.49481719-.08701445,4.98941147-.18098224,7.48410535-.27147286,9.72933688-.35291455,19.45867378-.70582851,29.1880107-1.05874224,5.57150059-.2020959,11.14300119-.40419172,16.71450179-.60628755,3.20801233-.11636468,3.22339567-5.11692268,0-5-17.95707908.65135966-35.92195827,1.52692424-53.88555819,1.95460085-.1172196.00279076-.62255603.06974832-.76787875.00563999-.18572709-.08193249.05585847.06634112.07680309.09396291-.14822435-.19547841-.23404742-.72871135-.2934682-.92370633-.33900682-1.11248345-.62374045-2.24192328-.85815398-3.38093255-.47263724-2.29653209-.67690801-4.61563242-.69481325-6.95886395-.0245744-3.21601439-5.02463133-3.22346514-5,0h0Z\"/><path d=\"M109.89878108,18.37128634c-1.03128451,3.18371748-1.43214314,6.61611863-1.13397013,9.95022993.11617157,1.29900736,1.06661474,2.5642015,2.5,2.5,1.25466478-.05619659,2.62474984-1.10507208,2.5-2.5-.1372401-1.53459148-.12966177-3.07764058.03685816-4.60975581.00919655-.0866428.01904614-.17321213.02954876-.25970799.03516862-.27940424.02814408-.23063387-.02107363.1463111-.02518379-.1468121.05613941-.37385317.0799431-.51660737.06210037-.37242491.1332162-.74328349.21341405-1.11223578.16666532-.76674812.37491114-1.52267809.61667486-2.26903602.40320327-1.24474409-.46997527-2.7846365-1.74609855-3.07529661-1.37044825-.31214433-2.64358392.41334193-3.07529661,1.74609855h0Z\"/><path d=\"M118.89231863,25.7850026c19.45059166-.52346332,38.9106795-.64325382,58.36624153-.35928521,3.21859898.04697788,3.21987364-4.95300351,0-5-19.45556197-.28396861-38.91564981-.16417811-58.36624153.35928521-3.211205.08642143-3.22399942,5.08676576,0,5h0Z\"/><path d=\"M188.52487863,23.55979516c-.07707293-.0342412-.15037812-.07936919-.22713261-.11299686-.37501539-.16430173.22735883.09859745.22502639.190253.00068544-.02693521-.15216473-.15521727-.17268281-.17177439-.14642545-.11815841.34264127.54735148.18612641.23328872-.02844044-.05706858-.06340127-.11661302-.09684073-.17095667-.19208507-.31216422.15271216.48001825.11782718.2765627-.03134566-.18281364-.09666267-.35623136-.12259018-.54272769l.08930242.66459903c-.02492457-.24291031-.02382671-.47879825.00239722-.72155868l-.08930242.66459903c.01972507-.1375132.04393138-.27322457.08060469-.40738305.01821052-.06675021.03883784-.132745.06188195-.19798437.08903728-.23438796.04495418-.13067792-.1322493.31113011.0544322-.07724425.10544839-.18605154.15208233-.26895388.18978369-.33738323-.47888314.51619442-.06572183.10804564.06064287-.05914522.12367878-.11561899.18910772-.16942129-.34425613.2568385-.41131357.31364036-.20117232.17040557.10203269-.0534268.24032031-.11085528.32704564-.1812248-.40878603.16388143-.49258831.20017053-.25140683.1088673.07887458-.02771754.15861226-.0526781.23921302-.07488166.16288295-.04502193.32781871-.0758883.49460006-.10204446l-.66459903.08930242c.42963808-.05386757.85316021-.04884677,1.28241885.00654346l-.66459903-.08930242c.25701639.04003512.51045095.09280927.75942718.16902743.12340189.03777656.24269045.08964704.36580302.12712263-.69005776-.2100543-.29718955-.12740931-.09635125-.02474979.26021106.13300821.51102986.28427658.75244127.44885742.14171551.09661373.49673106.42170252-.03486491-.04420536.11011262.09650626.22839028.1848887.33941647.28058178.44824052.38633695.86333775.80969185,1.26489471,1.24380201.18410058.19902515.36546946.40063723.54536443.6034688.07334993.08270204.44549232.39849531.12864365.13750435-.13274233-.17812591-.14401191-.18311349-.03380875-.01496273-.13957196-.38902145-.17380484-.45763715-.10269864-.20584707l-.08930242-.66459903c.01737787.09121534.02189121.18304508.01354003.27548924l.08930242-.66459903c-.03841705.24544737-.19992487.47002468.08155191-.09257384-.16044204.32068171.14338045-.13758171.1464127-.16773555-.01510958.15025559-.45632548.45785531-.56439175.55475446-.18478501.16569009-.37659449.32183562-.56811247.47948844-.23682356.19494725.45197743-.32979349.09188891-.07564314-.12159154.08581927-.24188404.17282797-.36520892.2561997-.41055798.27755085-.8380474.53083031-1.27871348.75755997-.13222258.0680306-.26565241.1337918-.40015272.19720048-.08556497.04033866-.50070571.21431643-.10867439.05597204.40715784-.1644541-.06167062.0225787-.11426305.04290857-.13873563.05362897-.27871267.10375264-.41901444.15311126-1.23067107.43295414-2.18198389,1.72836575-1.74609855,3.07529661.39337569,1.21557166,1.75448228,2.21076539,3.07529661,1.74609855,2.09577076-.73729906,4.03806228-1.85370011,5.6417614-3.40481807,1.31943498-1.2761741,1.84208265-3.00961418.99821117-4.71590796-.45820366-.92648001-1.36922023-1.77793474-2.10240072-2.50491401-1.65207571-1.63810252-3.62998982-2.82891383-5.99191953-2.97407421-1.15236012-.07082219-2.33183691.21253871-3.34847378.75046647-1.13991682.60315823-1.91043628,1.59524801-2.37936446,2.76966505-.85043743,2.12989591-.04435174,5.15261682,2.16692582,6.13502123.63477034.28200946,1.22925555.4439989,1.9263969.25202087.57989764-.15969159,1.20833377-.60807206,1.49407768-1.14889971.57467963-1.08769644.37908814-2.85360066-.89687884-3.42047458h0Z\"/><path d=\"M202.89109339,29.61772203c18.41941386-.75837838,36.85462841-1.11827812,55.28964883-1.06862079,5.20804452.0140286,10.41592695.06146098,15.62340385.13926611,3.21861401.04808945,3.21979278-4.95189294,0-5-18.4329622-.27540766-36.87127689-.15205946-55.29866441.38070007-5.20588816.15050894-10.4107389.33440593-15.61438827.54865461-3.20611905.13200482-3.22285512,5.13269389,0,5h0Z\"/><path d=\"M285.38071908,22.90331278c-1.25569175,1.76821072-2.31523615,3.94783201-2.07768435,6.16969264.28931525,2.70601258,2.43790926,4.3177948,5.02077423,4.63214737,2.70515559.32923619,5.51379312.19219039,8.23709964.24980923,2.74758958.05813261,5.49517916.11626525,8.24276874.1743979,11.15687875.23605379,22.31375749.47210786,33.47063623.70816204,6.32778191.13388147,12.65556383.26776297,18.98334574.40164447,3.2187534.06810152,3.21820601-4.93191007,0-5-20.23225023-.42806849-40.46450046-.85613698-60.69675072-1.28420441-1.41542494-.0299471-2.83084989-.0598942-4.24627483-.0898413-1.15805023-.02450164-2.4237871.08867624-3.56431217-.11703431-.31239174-.05634447-.57710479-.2337432-.46009013-.03578419-.05319333-.08998957-.03032556-.38615214.01325946-.62052065.18122009-.97446971.83461163-1.87634765,1.39458157-2.66487306.78220214-1.10146317.19550657-2.78153988-.89687884-3.42047458-1.25357655-.73321517-2.63645764-.20713985-3.42047458.89687884h0Z\"/><path d=\"M356.36179182,20.13629626c-.28565251,2.5402118-.26793812,5.10182694.05281688,7.63784182.08705442.68828642.22137623,1.25691014.73223305,1.76776695.4336057.4336057,1.14501564.76012615,1.76776695.73223305.64655933-.02895947,1.31713952-.24134366,1.76776695-.73223305.41566084-.45279866.81321726-1.12747398.73223305-1.76776695-.32075544-2.5360184-.33846899-5.09763354-.05281688-7.63784182.06687356-.59468408-.32732545-1.36285936-.73223305-1.76776695-.4336057-.4336057-1.14501564-.76012615-1.76776695-.73223305-.64655933.02895947-1.31713952.24134366-1.76776695.73223305-.47609294.51863014-.65396592,1.07176366-.73223305,1.76776695h0Z\"/><path d=\"M368.16485655,31.13273132c20.38371814-.31738413,40.76743628-.63476826,61.15115441-.95215239,5.800245-.09031256,11.60049-.18062511,17.400735-.27093767,3.21432375-.05004854,3.2239749-5.05019881,0-5-20.38371814.31738413-40.76743628.63476826-61.15115441.95215239-5.800245.09031256-11.60049.18062511-17.400735.27093767-3.21432375.05004854-3.2239749,5.05019881,0,5h0Z\"/><path d=\"M458.36800491,28.49755893c.80573722.29581914.43250996.21458361.30514849.11845908-.00571326-.00431201.51047769.45243995.25828748.19986334-.1772498-.17752138.02598836-.11543785.18843098.26717666-.0097624-.02299418-.11944414-.17721247-.10946127-.1809113.01926462-.00713789.26073332.71223026.08248757.14309769-.03300526-.10538467-.06681483-.39140533-.00153613.06135655.0676718.46936001.03424839.11792649.02862795.00039777-.01900572-.39742693-.12165398.69967996-.00138329.11752935.07660545-.37079616-.31820946.53801631-.05171828.1447908.15491995-.22859473-.37191827.40502359-.15809369.19053055.06133025-.06152199.13184884-.12479455.18568674-.1922329.14482933-.18141589-.24309208.17507657-.24909773.17798857.11567769-.05608952.22664291-.15256136.34064455-.21513513.0473565-.02599326.20369557-.1255126.2431004-.12025966.04900142.00653224-.5504091.18951161-.27869648.12733732.1792837-.04102436.3514722-.10745912.53283565-.14487727.10503182-.02166973.42891116-.06849809.00939484-.01141174-.40437812.05502639-.14548629.01801899-.05764452.01415863.22501764-.00988878.44792267-.01946505.6732703-.00898775.11075791.00514957.67545461.06891335.19598021.00560351-.4787462-.06321369.08070101.02455902.18921962.04933881.17223721.03932968.3430028.0860257.51125235.13991521.0841962.02696763.16675309.05926601.25097621.08595048.40261153.12755968-.43931421-.20749075-.16692857-.07668535.30097916.14453662.59528758.29353178.87676995.47414979.1454402.09332421.30952759.1875208.43700238.30454026-.01769055-.01623959-.48373568-.41193708-.19440296-.14072676.08089778.07583074.16696434.14622008.24785302.22223669.23347365.2194111.49978683.46360262.67421565.73395435-.01294092-.02005747-.36277611-.52179786-.15383367-.18598587.04660539.07490412.09945086.14650241.14680558.22096298.09480869.1490772.18329202.30240331.26503085.45903568.04092439.07842152.07697547.15901523.11751774.23752679.19345561.37463377-.11091258-.23432278-.09548635-.23166515.04481656.00772098.15639843.45601916.17000351.50319978.02762586.09580285.16976149.44467196.12455465.53586706-.02298826.04637387-.0320665-.59712802-.04798061-.30973521-.0048273.08717607-.03031564.26968403-.00033508.35355868-.14348489-.40141826.12553338-.5105954.01370173-.25638455.01491949-.03391433.2870907-.5648352.07595722-.22295674.02090685-.03385347.3960035-.47320292.11502503-.19620002.04706656-.04640061.50488475-.3157519.16336819-.15047829-.09682959.04685973-.62600092.27318837-.2126852.12032844.39343953-.14550896.0252802-.01333644-.0731897.02556183-.13427838.05304358-.26892327.10515102-.40402373.15606713-1.94757487.73399409-3.97338269,1.23848687-6.03458864,1.52246655-.57388324.07906594-1.21696142.67535005-1.49407768,1.14889971-.31358395.5358674-.44643885,1.3256252-.25202087,1.9263969.19576179.60492423.5706341,1.18855359,1.14889971,1.49407768.63694467.33652691,1.22025665.34930833,1.9263969.25202087,2.31380496-.31878115,4.58275826-.9170628,6.74515851-1.80194905.75501111-.30896174,1.41649503-.59050236,2.02229643-1.15785788.77712433-.7278058,1.14939912-1.67972268,1.24446573-2.72122433.11409835-1.25000371-.32807583-2.5291758-.87555851-3.63299153-1.02653863-2.06967184-2.93440924-3.56476025-5.05654228-4.38055158-2.08554829-.8017274-4.84744059-.74560096-6.69341403.61680451-1.31857823.97316578-2.21689257,2.44040916-2.08235509,4.12988801.14592292,1.83245365,1.17066479,3.24263973,2.90549024,3.87956522,1.22972505.45148245,2.79257535-.50483024,3.07529661-1.74609855.32183211-1.4129818-.42947189-2.59190903-1.74609855-3.07529661h0Z\"/><path d=\"M9.25461532,31.83524652c5.81841141-.35992492,11.63682281-.71984983,17.45523422-1.07977475,1.34784293-.0833771,2.5-1.08933328,2.5-2.5,0-1.28882103-1.14543309-2.58379304-2.5-2.5-5.81841141.35992492-11.63682281.71984983-17.45523422,1.07977475-1.34784293.0833771-2.5,1.08933328-2.5,2.5,0,1.28882103,1.14543309,2.58379304,2.5,2.5h0Z\"/><path d=\"M478.88687189,34.02495122c8.68734954-1.09794288,17.43433148-1.61275587,26.19049394-1.54147023,3.21817663.02619981,3.22124409-4.97377522,0-5-8.75616577-.07128567-17.50314768.44352776-26.19049394,1.54147023-1.33927612.16926321-2.5,1.02785259-2.5,2.5,0,1.21947426,1.15114907,2.67047331,2.5,2.5h0Z\"/><path d=\"M5.71279965,100.84530897c20.83512651-.35942389,41.67025301-.71884777,62.50537952-1.07827166,5.89360152-.1016697,11.78720304-.20333941,17.68080456-.30500911,3.21391366-.05544278,3.22403086-5.05561731,0-5-20.83512651.35942389-41.67025301.71884777-62.50537952,1.07827166-5.89360152.1016697-11.78720304.20333941-17.68080456.30500911-3.21391366.05544278-3.22403086,5.05561731,0,5h0Z\"/><path d=\"M92.14013986,92.41350998c-.01998844,2.20209082-.30872372,4.59282696.04127701,6.77016588.44390899,2.76153804,2.85320788,3.21695716,5.21114213,3.21051279,4.72125486-.01290346,9.44250972-.02580686,14.16376458-.03871022,9.52533863-.02603309,19.05067727-.05206601,28.5760159-.07809887,5.46671605-.0149406,10.9334321-.02988117,16.40014815-.04482175,3.21685852-.0087917,3.22294641-5.00880834,0-5-10.27079987.02807017-20.54159974.05614034-30.8123996.08421065-5.13539998.01403515-10.27079996.02807034-15.40619993.04210558-2.48487098.00679125-4.96974195.0135825-7.45461293.02037377-1.32526453.00362201-2.65052905.00724403-3.97579358.01086605-.66261434.00181096-1.32528101.0061521-1.98789679.00543303-.27024318.00362944-.54045811.00254317-.81064477-.0032588.04831326.00884908.09079849-.00576876.12745569-.04385352l.89687884.89687884c-.01758802.35369166-.02447199.30160948-.02065189-.15624656l.0085862-.94592615.0128793-1.41888922.03005169-3.31074152c.02921218-3.21825449-4.97076233-3.221062-5,0h0Z\"/><path d=\"M155.68737971,89.27278421c.65831832,3.45035656,1.31663664,6.90071313,1.97495495,10.35106969.24560923,1.28727913,1.86206884,2.13871573,3.07529661,1.74609855,1.37378735-.44457646,2.00924605-1.6960965,1.74609855-3.07529661-.65831832-3.45035656-1.31663664-6.90071313-1.97495495-10.35106969-.24560923-1.28727913-1.86206884-2.13871573-3.07529661-1.74609855-1.37378735.44457646-2.00924605,1.6960965-1.74609855,3.07529661h0Z\"/><path d=\"M170.44380698,95.25864868c22.2379562.28592703,44.4759124.57185407,66.71386859.8577811,6.30628609.08108379,12.61257217.16216757,18.91885826.24325136,3.21851164.04138238,3.22026904-4.95859503,0-5-22.2379562-.28592703-44.4759124-.57185407-66.71386859-.8577811-6.30628609-.08108379-12.61257217-.16216757-18.91885826-.24325136-3.21851164-.04138238-3.22026904,4.95859503,0,5h0Z\"/><path d=\"M266.56170785,94.41309655c-.19199615-.02719993-.37511151-.08818876-.5639309-.12124936-.31757925-.0556053.423985.23299648.1445053.07042427-.07014268-.04080171-.14589398-.07350817-.21656043-.11392045-.06737505-.03853001-.60912542-.395169-.29122486-.17954311.29752072.20180263.00386216-.01089573-.06751108-.07657043-.10459772-.09624649-.20596746-.19577829-.30455268-.2982004-.13934114-.14476422-.27251844-.29543101-.40205359-.44897528-.05565697-.0659729-.10967249-.13321785-.16485522-.19957668-.11984611-.14411842-.14276491-.32449066.07458263.09956031-.19136643-.3733611-.51852821-.70912903-.73945426-1.07108536-.10885169-.17833822-.21282233-.35973378-.30863382-.54544925-.02930812-.05680917-.12224811-.30249758-.15615573-.32038065.02016674.01063605.16055087.45061871.08413851.19130253-.05587238-.18961084-.11288335-.38474207-.17567024-.5718642-.08126546-.24219336.08827364-.24600282.00796461.17747143.0169815-.08954449-.00776879-.22758669-.01325759-.31999127-.02585644-.43529592-.08627654.53577593.02094551-.03076063.05876148-.31048207-.23807022.42891969-.05806879.16019196.14850992-.22171343-.13875677.1591026-.14290167.15832916.06903542.01288211.16963052-.24556467.25299887-.2496321.00548413-.00026756-.51984918.32243659-.07127821.07607307.21159062-.11620951.41792523-.23542023.63615536-.33985022.09051115-.04331243.18388372-.08160206.27375204-.12610323.32860205-.16271782-.38733181.14072456-.04201768.01735186.22072226-.07885893.43759868-.16786807.65981852-.24312907.47586341-.16116451.96023621-.29656548,1.45068528-.40550357.2291897-.0509074.45968099-.09096689.69004387-.13540102.14445897-.02786434.42373312-.14647088-.06826313.00155086.08976867-.02700776.20623403-.02414145.29949805-.03372411.42225023-.04338522.84750091-.07241913,1.2721893-.06173854.16003778.00402483.4290836.07306202.58171346.03780196-.00069494.00016054-.5508683-.10856661-.30204033-.04042065.06899199.01889468.14523139.02437785.2155785.03837904.18880898.03757867.37647279.08384679.56036495.14092954.06432295.01996676.13634528.05699427.20236618.0680088.28215253.04707263-.50877535-.26972357-.1457278-.0619826.1322784.07569158.27566645.17892363.41263255.23936716.20542219.09065339-.22903649-.16699939-.23897053-.1896686.01397633.03189361.15352564.14719439.19340607.18089569.30489636.25765537-.29138022-.47650468-.03057752-.03214503.02667748.0454535.05733628.14426465.09563004.17830908-.14536326-.37141069-.18648375-.45912317-.12336148-.26313745.01778455.05158915.03189156.10416449.04232104.15772602.11226546.30316075.00592696-.50354656-.02814971-.18398656.00319728.0538324.00307205.10765714-.00037567.16147423-.00951101.19575677.00629278.10860303.04741137-.26146122-.03220988.06261617-.03589037.17029185-.05399594.23944496-.07037168.26878032-.2158113.27528028.05826309-.05243032-.06487393.07756973-.24111993.59495465-.3289039.58117675-.02104744-.00330345.33494852-.37639412.13673849-.17550331-.10062858.10198957-.19182043.21316231-.29543732.31287754-.03242151.03120069-.27001297.2422811-.270429.24154417-.01388804-.02460073.41859361-.28965371.07315476-.06246951-.20316795.13361713-.40562415.26543286-.61695909.3860028-.4772856.27229901-.9763012.50416718-1.47420451.73563936-1.18944929.55296764-1.58115732,2.35910581-.89687884,3.42047458.78999647,1.22534555,2.14814871,1.48837529,3.42047458.89687884,2.58277485-1.20071611,5.07361625-3.06815691,5.19808647-6.18138448.11086152-2.77284904-2.15474001-4.87159744-4.75110291-5.32465783-2.78513674-.48600107-5.62549248.12458137-8.19041533,1.2348381-1.51997653.65793954-2.78234271,1.60802391-3.3821299,3.20783626-.51451577,1.3723679-.25326675,2.85692004.30013215,4.16827644.56820473,1.34644089,1.42755714,2.5414672,2.38591429,3.64030287.96384796,1.10513134,2.30850313,2.1122066,3.79538575,2.32285199.69468418.09841531,1.29463712.11767828,1.9263969-.25202087.51858402-.30346989,1.01315141-.89808409,1.14889971-1.49407768.26884528-1.18034675-.36135178-2.87912072-1.74609855-3.07529661h0Z\"/><path d=\"M282.25942069,94.09474651h120.27272727c3.2172614,0,3.22259025-5,0-5h-120.27272727c-3.2172614,0-3.22259025,5,0,5h0Z\"/><path d=\"M405.56627939,85.74832678c-.30863375,2.19593144-.45810535,4.36793616-.24177809,6.58136297.19629131,2.00842212.47178918,4.1407421,2.45122717,5.18165195.95923555.50442486,2.07855958.50264875,3.13521572.54356839,1.16559527.04513838,2.33119055.09027677,3.49678582.13541515,2.24793374.0870526,4.49586749.1741052,6.74380123.2611578,8.99173496.34821041,17.98346991.69642085,26.97520487,1.0446313,5.16192191.19989859,10.32384383.39979719,15.48576574.59969579,3.21780387.12461143,3.21238495-4.87559842,0-5-10.40710064-.40302137-20.81420127-.80604273-31.22130191-1.20906407-5.16192192-.19989858-10.32384385-.39979715-15.48576577-.59969571-1.24885208-.04836255-2.49770416-.09672511-3.74655624-.14508766-.66605444-.02579336-1.33210889-.05158672-1.99816333-.07738008-.33302722-.01289668-.66605444-.02579336-.99908166-.03869004-.63802482-.09786557-.53359849.04363958.313279.42451545.14168437-.12378777-.24609978-2.43318016-.25587457-2.77848906-.03381714-1.19464001.00212017-2.40962428.16863719-3.59439411.18767609-1.33531678-.32597095-2.68508622-1.74609855-3.07529661-1.17038449-.32158814-2.88617355.40048656-3.07529661,1.74609855h0Z\"/><path d=\"M463.03214796,88.04929197v9.27272727c0,1.307694,1.14988643,2.56047175,2.5,2.5,1.35450499-.06066844,2.5-1.09845912,2.5-2.5v-9.27272727c0-1.307694-1.14988643-2.56047175-2.5-2.5-1.35450499.06066844-2.5,1.09845912-2.5,2.5h0Z\"/><path d=\"M469.88757175,94.43783767c11.08758704-.44467996,22.18603589-.54070758,33.27965714-.28794712,3.21874882.07333696,3.21774993-4.9266858,0-5-11.09362154-.25276046-22.19207038-.15673283-33.27965714.28794712-3.20654419.12860201-3.22298592,5.12926142,0,5h0Z\"/><path class=\"cls-1\" d=\"M176.84592572,37.10557417c-6.02703392,11.89769586-11.57032165,24.03075489-16.65573509,36.35998377-.51506454,1.24873792.55752711,2.74871122,1.74609855,3.07529661,1.43584806.39452993,2.55830114-.49267921,3.07529661-1.74609855,4.91998097-11.92814945,10.3210246-23.65552587,16.15169335-35.16558609,1.45077884-2.86391708-2.86135988-5.39780694-4.31735343-2.52359574h0Z\"/><path class=\"cls-1\" d=\"M178.53375923,33.15545396c-2.92086284,1.00813302-5.74062537,2.32829836-8.35329395,3.97999115-1.10448225.69823834-1.64612922,2.25832936-.89687884,3.42047458.71285336,1.10569064,2.23798701,1.64443106,3.42047458.89687884,1.71465957-1.08398396,3.51229184-2.02575397,5.37924125-2.81917157l-.59719884.25202087c.78237251-.3289405,1.57458394-.63189601,2.37685386-.90879871.61920597-.21371835,1.15595203-.57109426,1.49407768-1.14889971.31358395-.5358674.44643885-1.3256252.25202087-1.9263969-.39540351-1.22183782-1.75171933-2.20292999-3.07529661-1.74609855h0Z\"/><path class=\"cls-1\" d=\"M175.53998188,39.34504367c.24422185.17732039.48590342.35793133.72515484.54190063l-.50596908-.39090976c1.83117959,1.41809027,3.4911153,3.04420174,4.94587576,4.84641796.37721231.4673059,1.19471553.73223305,1.76776695.73223305.61316822,0,1.34560469-.27235209,1.76776695-.73223305.43736004-.47643661.76205534-1.1019439.73223305-1.76776695l-.08930242-.66459903c-.11877984-.423512-.33309005-.79123464-.64293063-1.10316792-1.78520971-2.21159014-3.87971303-4.11125401-6.17699968-5.77922836-.4947973-.35925391-1.36157-.40756229-1.9263969-.25202087-.57989764.15969159-1.20833377.60807206-1.49407768,1.14889971-.30654619.58020013-.46020846,1.28307569-.25202087,1.9263969l.25202087.59719884c.2222534.37566583.52121301.67462544.89687884.89687884h0Z\"/><path class=\"cls-1\" d=\"M120.04755435,13.13313673c19.01740746-5.69723091,39.26522843-7.117893,58.87720941-3.95610538,1.33140368.2146451,2.69016716-.34446247,3.07529661-1.74609855.3274475-1.19170897-.4054178-2.85915589-1.74609855-3.07529661-15.96568875-2.57394279-32.24149908-2.37386763-48.13067558.66509231-4.52246248.86496505-8.99444289,1.96972028-13.40492995,3.29101306-3.07473691.92112903-1.76498503,5.74834989,1.32919806,4.82139517h0Z\"/><path class=\"cls-1\" d=\"M176.61561124,4.25372859c2.70935408,2.57208806,5.22822239,5.33482701,7.53969679,8.2696712l.50596908-3.92644367c-.58161352.42544785-1.18537593.81731498-1.81692836,1.16483021-.31540961.17355589-.63668648.33632322-.96288593.48860482-.14760641.06890796-.2954898.142846-.44776097.20122844.58374776-.22381532-.04859778.01026962-.13137139.04136555-.67390289.25316807-1.36507358.46144035-2.06651251.62331308-.31881904.07357463-.63996399.13772186-.96268919.19167133-.14137497.02363343-.70375558.19596538-.11284779.02158341-.17907468.05284648-.4022605.04208181-.58621418.05797852-1.29946215.11229556-2.56407682,1.06939835-2.5,2.5.0563464,1.25800957,1.10470687,2.62057698,2.5,2.5,3.45109817-.29823338,6.80045892-1.41746479,9.61080606-3.47322193.65631618-.48009253,1.08272751-1.00161642,1.19355092-1.8263772.11379104-.8468462-.17489077-1.44911035-.68758184-2.10006647-2.31147542-2.93484547-4.8303439-5.69758426-7.53969679-8.2696712-.94900381-.90092373-2.60595407-1.01263448-3.53553391,0-.89652627.9766277-1.0131428,2.57372071,0,3.53553391h0Z\"/><path class=\"cls-1\" d=\"M367.83396119,17.26288889c3.01842312-3.68515289,7.23220657-5.74158499,11.73879355-7.03599492,5.19719403-1.49277039,10.64432363-2.20670469,16.00418889-2.819889,12.4136484-1.42015781,24.97372436-1.58914063,37.42014691-.48802374,4.85045491.42911269,10.29584754,1.1397386,13.593765,5.11607659.86253185,1.03996483,2.6433047.8922292,3.53553391,0,1.02906277-1.02906277.86466507-2.49299703,0-3.53553391-3.4674273-4.180718-8.90824978-5.58731478-14.06883855-6.25603119-6.18408929-.80134305-12.48972924-1.01863654-18.72022691-1.03978995-6.69695961-.02273711-13.39519785.31642622-20.0555549,1.01608218-5.92804814.62272851-11.95409072,1.34487172-17.73764428,2.83175531-5.71839819,1.47013291-11.42712372,4.01376845-15.24569753,8.67581473-.8548706,1.04370021-1.02125971,2.5142742,0,3.53553391.88211895.88211895,2.6757362,1.04971566,3.53553391,0h0Z\"/><path class=\"cls-1\" d=\"M446.15046635,7.04999412c.91172119,1.59789802,1.79825813,3.20996542,2.65587789,4.83756217.41966883.79645043.83269568,1.59639872,1.23894704,2.39977648.21183355.41890903.41295268.84422973.63035973,1.26022643.11830196.25354672.13625006.28183135.05384431.08485389-.07044973-.18537755-.06806941-.16719023.00714095.05456197-.11993588-.90596695.15146247-1.5138274.81419503-1.82358134.40107846-.19785008.45688747-.255223.16742704-.17211874l.32337088-.04873383c-.15922415.01263115-.31848039.0248438-.47776873.03663793-.2389315.01769122-.47793401.03444066-.71699742.05024834-.43828509.02898089-.87678018.05471721-1.31543747.07736589-.91719273.04735635-1.83508995.08094726-2.75329545.10060859-1.91650559.04103769-3.8334971.01922715-5.74882013-.05795974-1.30829653-.05272392-2.55878381,1.18757202-2.5,2.5.06268856,1.39960674,1.09838191,2.44351525,2.5,2.5,2.23459062.09005327,4.47146108.10375779,6.70681927.03241664,1.03767559-.03311728,2.07479203-.08393141,3.11073378-.15243137,1.36790408-.09045042,2.86089772-.08380129,3.90397701-1.12153242,1.28739054-1.28078972,1.01070791-3.00617909.29415754-4.47864547-.4623354-.95007044-.94536517-1.8907688-1.43167925-2.82873588-1.00896053-1.94600936-2.05919179-3.87023553-3.1454986-5.77411527-.64844271-1.1364717-2.29380368-1.62325846-3.42047458-.89687884-1.14781594.7400121-1.59064481,2.20456859-.89687884,3.42047458h0Z\"/><path class=\"cls-1\" d=\"M2.5,7.94737669c9.72256748-1.17986515,19.8490597,1.35309878,27.63025282,7.39316987,1.06546371.82705524,2.49680808,1.03872582,3.53553391,0,.86209969-.86209969,1.07268684-2.70287179,0-3.53553391C24.85807421,4.96811645,13.62465778,1.59736333,2.5,2.94737669c-1.34013459.16262969-2.5,1.03260113-2.5,2.5,0,1.22484458,1.15054569,2.66376066,2.5,2.5h0Z\"/><path class=\"cls-1\" d=\"M31.67651015,5.87556767l3.23044077,4.72780785c.53832689.78785103,1.08430945,1.57104389,1.61522038,2.36390393.03169418.04733195.339601.45417863.31806655.50995949-.07574581-.11681859-.11138202-.24310231-.10690863-.37885114-.02257928-.15861556-.01030339-.31603649.03682765-.47226278.04260484-.18653722.12772849-.34812004.25537095-.48474846.14776261-.17430604.15153003-.18994198.01130226-.04690784.3032156-.22125449.37262824-.28297079.20823793-.18514888-.16555998.08982608-.0809572.05997787.25380835-.08954461-.13774123-.04721718-.73222276.20760781-.90884538.23811029-.20814543.03594643-.41829528.06175938-.62742737.09102106-.10191528.01425995-.79365664.10676165-.29191996.04073249-.95707667.12595246-1.9155071.24141477-2.87523253.34530719-1.91956845.20779757-3.84371956.36879751-5.77075284.48848761-1.30272153.08091342-2.56306798,1.09192224-2.5,2.5.05755762,1.28505155,1.1021209,2.58682376,2.5,2.5,2.2482274-.1396398,4.49248148-.33623552,6.73005125-.59611777,1.26065161-.14641822,2.51989873-.3095204,3.77602118-.49068835,1.08014181-.15578662,2.08482216-.50328039,2.92978261-1.21818274,1.07662342-.91090727,1.5199098-2.45398409,1.10509485-3.80548223-.34613154-1.12772246-1.14688338-2.08506878-1.80293702-3.04521502-1.25628252-1.83859194-2.51256504-3.67718388-3.76884756-5.51577583-.73639787-1.07773145-2.23041818-1.66412393-3.42047458-.89687884-1.0724989.69145421-1.68593496,2.26567683-.89687884,3.42047458h0Z\"/><path class=\"cls-1\" d=\"M18.13115096,111.93484173c17.93173164,8.30654265,38.20684645,10.744127,57.62092077,7.08442672,5.42977261-1.02355332,10.75158343-2.55082959,15.90250276-4.54889712,1.25803463-.48799796,2.12981794-1.67901311,1.74609855-3.07529661-.33017284-1.20143757-1.80959083-2.23707219-3.07529661-1.74609855-17.42496475,6.75923149-36.79694297,7.88125407-54.89591774,3.21626534-5.06904446-1.30654004-10.02442181-3.04726923-14.77471199-5.2477532-1.22433603-.567151-2.69364743-.34577613-3.42047458.89687884-.63168368,1.07998835-.33391533,2.85033197.89687884,3.42047458h0Z\"/><path class=\"cls-1\" d=\"M83.89730522,109.71979716l3.95097962-.04725199c.35916259-.00429543.71835945-.01067638,1.0775399-.01288691.11711771-.00072078.23414181-.0021928.35121482.00253116.42047281.01696629-.00991302-.0149765-.18065348-.03029333.25013023.07701293.17775835.04458949-.21711564-.0972703l-.32091425-.24920178c.30673331.25445111-.30944828-.49491342-.12709709-.14306624-.05517846-.106467-.22098924-.60881204-.12077311-.21330616.0636923.2513635-.05280165-.71982158-.02709392-.1802211.0545994,1.14603094-.22417451,2.34697715-.36526235,3.48119945-.16395679,1.31806855-.32791338,2.63613713-.49186998,3.9542057-.07335643.58972198.33222419,1.3677581.73223305,1.76776695.4336057.4336057,1.14501564.76012615,1.76776695.73223305.64655933-.02895947,1.31713952-.24134366,1.76776695-.73223305.47869321-.52146274.64553787-1.07081309.73223305-1.76776695.182174-1.46452064.36434799-2.92904129.54652225-4.3935619.17678016-1.42115677.50968091-2.88768963.12961126-4.30524159-.26404007-.98479453-.93326485-1.8394107-1.82094987-2.33355842-.86327528-.48055955-1.84604335-.49830978-2.80459359-.48684594l-4.57954456.05476935c-1.30711599.01563254-2.5609728,1.13869995-2.5,2.5.06006858,1.34111213,1.09883162,2.51675736,2.5,2.5h0Z\"/><path class=\"cls-1\" d=\"M274.60047168,80.00096956c1.92552564-12.67811297,5.03840262-25.15009806,9.29623546-37.24609287.47311579-1.34406548-.54823835-2.64329644-1.74609855-3.07529661-2.79882312-1.00937661-6.05507867-.15657894-8.0695523,2.00813506-2.19011032,2.35344976,1.33777102,5.89720696,3.53553391,3.53553391.91002647-.97789666,1.97976064-1.16408327,3.20482033-.72227379l-1.74609855-3.07529661c-4.2578324,12.09599358-7.37070963,24.56797861-9.29623546,37.24609287-.20248923,1.33323662.33611516,2.68787355,1.74609855,3.07529661,1.18208789.3248039,2.8713306-.40313842,3.07529661-1.74609855h0Z\"/><path class=\"cls-1\" d=\"M281.80102598,45.93850386c1.08716281,1.36661658,2.17432562,2.73323317,3.26148843,4.09984975.22644293.24379107.49463243.4160978.8045685.5169202.29793293.15652643.61899908.22829738.96319845.21531285.61316822,0,1.34560469-.27235209,1.76776695-.73223305.43736004-.47643661.76205534-1.1019439.73223305-1.76776695l-.08930242-.66459903c-.11877984-.423512-.33309005-.79123464-.64293063-1.10316792-1.08716281-1.36661658-2.17432562-2.73323317-3.26148843-4.09984975-.22644293-.24379107-.49463243-.4160978-.8045685-.5169202-.29793293-.15652643-.61899908-.22829738-.96319845-.21531285-.61316822,0-1.34560469.27235209-1.76776695.73223305-.43736004.47643661-.76205534,1.1019439-.73223305,1.76776695l.08930242.66459903c.11877984.423512.33309005.79123464.64293063,1.10316792h0Z\"/><path class=\"cls-1\" d=\"M193.62649735,37.36472305c15.61498341,5.6386394,30.41179756,13.48388317,43.88511699,23.18216691,3.8282409,2.75562133,7.53276893,5.67199584,11.12558368,8.72790793,1.02782512.8742291,2.52668663,1.00884728,3.53553391,0,.89631605-.89631605,1.03309573-2.65682183,0-3.53553391-13.14343824-11.17931056-27.79172203-20.54401878-43.52405534-27.64236208-4.4907899-2.02622-9.05918385-3.88028937-13.69298117-5.55357403-1.27002261-.45861077-2.73742355.51644691-3.07529661,1.74609855-.38161263,1.38883698.47146962,2.61502248,1.74609855,3.07529661h0Z\"/><path class=\"cls-1\" d=\"M246.72692565,57.70385537l-.03461186,4.73921487c-.00503767.68978043-.01775689,1.37888953-.03260512,2.06806276-.01716116.19658612-.00426145.10798718.03869914-.26579681l-.03320004.15467405c-.23577925.49909133.31439196-.48910047.02074445-.03353081.16191144-.25119212.37999124-.34542788.58920453-.52844793.1971178-.07509033.18865145-.08134339-.02539905-.01875917.34771975-.03828424.42418866-.05078386.22940673-.03749888-3.10997199-.09812803-6.24375307.00957995-9.35611832.00928781-1.30769782-.00012274-2.56046782,1.14997424-2.5,2.5.06067315,1.35461011,1.09845683,2.49986845,2.5,2.5,1.81219144.0001701,3.62438288.0003402,5.43657432.00051027.86985191.00008164,1.73970383.00016327,2.60955574.0002449,1.03057398.00009671,2.0688534.03269574,3.03631059-.37557598,1.1468798-.48398896,1.97530058-1.47656531,2.28111617-2.68703215.21728947-.86006636.1945725-1.76102447.20099105-2.63988149l.03933166-5.38547144c.00955239-1.30795729-1.15671914-2.56016571-2.5-2.5-1.36268378.06103477-2.48976305,1.09831019-2.5,2.5h0Z\"/><path class=\"cls-1\" d=\"M365.55464125,45.21477472c10.15036804,11.40986687,19.48926717,23.50680195,27.95843859,36.21459953,1.77605691,2.66493268,6.10865324.16420857,4.31735343-2.52359574-8.70135709-13.05618687-18.31161685-25.50386834-28.74025811-37.2265377-2.14312926-2.40905743-5.66895006,1.13739482-3.53553391,3.53553391h0Z\"/><path class=\"cls-1\" d=\"M384.15050158,79.87512115c1.93097295,1.43162642,3.92447649,2.77619276,5.98252659,4.01860229,1.06983226.64583938,2.15586232,1.26502434,3.25695372,1.85600689,1.22587048.65795451,2.47773578,1.33632875,3.89852918,1.40386576,2.41423363.11475991,4.18300921-1.6723612,4.68899762-3.91322848.16162232-.71577561.21660026-1.45072029.35448528-2.17087449.02610677-.13635202.16184945-.99013595.26272721-.99787942-.15224754.33944588-.16961266.38835242-.05209536.14671963l.0799686-.14038425c.14830556-.2217954.11351628-.18193051-.10436784.11959468.07286704-.08048467.15108222-.15538692.23464554-.22470675.97896238-.87308058.95614595-2.6578095,0-3.53553391-1.04495057-.95924541-2.49130606-.93128712-3.53553391,0-1.26164881,1.12519245-1.6410219,2.76271481-1.87220983,4.3600034-.04588566.31702627-.09043699.63464694-.15429395.94867824-.02884614.14185755-.28453382.77239121-.23726529.86360426-.11732126-.22639223.28651554-.44325953-.0185002-.06025611l.21385789-.27515189c-.18588629.1815035-.12673454.14799894.17745523-.10051368-.38050723.23114719.48266034-.07562453.05722082-.00134374-.27170224.0474386.29162977.13723045.05731044-.02013561-.06519598-.04378484-.568272-.19622157-.28316311-.07629398-.25024011-.10526047-.49503871-.24648947-.73496606-.37262735-.46796903-.24602706-.93278694-.49812976-1.39514074-.75453921-.96679156-.53615758-1.9215745-1.09385219-2.86364145-1.67235142-1.88460682-1.15728888-3.71347908-2.40156354-5.48990465-3.71860829-1.05449411-.78180361-2.83665847-.20811023-3.42047458.89687884-.69064013,1.30717494-.22868365,2.58598076.89687884,3.42047458h0Z\"/><path class=\"cls-1\" d=\"M475.23144127,18.28608192c6.8076412-7.59088341,17.86526083-7.08949954,27.16821716-6.64123104,3.21647269.15498766,3.20843682-4.84539956,0-5-10.66368387-.51383597-22.96187272-.52691058-30.70375107,8.10569714-2.14294582,2.38949901,1.38172174,5.93714947,3.53553391,3.53553391h0Z\"/><path class=\"cls-1\" d=\"M473.01185093,108.99794765c9.37308422,3.73224284,19.31331098,5.85013726,29.38604923,6.37204925,3.21581031.16662499,3.20677219-4.83384331,0-5-9.63451186-.49920559-19.09616918-2.62541489-28.05685117-6.19344442-1.25483236-.49965827-2.74561658.54626452-3.07529661,1.74609855-.39098707,1.4229542.48664823,2.57379952,1.74609855,3.07529661h0Z\"/></svg>\n<figcaption>\n图2: 图 1 中的 SeqCst 操作构成的 bwcb。本图中只画出了部分箭头，传递闭包是完整的序。\n</figcaption>\n</figure>\n<p>第二步就是说明 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 添加 SeqCst 其他要求保证的序之后依旧不会成环。事实上，很大一块要添加的关系已经是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 的一个子序了。</p>\n<p>SeqCst 操作所形成的全序 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span> 需要兼容的序包括<sup>[3]</sup>：</p>\n<ul>\n<li>Strongly happens-before，这部分可以理解为 SeqCst 操作被其他例如 AcqRel-pair 同步构成的要求。</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo></mrow><annotation encoding=\"application/x-tex\">([F]; sb)?; cob; (sb; [F])?</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">([</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">]</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">)?</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">])?</span></span></span></span>，这部分可以理解为 SC 中“顺序一致”这一要求。</li>\n</ul>\n<h2>吸收 Strongly happens-before</h2>\n<p>首先处理 SeqCst 操作之间的 Strongly happens-before，其实这已经是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 的一个子序了，所以不需要额外处理：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">[</mo><mi>S</mi><mi>C</mi><mo stretchy=\"false\">]</mo><mo separator=\"true\">;</mo><mi>s</mi><mi>h</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">[</mo><mi>S</mi><mi>C</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">)</mo><mo>⊂</mo><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">\n([SC]; shb; [SC]) \\subset bwcb\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">([</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">SC</span><span class=\"mclose\">]</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">hb</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">SC</span><span class=\"mclose\">])</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⊂</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span></span></p>\n<details>\n<summary>证明</summary>\n<p>Strongly happens-before 是一个关系的传递闭包，所以可能有多个中间操作，每一跳如果是 A Strongly happens-before D，可能性包括：</p>\n<ol>\n<li>A Sequenced-before D</li>\n<li>A synchronize-with D，并且 A 和 D 都是 SeqCst 操作。</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∃</mi><mi>B</mi><mo separator=\"true\">,</mo><mi>C</mi><mo separator=\"true\">,</mo><mi>s</mi><mi mathvariant=\"normal\">.</mi><mi>t</mi><mi mathvariant=\"normal\">.</mi></mrow><annotation encoding=\"application/x-tex\">\\exists B,C, s.t.</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">∃</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord\">.</span><span class=\"mord mathnormal\">t</span><span class=\"mord\">.</span></span></span></span> A sequenced-before B, B simply happens-before C, C sequenced-before D。Simply happens-before 也是一个传递闭包，共两种情况：\n<ul>\n<li>B sequenced-before C</li>\n<li>B synchronize-with C</li>\n</ul>\n</li>\n</ol>\n<p>因为我们最后要进行线性化，所以如果一个传递闭包中的一个关系有一段是第二种情况的话，可以直接切开当成前中后三段单独的关系加到要进行全序化的关系中。把剩下的所有闭包都做好，可以发现最终要考虑的关系是：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><msup><mo stretchy=\"false\">)</mo><mo>∗</mo></msup></mrow><annotation encoding=\"application/x-tex\">\nsb; (sw^+; sb)^*\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0713em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8213em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7387em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">∗</span></span></span></span></span></span></span></span></span></span></span></span></p>\n<p>要证明：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi mathvariant=\"normal\">∀</mi><mi>A</mi><mo separator=\"true\">,</mo><mi>B</mi><mo>∈</mo><mi>S</mi><mi>e</mi><mi>q</mi><mi>C</mi><mi>s</mi><mi>t</mi><mo separator=\"true\">,</mo><mi>A</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><msup><mo stretchy=\"false\">)</mo><mo>∗</mo></msup></mrow></msub><mi>B</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\n\\forall A, B \\in SeqCst, A \\to_{sb; (sw^+; sb)^*} B \\implies end(A) \\prec begin(B)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">∀</span><span class=\"mord mathnormal\">A</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0385em;vertical-align:-0.3552em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">qC</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">t</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3448em;\"><span style=\"top:-2.5198em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span><span class=\"mpunct mtight\">;</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7027em;\"><span style=\"top:-2.786em;margin-right:0.0714em;\"><span class=\"pstrut\" style=\"height:2.5em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mpunct mtight\">;</span><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span><span class=\"mclose mtight\"><span class=\"mclose mtight\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6183em;\"><span style=\"top:-2.786em;margin-right:0.0714em;\"><span class=\"pstrut\" style=\"height:2.5em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mbin mtight\">∗</span></span></span></span></span></span></span></span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3552em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<h3>同步操作 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mo>−</mo><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mo>−</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\implies begin(-) \\prec end(-)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.549em;vertical-align:-0.024em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord\">−</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord\">−</span><span class=\"mclose\">)</span></span></span></span></h3>\n<p>首先，如果只有一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">sb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span></span></span></span>，根据两侧的操作都是 SeqCst，这是显然的。所以只需要考虑至少有一段 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup></mrow><annotation encoding=\"application/x-tex\">sw^+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7713em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span></span></span></span> 的情况，此时同样由于最两端的操作都是 SeqCst，只需证明：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi mathvariant=\"normal\">∀</mi><mi>A</mi><mo separator=\"true\">,</mo><mi>B</mi><mo separator=\"true\">,</mo><mi>A</mi><msub><mo>→</mo><mrow><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup><msup><mo stretchy=\"false\">)</mo><mo>∗</mo></msup></mrow></msub><mi>B</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\n\\forall A, B, A \\to_{sw^+ ; (sb; sw^+)^*} B \\implies begin(A) \\prec end(B)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0496em;vertical-align:-0.3552em;\"></span><span class=\"mord\">∀</span><span class=\"mord mathnormal\">A</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3448em;\"><span style=\"top:-2.5198em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7027em;\"><span style=\"top:-2.786em;margin-right:0.0714em;\"><span class=\"pstrut\" style=\"height:2.5em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mpunct mtight\">;</span><span class=\"mopen mtight\">(</span><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span><span class=\"mpunct mtight\">;</span><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7027em;\"><span style=\"top:-2.786em;margin-right:0.0714em;\"><span class=\"pstrut\" style=\"height:2.5em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mclose mtight\"><span class=\"mclose mtight\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6183em;\"><span style=\"top:-2.786em;margin-right:0.0714em;\"><span class=\"pstrut\" style=\"height:2.5em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mbin mtight\">∗</span></span></span></span></span></span></span></span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3552em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>特别地，这里 A 和 B 不需要是 SeqCst 操作。但是因为他们都参与了 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>w</mi></mrow><annotation encoding=\"application/x-tex\">sw</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span></span></span></span>，所以一定是 Acquire and/or Release 操作。我们可以对 Kleene star 的展开个数进行归纳</p>\n<h2><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup></mrow><annotation encoding=\"application/x-tex\">sw^+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7713em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span></span></span></span></h2>\n<p>首先讨论只有一段 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup></mrow><annotation encoding=\"application/x-tex\">sw^+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7713em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span></span></span></span> 的情况，这是归纳的 Base case，也会在归纳的后续步骤中用到。</p>\n<p>我们声称：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><msubsup><mo>→</mo><mrow><mi>s</mi><mi>w</mi></mrow><mo>+</mo></msubsup><mi>B</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\nA \\to_{sw}^+ B \\implies begin(A) \\prec end(B)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0683em;vertical-align:-0.247em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8213em;\"><span style=\"top:-2.453em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span></span></span></span><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.247em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>原因是，如果有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msubsup><mo>→</mo><mrow><mi>s</mi><mi>w</mi></mrow><mo>+</mo></msubsup><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{sw}^+ B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0183em;vertical-align:-0.247em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-2.453em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span></span></span></span><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.247em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span>，那么 A 和 B 是对同一个原子对象的访问，A 是 Release 操作，B 是 Acquire 操作，并且可能有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>k</mi><mo>≥</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">k \\geq 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8304em;vertical-align:-0.136em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≥</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0</span></span></span></span> 个对同一个原子对象的 Acquire-Release AMO 操作：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>M</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>M</mi><mi>k</mi></msub></mrow><annotation encoding=\"application/x-tex\">M_1, ..., M_k</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">...</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.03148em;\">k</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>，满足：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><msub><mi>M</mi><mn>1</mn></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><msub><mi>M</mi><mi>k</mi></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">\nA \\to_{rf} M_1 \\to_{rf} ... \\to_{rf} M_k \\to_{rf} B\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.653em;vertical-align:-0.2861em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.03148em;\">k</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span></span></p>\n<p>根据原子操作的原子性，一定有：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>M</mi><mn>1</mn></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>M</mi><mi>k</mi></msub></mrow><annotation encoding=\"application/x-tex\">A \\to_{co} M_1 \\to_{co} ... \\to_{co} M_k</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5169em;vertical-align:-0.15em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.03148em;\">k</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>。注意到 B 读取到的是 A 或者 A 在这一原子对象 Coherence 序之后的另一个写入的值，因此 B 完成一定晚于 A 开始的时间。</p>\n<p>另一种解释的方法是 B 读取的值依赖 A 写入的值，因此 B 完成时刻一定晚于 A 开始的时刻。<sup>[5]</sup></p>\n<h2>添加 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mi>s</mi><msup><mi>w</mi><mo>+</mo></msup></mrow><annotation encoding=\"application/x-tex\">sb; sw^+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9658em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span></span></span></span></h2>\n<p>下面讨论归纳中的一步。如果有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>C</mi><msubsup><mo>→</mo><mrow><mi>s</mi><mi>w</mi></mrow><mo>+</mo></msubsup><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">B \\to_{sb} C \\to_{sw}^+ D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0183em;vertical-align:-0.247em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-2.453em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span></span></span></span><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.247em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span>，并且如果有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(A) \\prec end(B)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span>，那么注意 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 必须是 Acquire 操作，因此 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">B \\to_{sb} C \\implies end(B) \\prec begin(C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span>。把他们串起来：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>C</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>D</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\nbegin(A) \\prec end(B) \\prec begin(C) \\prec end(D)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mclose\">)</span></span></span></span></span></p>\n</details>\n<h2>顺序一致性：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo></mrow><annotation encoding=\"application/x-tex\">([F]; sb)?; cob; (sb; [F])?</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">([</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">]</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">)?</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">])?</span></span></span></span></h2>\n<p>最后剩下的就是这些关系。抄袭一下 SC11 的论文，我们把它叫作 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> (Partial preserved SC)</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi><mo>:</mo><mo>=</mo><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo></mrow><annotation encoding=\"application/x-tex\">\nppsc := ([F]; sb)?; cob; (sb; [F])?\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">:=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">([</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">]</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">)?</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">])?</span></span></span></span></span></p>\n<p>需要证明把它加入 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 之后不会产生环。假设如果有环存在，事实上我们可以只考虑最多有一条 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边的环，如果有一个环中有多个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边，那么一定存在有一个环最多只有一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边，其他边都是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">[</mo><mi>F</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">?</mo></mrow><annotation encoding=\"application/x-tex\">([F]; sb)?; cob ;(sb; [F])?</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">([</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">]</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">)?</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">])?</span></span></span></span>。</p>\n<details>\n<summary>证明</summary>\n<p>归纳，每次通过 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 传递性消掉一条 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边。如果环中有至少两条 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">\nA \\to_{bwcb} B \\to ... \\to C \\to_{bwcb} D \\to ... \\to A\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span></span></p>\n<p>那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 不重叠，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 不重叠。这意味着 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><mo separator=\"true\">,</mo><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">C, D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 不能同时和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo separator=\"true\">,</mo><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A, B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 重叠。因此：</p>\n<ul>\n<li>如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 不重叠，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{bwcb} C \\to_{bwcb} D \\to ... \\to A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span>，或者 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C \\to_{bwcb} A \\to_{bwcb} B \\to ... \\to C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span>，这样环可以消掉一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span>。</li>\n<li>如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 不重叠，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{bwcb} B \\to_{bwcb} C \\to_{bwcb} D \\to ... \\to A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span>，或者 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C \\to_{bwcb} B \\to ... \\to C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n<li>如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 不重叠，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C \\to_{bwcb} D \\to_{bwcb} A \\to_{bwcb} B \\to ... \\to C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 或者 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{bwcb} D \\to ... \\to A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span></li>\n<li>如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 不重叠，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C \\to_{bwcb} D \\to_{bwcb} B \\to ... \\to C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 或者 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow></msub><mi>D</mi><mo>→</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{bwcb} B \\to_{bwcb} D \\to ... \\to A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal mtight\">c</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span></li>\n</ul>\n</details>\n<p>因此只需考虑两个情况：有一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边，或者没有。</p>\n<h3>有一条 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边</h3>\n<p>此时，成环等价于存在一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> 链，让链尾操作完全发生在链头操作之前。因此要证明不存在环，只需证明不存在这样的 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> 链即可，也就是只需证：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mtable rowspacing=\"0.25em\" columnalign=\"right left\" columnspacing=\"0em\"><mtr><mtd class =\"mtr-glue\"></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mrow></mrow><mi mathvariant=\"normal\">∀</mi><mi>A</mi><mo separator=\"true\">,</mo><msub><mi>M</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>M</mi><mi>k</mi></msub><mo separator=\"true\">,</mo><mi>B</mi><mo>∈</mo><mi>S</mi><mi>e</mi><mi>q</mi><mi>C</mi><mi>s</mi><mi>t</mi><mo separator=\"true\">,</mo></mrow></mstyle></mtd><mtd class =\"mtr-glue\"></mtd><mtd class =\"mml-eqn-num\"></mtd></mtr><mtr><mtd class =\"mtr-glue\"></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mrow></mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow></msub><msub><mi>M</mi><mn>1</mn></msub><msub><mo>→</mo><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow></msub><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><msub><mo>→</mo><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow></msub><msub><mi>M</mi><mi>k</mi></msub><msub><mo>→</mo><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow></msub><mi>B</mi></mrow></mstyle></mtd><mtd class =\"mtr-glue\"></mtd><mtd class =\"mml-eqn-num\"></mtd></mtr><mtr><mtd class =\"mtr-glue\"></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mrow></mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow></mstyle></mtd><mtd class =\"mtr-glue\"></mtd><mtd class =\"mml-eqn-num\"></mtd></mtr></mtable><annotation encoding=\"application/x-tex\">\n\\begin{align}\n&amp; \\forall A, M_1, ..., M_k, B \\in SeqCst,\\\\\n&amp; A \\to_{ppsc} M_1 \\to_{ppsc} ... \\to_{ppsc} M_k \\to_{ppsc} B \\\\\n\\implies &amp; begin(A) \\prec end(B)\n\\end{align}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:4.5em;vertical-align:-2em;\"></span><span class=\"mtable\"><span class=\"col-align-r\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.5em;\"><span style=\"top:-4.66em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"></span></span><span style=\"top:-3.16em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"></span></span><span style=\"top:-1.66em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2em;\"><span></span></span></span></span></span><span class=\"col-align-l\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.5em;\"><span style=\"top:-4.66em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"></span><span class=\"mord\">∀</span><span class=\"mord mathnormal\">A</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">...</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.03148em;\">k</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">qC</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">t</span><span class=\"mpunct\">,</span></span></span><span style=\"top:-3.16em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">pp</span><span class=\"mord mathnormal mtight\">sc</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">pp</span><span class=\"mord mathnormal mtight\">sc</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\">...</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">pp</span><span class=\"mord mathnormal mtight\">sc</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.03148em;\">k</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">pp</span><span class=\"mord mathnormal mtight\">sc</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span><span style=\"top:-1.66em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2em;\"><span></span></span></span></span></span></span></span><span class=\"tag\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.5em;\"><span style=\"top:-4.5em;\"><span class=\"pstrut\" style=\"height:2.84em;\"></span><span class=\"eqn-num\"></span></span><span style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:2.84em;\"></span><span class=\"eqn-num\"></span></span><span style=\"top:-1.5em;\"><span class=\"pstrut\" style=\"height:2.84em;\"></span><span class=\"eqn-num\"></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2em;\"><span></span></span></span></span></span></span></span></span></p>\n<p>看上去非常像归纳，但是其实归纳是证不出来的，因为每一段只能构成 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mo>−</mo><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mo>−</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(-) \\prec end(-)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord\">−</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord\">−</span><span class=\"mclose\">)</span></span></span></span> 的关系，这不是传递的。必须要考虑其中每个操作具体的类型。</p>\n<p>首先一个引理：</p>\n<blockquote>\n<p>如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{cob} B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 是一个 SeqCst 内存操作，或者 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>F</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{cob} B \\to_{sb} F</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>F</mi></mrow><annotation encoding=\"application/x-tex\">F</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span></span></span></span> 是一个 SeqCst Fence，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(A) \\prec end(B)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span>，或者对于 Fence 时 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>F</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(A) \\prec end(F)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">)</span></span></span></span></p>\n</blockquote>\n<details>\n<summary>证明</summary>\n<p>考虑 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub></mrow><annotation encoding=\"application/x-tex\">\\to_{cob}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5169em;vertical-align:-0.15em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 这一段，由于 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">cob</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span></span></span></span> 被定义为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mi>r</mi><mi>f</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi><msup><mo stretchy=\"false\">)</mo><mo>+</mo></msup></mrow><annotation encoding=\"application/x-tex\">(rf \\cup fr \\cup co)^+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0213em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span></span></span></span>，除了 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">cob</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span></span></span></span> 两端的操作，中间可能有其他对于同一个原子对象的 Load / Store / AMO 操作。我们再定义一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>f</mi></mrow><annotation encoding=\"application/x-tex\">rf</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span></span></span></span> 的扩展：Read after <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>a</mi><mo>:</mo><mo>=</mo><mi>c</mi><mi>o</mi><mo stretchy=\"false\">?</mo><mo separator=\"true\">;</mo><mi>r</mi><mi>f</mi><mo>⊇</mo><mi>r</mi><mi>f</mi></mrow><annotation encoding=\"application/x-tex\">ra := co?; rf \\supseteq rf</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">:=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mclose\">?</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⊇</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span></span></span></span>，可以理解为写入早于读取发生。我们允许这一链条中内存操作由 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>a</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">ra \\cup fr \\cup co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5556em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span> 相连。</p>\n<ul>\n<li>\n<p>首先，如果在这一链条中部（不在两端）存在 AMO 在链条中起的作用不只是其中读取一半或者写入一半产生的，那么存在另一个具有相同端点的链，其中这个 AMO 被去掉。这样我们可以把所有链条中的 AMO 都删去或者只当作普通的读取或写入。</p>\n<p>具体而言，如果有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{ra \\cup fr \\cup co} B \\to_{ra \\cup fr \\cup co} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 是 AMO，和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 的关联与和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span> 的关联并不同时是读取的那一半或者写入的那一半，那么有两种情况：</p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{ra} B \\to_{ra \\cup co} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2389em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{fr \\cup co} B \\to_{fr} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mbin mtight\">∪</span><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n</ul>\n<p>注意到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>f</mi><mi>r</mi><mo>:</mo><mo>=</mo><mi>r</mi><msup><mi>f</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">fr := rf^{-1}; co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">:=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0085em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">−</span><span class=\"mord mtight\">1</span></span></span></span></span></span></span></span></span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span>，并且根据原子操作的原子性：</p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{ra} B \\to_{ra} C \\implies A \\to_{co} B \\to_{ra} C \\implies A \\to_{ra} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{ra} B \\to_{co} C \\implies A \\to_{co} B \\to_{co} C \\implies A \\to_{co} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{fr} B \\to_{fr} C \\implies A \\to_{fr} B \\to_{co} C \\implies A \\to_{fr} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{co} B \\to_{fr} C \\implies A \\to_{co} B \\to_{co} C \\implies A \\to_{co} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7073em;vertical-align:-0.024em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n</ul>\n</li>\n<li>\n<p>随后，在链条中部的 Load 也可以被略掉。原因是在链条中部的读取只能构成如下 Pattern：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi>A</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><mi>C</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi></mrow><annotation encoding=\"application/x-tex\">\n... A \\to_{ra} B \\to_{fr} C ...\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\">...</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mord\">...</span></span></span></span></span></p>\n<p>由于 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>f</mi><mi>r</mi><mo>:</mo><mo>=</mo><mi>r</mi><msup><mi>f</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">fr := rf^{-1}; co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">:=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0085em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">−</span><span class=\"mord mtight\">1</span></span></span></span></span></span></span></span></span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span>，因此 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>a</mi><mo separator=\"true\">;</mo><mi>f</mi><mi>r</mi><mo>=</mo><mi>c</mi><mi>o</mi><mo separator=\"true\">;</mo><mi>c</mi><mi>o</mi><mo>=</mo><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">ra; fr = co; co = co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">a</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span>，所以 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{co} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span>。</p>\n</li>\n<li>\n<p>最后，多个连续的写入可以合并为一个：</p>\n<p>使用 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 表示写，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 表示读：</p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>B</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub></mrow><annotation encoding=\"application/x-tex\">W_A \\to_{co} W_B \\to_{co} W_C \\implies W_A \\to_{co} W_C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>R</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><msub><mi>W</mi><mi>B</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><msub><mi>R</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub></mrow><annotation encoding=\"application/x-tex\">R_A \\to_{fr} W_B \\to_{co} W_C \\implies R_A \\to_{fr} W_C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>B</mi></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><msub><mi>R</mi><mi>C</mi></msub><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub></mrow><annotation encoding=\"application/x-tex\">W_A \\to_{co} W_B \\to_{rf} R_C \\implies W_A \\to_{ra} W_C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟹</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n</ul>\n</li>\n</ul>\n<p>于是在考虑 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{cob} B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 的时候，事实上只有三种可能性。使用 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 表示写入，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 表示读取：</p>\n<ol>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>B</mi></msub></mrow><annotation encoding=\"application/x-tex\">W_A \\to_{co} W_B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>R</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><msub><mi>W</mi><mi>B</mi></msub></mrow><annotation encoding=\"application/x-tex\">R_A \\to_{fr} W_B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><msub><mi>R</mi><mi>B</mi></msub></mrow><annotation encoding=\"application/x-tex\">W_A \\to_{ra} R_B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>R</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>a</mi></mrow></msub><msub><mi>R</mi><mi>B</mi></msub></mrow><annotation encoding=\"application/x-tex\">R_A \\to_{fr} W_C \\to_{ra} R_B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">a</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span></li>\n</ol>\n<p>需要证明的是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(A) \\prec end(B)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span>（或者 Fence 的情况下 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>F</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(A) \\prec end(F)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">)</span></span></span></span>）。前两种情况比较自然，后两种情况需要略加说明。</p>\n<p><strong>对于第三种情况</strong>，注意到对于同一原子变量的所有写入，所有核心必须以相同的顺序观测。<sup>[6]</sup> 所以如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub><msub><mo>→</mo><mrow><mi>r</mi><mi>f</mi></mrow></msub><msub><mi>R</mi><mi>B</mi></msub></mrow><annotation encoding=\"application/x-tex\">W_A \\to_{co} W_C \\to_{rf} R_B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1514em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.05017em;\">B</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>，那么 B 完成时，C 已经部分可见，因此 A 也已经部分可见，因此一定晚于 A 开始执行。</p>\n<p><strong>对于第四种情况</strong>，需要用到 B 是一个 SeqCst 读取（或者随后 F 是一个 SeqCst Fence）。在 B (或者 F) 完成时，根据对 SeqCst 读取的额外要求，B 读到的值必须已经全局可见了，那么 C 也必须全局可见了。注意到，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>W</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>f</mi><mi>r</mi></mrow></msub><msub><mi>W</mi><mi>C</mi></msub></mrow><annotation encoding=\"application/x-tex\">W_A \\to_{fr} W_C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9694em;vertical-align:-0.2861em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.07153em;\">C</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>，因此 A 开始执行必须早于 C 全局可见的时刻。</p>\n</details>\n<p>利用这个引理，可以发现，如果我们把 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> 链条根据 Fence 划分开来，构成由 Fence 连接的内部无 Fence 段，我们可以根据这个划分出的段数进行归纳，如果把每段两侧的 Fence 状态都完全讨论清楚的话，是可以证明的整条链条的开始操作 A 和末尾操作 B 保证 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(A) \\prec end(B)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span></span></span></span> 的。</p>\n<details>\n<summary>证明</summary>\n<p>首先，注意到在没有 Fence 参与的情况下，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> 就是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">cob</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span></span></span></span> 关系，而 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">cob</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span></span></span></span> 传递。所以下述每段内只会写一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">cob</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">co</span><span class=\"mord mathnormal\">b</span></span></span></span>。</p>\n<p>考虑划分出的段数。如果只有一段，有四种可能性：</p>\n<ul>\n<li>两端均无 Fence，直接使用引理。</li>\n<li>开头有 Fence：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>F</mi><mi>A</mi></msub><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">F_A \\to_{sb} B \\to_{cob} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span>。使用引理，并且 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><msub><mi>F</mi><mi>A</mi></msub><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><msub><mi>F</mi><mi>A</mi></msub><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">begin(F_A) \\prec end(F_A) \\prec begin(B) \\prec end(C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3283em;\"><span style=\"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">A</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span></li>\n<li>末尾有 Fence：直接使用引理。</li>\n<li>开头末尾都有 Fence：上述两种情况的方法合并即可。</li>\n</ul>\n<p>接下来进行归纳。在链条末尾新加一段由 Fence 切分开的内部无 Fence 段，那么这一段一定由 Fence 开始：</p>\n<ul>\n<li>\n<p>如果目前处理这段结尾不是 Fence：已知 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><msubsup><mo>→</mo><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><mo>+</mo></msubsup><mi>F</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to_{ppsc}^+ F \\to_{sb} B \\to_{cob} C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.1544em;vertical-align:-0.3831em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-2.453em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">pp</span><span class=\"mord mathnormal mtight\">sc</span></span></span></span><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3831em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span>，根据归纳假设</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>A</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>F</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>b</mi><mi>e</mi><mi>g</mi><mi>i</mi><mi>n</mi><mo stretchy=\"false\">(</mo><mi>B</mi><mo stretchy=\"false\">)</mo><mo>≺</mo><mi>e</mi><mi>n</mi><mi>d</mi><mo stretchy=\"false\">(</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\nbegin(A) \\prec end(F) \\prec begin(B) \\prec end(C)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">A</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">in</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≺</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">d</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span></span></p>\n</li>\n<li>\n<p>如果目前处理这段结尾是 Fence，处理方法完全一样。</p>\n</li>\n</ul>\n</details>\n<h3>无 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 边</h3>\n<p>此时成环直接由 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mi>p</mi><mi>s</mi><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">ppsc</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">pp</span><span class=\"mord mathnormal\">sc</span></span></span></span> 成环。在讨论这样的环的存在性时，可以只考虑只有一个 Fence 的情况，因为如果有多于一个 Fence，由于 Fence 在一个时刻发生，所以两个 Fence 一定能比较先后，把环的其中一半换成 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi><mi>w</mi><mi>c</mi><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">bwcb</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\" style=\"margin-right:0.02691em;\">w</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">b</span></span></span></span> 即可。</p>\n<p>所以只需证明，不存在这样的环：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>F</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>A</mi><msub><mo>→</mo><mrow><mi>c</mi><mi>o</mi><mi>b</mi></mrow></msub><mi>B</mi><msub><mo>→</mo><mrow><mi>s</mi><mi>b</mi></mrow></msub><mi>F</mi></mrow><annotation encoding=\"application/x-tex\">\nF \\to_{sb} A \\to_{cob} B \\to_{sb} F\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">co</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">F</span></span></span></span></span></p>\n<p>其中 A 和 B 无须是 SeqCst 操作，但 F 一定是 SeqCst Fence。使用前述引理，这一性质是显然的。</p>\n<hr />\n<div class=\"footnotes\">\n<ul>\n<li>\n<p>[1] 这里依赖不是指 C++ 的没人用的 consume，而是说为了完成这个读一定需要某个操作带有的值。</p>\n</li>\n<li>\n<p>[2] 这一条是没办法完全在局部实现的，在总线上需要灌一个 Barrier 下去。不过目前唯一不支持 MCA 的（还勉强活着的）架构是 POWER，其实现仅会在 SMT 共享 Store buffer 时发生 Non-MCA 的现象，外面的缓存还是 Fully coherent and MCA 的，所以这个 Barrier 直接做成清空核心 Store Buffer 即可，代价和复杂度也不是特别高。 <!-- 不要求和其他更弱的访存操作也保持原子性。也就是说只有 SeqCst 的写入操作的生效顺序需要所有线程同意。很遗憾，这部分看上去还是需要整个缓存系统配合实现，可能需要 LLC 上有一把大锁。 --></p>\n</li>\n<li>\n<p>[3] N4917 [atomics.order] &amp; [intro.race]</p>\n</li>\n<li>\n<p>[4] 特别注意，如果把条件扩张成 Coherence-ordered before 之后并不能保证这件事情！核心是因为 Coherence-ordered before 是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>f</mi><mo>∪</mo><mi>f</mi><mi>r</mi><mo>∪</mo><mi>c</mi><mi>o</mi></mrow><annotation encoding=\"application/x-tex\">rf \\cup fr \\cup co</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">co</span></span></span></span> 的一个传递闭包。C++ 标准做了这个闭包，结果导致了 C++ 目前标准过强，在 x86 上目前的编译是 Unsound 的，将会在下篇文章中具体讨论。<a href=\"https://stackoverflow.com/questions/79622116/in-the-independent-read-independent-write-iriw-scenario-is-changing-loads-to\">搞清楚这个细节</a>是这篇文章拖了一周的原因…</p>\n</li>\n<li>\n<p>[5] 注意，AMO 操作可能实际执行的操作不依赖之前的值（例如 exchange），但是为了保证这样的 AMO 链对于其他内存操作的排序总都有如同 carry dependency 的排序能力，内存模型通常禁止这样的 AMO 提前做 forward。其中一个例子是 RVWMO 不允许 <code>amoswap</code> 做 local-bypass。</p>\n<p>另一方面，通常所有的内存模型（语言或者硬件）都会要求对同一对象（地址）的操作有一个统一的修改顺序（Write coherence）。如果有些线程（核心）对部分距离较近的修改可见了，那么硬件必须要求这个线程（核心）之后不会忽然看到一个更老的来自其他写入突然可见。（比如如果一个 Store 从一个做 bypass 的 Store buffer 进入了一个不做 bypass 的 Store buffer，就会有这个问题）。 如果某个有 Store 成分的内存访问在其他核心变得可见的时刻一定是在自己的执行时段内（a.k.a. 上篇博客提到的“有效的回应”），那么也可以保证这样的 AMO 链能保证头尾两个访问的相互顺序（因为最后一个读取的完成时刻，一定在最早一个写入在读取发生的缓存结构处生效的时刻之后）。</p>\n<p>Write coherence 规则的存在导致硬件实现不能干这种事情：对于一个还没有 Commit 的写先去请求 Shared Grant，然后假装已经写入了。当这个 Grant 被 Revoke 的时候，把这个还没有发出的写直接丢掉。这种实现下，这个被丢掉的写 Effectively 被别的核心观测到的时候是在它还没开始执行时就发生了。</p>\n</li>\n<li>\n<p>[6] 见上方 [5] 中第二段开始的对于 Write coherence 的说明。</p>\n</li>\n</ul>\n</div>","plain":"昨天 前天 上周的文章最后的命题伪证了：\n这是一个错误结论：SeqCst ld/st/AMO 存在全序 + 所有 SeqCst 操作等待/阻拦前后所有类型其他访存 \\implies C++11 SeqCst Semantics\n\n问题是 SeqCst ld/st/AMO 的全序可能和 Fence 不兼容，所以如何在 Non-MCA 系统上实现 std::memory_order_seq_cst 还是一个非常 Nontrivial 的事情，需要把 SeqCst ld/st/AMO 的实现方法也考虑进来。本文在上篇文章提出的设计的基础上细化一下 SeqCst ld/st/AMO 的实现，并且给出一个比较详细的证明，说明这一设计符合 C++11 SeqCst Semantics。这显然不是唯一的设计，也不是所有系统下都最自然的设计，不过可以认为是一个 MCA 系统不再等待所有 ProbeAck 之后得到的 Non-MCA 系统一个比较直观的设计。\n- co: Coherence order，和 C++ 标准中的 Modification order 基本同义。\n- rf: Read-from，W \\to_{rf} R 表示 R 读到了 W 的值，可以理解为 “W 早于 R”。\n- fr: From-read，部分文献称为 Read-before (rb)，R \\to_{fr} W 表示 R 读到了 W 在 co 序之前某个操作写入的值，可以理解为“R 早于 W”\n- sw: Synchronize-with，在本文中狭义解释为一个 Release 操作写入的值被一个 Acquire 操作读到。标准库中有别的 sw 操作，这里不做讨论。\n- cob: Coherence-ordered before\n- bwcb, ra, ppsc 都是本文中定义的关系，分别指 Base wall-clock before, read-after 和 partial preserved SC\n分号 (;) 表示关系连接，即：\n\na ; b := \\{ (X, Y) \\in dom(a) \\times codom(b) \\mid exists Z, XaZ \\land ZbY \\}\n\n中括号 ([S]) 表示 S 类型的操作上的 Identity 关系，即：\n\n[S] := \\{ (X, X) \\mid X \\in S \\}\n\n中括号可以用于固定一个序的两端，例如 [F]; sb; [F] 表示 sb 关系中两端都是 Fence (F) 的子关系。\n\nThe Hardware\n实现很重要的一个属性是希望尽量在核心“局部”可以实现这个排序，不需要通过总线上或者其他信道上和别的核心进行访存之外的通信。很遗憾，SeqCst 的语义并不能完全在局部完成，需要的硬件功能集合包括：\n- 所有 SeqCst 操作会等待同一线程 sequenced-before 的所有操作完成，然后才开始本操作。等待本操作完成之后，才开始 sequenced-after 的其他操作。这里“完成”指的是全局可见之后，在硬件实现上需要核心发出的写操作对应的回应蕴含它已经全局可见了。\n- Acquire / Release 操作也要进行类似的等待。不过 Acquire 只阻止 R \\rightarrow *，Release 只阻止 * \\rightarrow W。\n- 此外，Acquire / Release AMO 弱于 Relaxed AMO + Acquire / Release Fence，原因是 Acquire / Release AMO 只控制其绑定的 AMO 操作和其他访存操作的顺序。\n- 额外的，所有 SeqCst 操作结束时必须保证，该操作读取到的值必须全局可见。（对于 Fence，本线程之前所有 Load / AMO 读到的值都全局可见）。[2]\n可以画一张图，横轴方向 Wall clock，每个线程一条时间轴，Fence 标记为一个点，其他访存标记为核心视角开始执行到收到回应结束执行的时刻。\n在这个图中，并且如果 A \\rightarrow_{rf \\cup fr \\cup co} B，那么在图上，A 的前边沿一定早于 B 的后边沿[4]。把某操作 X 的前边沿记作 start(X)，后边沿记作 end(X)，在时间上 A 时刻早于 B 时刻记作 A \\prec B。那么：\n\nM \\to_{rf \\cup fr \\cup co} N \\implies start(M) \\prec end(N)\n\n这一事实将用于排序各个两侧的同步操作。\n\nSketch proof\n证明的思路大概是首先构造一个关系，可以包含 SeqCst 需要保证的所有序。如果这个关系不包含环，那么做传递闭包后是一个偏序，之后可以全序化。\n证明大概分作两步：\n第一步是根据 SeqCst 的执行时序，有一个很自然的基础序：如果两个 SeqCst 操作不互相重叠，那么在时间上完全更早发生的操作，应该在所有需要保证的序中都早于另一个操作。把这个序称作 Base wall-clock before bwcb，这是一个偏序，并且限制到同一个线程内是一个全序。\n第二步就是说明 bwcb 添加 SeqCst 其他要求保证的序之后依旧不会成环。事实上，很大一块要添加的关系已经是 bwcb 的一个子序了。\nSeqCst 操作所形成的全序 S 需要兼容的序包括[3]：\n- Strongly happens-before，这部分可以理解为 SeqCst 操作被其他例如 AcqRel-pair 同步构成的要求。\n- ([F]; sb)?; cob; (sb; [F])?，这部分可以理解为 SC 中“顺序一致”这一要求。\n\n吸收 Strongly happens-before\n首先处理 SeqCst 操作之间的 Strongly happens-before，其实这已经是 bwcb 的一个子序了，所以不需要额外处理：\n\n([SC]; shb; [SC]) \\subset bwcb\n\nStrongly happens-before 是一个关系的传递闭包，所以可能有多个中间操作，每一跳如果是 A Strongly happens-before D，可能性包括：\n- A Sequenced-before D\n- A synchronize-with D，并且 A 和 D 都是 SeqCst 操作。\n- \\exists B,C, s.t. A sequenced-before B, B simply happens-before C, C sequenced-before D。Simply happens-before 也是一个传递闭包，共两种情况：- B sequenced-before C\n- B synchronize-with C\n\n因为我们最后要进行线性化，所以如果一个传递闭包中的一个关系有一段是第二种情况的话，可以直接切开当成前中后三段单独的关系加到要进行全序化的关系中。把剩下的所有闭包都做好，可以发现最终要考虑的关系是：\n\nsb; (sw^+; sb)^*\n\n要证明：\n\n\\forall A, B \\in SeqCst, A \\to_{sb; (sw^+; sb)^*} B \\implies end(A) \\prec begin(B)\n\n\n同步操作 \\implies begin(-) \\prec end(-)\n首先，如果只有一个 sb，根据两侧的操作都是 SeqCst，这是显然的。所以只需要考虑至少有一段 sw^+ 的情况，此时同样由于最两端的操作都是 SeqCst，只需证明：\n\n\\forall A, B, A \\to_{sw^+ ; (sb; sw^+)^*} B \\implies begin(A) \\prec end(B)\n\n特别地，这里 A 和 B 不需要是 SeqCst 操作。但是因为他们都参与了 sw，所以一定是 Acquire and/or Release 操作。我们可以对 Kleene star 的展开个数进行归纳\n\nsw^+\n首先讨论只有一段 sw^+ 的情况，这是归纳的 Base case，也会在归纳的后续步骤中用到。\n我们声称：\n\nA \\to_{sw}^+ B \\implies begin(A) \\prec end(B)\n\n原因是，如果有 A \\to_{sw}^+ B，那么 A 和 B 是对同一个原子对象的访问，A 是 Release 操作，B 是 Acquire 操作，并且可能有 k \\geq 0 个对同一个原子对象的 Acquire-Release AMO 操作：M_1, ..., M_k，满足：\n\nA \\to_{rf} M_1 \\to_{rf} ... \\to_{rf} M_k \\to_{rf} B\n\n根据原子操作的原子性，一定有：A \\to_{co} M_1 \\to_{co} ... \\to_{co} M_k。注意到 B 读取到的是 A 或者 A 在这一原子对象 Coherence 序之后的另一个写入的值，因此 B 完成一定晚于 A 开始的时间。\n另一种解释的方法是 B 读取的值依赖 A 写入的值，因此 B 完成时刻一定晚于 A 开始的时刻。[5]\n\n添加 sb; sw^+\n下面讨论归纳中的一步。如果有 B \\to_{sb} C \\to_{sw}^+ D，并且如果有 begin(A) \\prec end(B)，那么注意 C 必须是 Acquire 操作，因此 B \\to_{sb} C \\implies end(B) \\prec begin(C)。把他们串起来：\n\nbegin(A) \\prec end(B) \\prec begin(C) \\prec end(D)\n\n\n顺序一致性：([F]; sb)?; cob; (sb; [F])?\n最后剩下的就是这些关系。抄袭一下 SC11 的论文，我们把它叫作 ppsc (Partial preserved SC)\n\nppsc := ([F]; sb)?; cob; (sb; [F])?\n\n需要证明把它加入 bwcb 之后不会产生环。假设如果有环存在，事实上我们可以只考虑最多有一条 bwcb 边的环，如果有一个环中有多个 bwcb 边，那么一定存在有一个环最多只有一个 bwcb 边，其他边都是 ([F]; sb)?; cob ;(sb; [F])?。\n归纳，每次通过 bwcb 传递性消掉一条 bwcb 边。如果环中有至少两条 bwcb 边：\n\nA \\to_{bwcb} B \\to ... \\to C \\to_{bwcb} D \\to ... \\to A\n\n那么 A 和 B 不重叠，C 和 D 不重叠。这意味着 C, D 不能同时和 A, B 重叠。因此：\n- 如果 C 和 A 不重叠，那么 A \\to_{bwcb} C \\to_{bwcb} D \\to ... \\to A，或者 C \\to_{bwcb} A \\to_{bwcb} B \\to ... \\to C，这样环可以消掉一个 bwcb。\n- 如果 B 和 C 不重叠，那么 A \\to_{bwcb} B \\to_{bwcb} C \\to_{bwcb} D \\to ... \\to A，或者 C \\to_{bwcb} B \\to ... \\to C\n- 如果 D 和 A 不重叠，那么 C \\to_{bwcb} D \\to_{bwcb} A \\to_{bwcb} B \\to ... \\to C 或者 A \\to_{bwcb} D \\to ... \\to A\n- 如果 D 和 B 不重叠，那么 C \\to_{bwcb} D \\to_{bwcb} B \\to ... \\to C 或者 A \\to_{bwcb} B \\to_{bwcb} D \\to ... \\to A\n因此只需考虑两个情况：有一个 bwcb 边，或者没有。\n\n有一条 bwcb 边\n此时，成环等价于存在一个 ppsc 链，让链尾操作完全发生在链头操作之前。因此要证明不存在环，只需证明不存在这样的 ppsc 链即可，也就是只需证：\n\n\\begin{align}\n& \\forall A, M_1, ..., M_k, B \\in SeqCst,\\\\\n& A \\to_{ppsc} M_1 \\to_{ppsc} ... \\to_{ppsc} M_k \\to_{ppsc} B \\\\\n\\implies & begin(A) \\prec end(B)\n\\end{align}\n\n看上去非常像归纳，但是其实归纳是证不出来的，因为每一段只能构成 begin(-) \\prec end(-) 的关系，这不是传递的。必须要考虑其中每个操作具体的类型。\n首先一个引理：\n如果 A \\to_{cob} B，其中 B 是一个 SeqCst 内存操作，或者 A \\to_{cob} B \\to_{sb} F，其中 F 是一个 SeqCst Fence，那么 begin(A) \\prec end(B)，或者对于 Fence 时 begin(A) \\prec end(F)\n\n考虑 \\to_{cob} 这一段，由于 cob 被定义为 (rf \\cup fr \\cup co)^+，除了 cob 两端的操作，中间可能有其他对于同一个原子对象的 Load / Store / AMO 操作。我们再定义一个 rf 的扩展：Read after ra := co?; rf \\supseteq rf，可以理解为写入早于读取发生。我们允许这一链条中内存操作由 ra \\cup fr \\cup co 相连。\n- 首先，如果在这一链条中部（不在两端）存在 AMO 在链条中起的作用不只是其中读取一半或者写入一半产生的，那么存在另一个具有相同端点的链，其中这个 AMO 被去掉。这样我们可以把所有链条中的 AMO 都删去或者只当作普通的读取或写入。\n具体而言，如果有 A \\to_{ra \\cup fr \\cup co} B \\to_{ra \\cup fr \\cup co} C，其中 B 是 AMO，和 A 的关联与和 C 的关联并不同时是读取的那一半或者写入的那一半，那么有两种情况：\n- A \\to_{ra} B \\to_{ra \\cup co} C\n- A \\to_{fr \\cup co} B \\to_{fr} C\n注意到 fr := rf^{-1}; co，并且根据原子操作的原子性：\n- A \\to_{ra} B \\to_{ra} C \\implies A \\to_{co} B \\to_{ra} C \\implies A \\to_{ra} C\n- A \\to_{ra} B \\to_{co} C \\implies A \\to_{co} B \\to_{co} C \\implies A \\to_{co} C\n- A \\to_{fr} B \\to_{fr} C \\implies A \\to_{fr} B \\to_{co} C \\implies A \\to_{fr} C\n- A \\to_{co} B \\to_{fr} C \\implies A \\to_{co} B \\to_{co} C \\implies A \\to_{co} C\n\n- 随后，在链条中部的 Load 也可以被略掉。原因是在链条中部的读取只能构成如下 Pattern：\n\n... A \\to_{ra} B \\to_{fr} C ...\n\n由于 fr := rf^{-1}; co，因此 ra; fr = co; co = co，所以 A \\to_{co} C。\n\n- 最后，多个连续的写入可以合并为一个：\n使用 W 表示写，R 表示读：\n- W_A \\to_{co} W_B \\to_{co} W_C \\implies W_A \\to_{co} W_C\n- R_A \\to_{fr} W_B \\to_{co} W_C \\implies R_A \\to_{fr} W_C\n- W_A \\to_{co} W_B \\to_{rf} R_C \\implies W_A \\to_{ra} W_C\n\n于是在考虑 A \\to_{cob} B 的时候，事实上只有三种可能性。使用 W 表示写入，R 表示读取：\n- W_A \\to_{co} W_B\n- R_A \\to_{fr} W_B\n- W_A \\to_{ra} R_B\n- R_A \\to_{fr} W_C \\to_{ra} R_B\n需要证明的是 begin(A) \\prec end(B)（或者 Fence 的情况下 begin(A) \\prec end(F)）。前两种情况比较自然，后两种情况需要略加说明。\n对于第三种情况，注意到对于同一原子变量的所有写入，所有核心必须以相同的顺序观测。[6] 所以如果 W_A \\to_{co} W_C \\to_{rf} R_B，那么 B 完成时，C 已经部分可见，因此 A 也已经部分可见，因此一定晚于 A 开始执行。\n对于第四种情况，需要用到 B 是一个 SeqCst 读取（或者随后 F 是一个 SeqCst Fence）。在 B (或者 F) 完成时，根据对 SeqCst 读取的额外要求，B 读到的值必须已经全局可见了，那么 C 也必须全局可见了。注意到，W_A \\to_{fr} W_C，因此 A 开始执行必须早于 C 全局可见的时刻。\n利用这个引理，可以发现，如果我们把 ppsc 链条根据 Fence 划分开来，构成由 Fence 连接的内部无 Fence 段，我们可以根据这个划分出的段数进行归纳，如果把每段两侧的 Fence 状态都完全讨论清楚的话，是可以证明的整条链条的开始操作 A 和末尾操作 B 保证 begin(A) \\prec end(B) 的。\n首先，注意到在没有 Fence 参与的情况下，ppsc 就是 cob 关系，而 cob 传递。所以下述每段内只会写一个 cob。\n考虑划分出的段数。如果只有一段，有四种可能性：\n- 两端均无 Fence，直接使用引理。\n- 开头有 Fence：F_A \\to_{sb} B \\to_{cob} C。使用引理，并且 begin(F_A) \\prec end(F_A) \\prec begin(B) \\prec end(C)\n- 末尾有 Fence：直接使用引理。\n- 开头末尾都有 Fence：上述两种情况的方法合并即可。\n接下来进行归纳。在链条末尾新加一段由 Fence 切分开的内部无 Fence 段，那么这一段一定由 Fence 开始：\n- 如果目前处理这段结尾不是 Fence：已知 A \\to_{ppsc}^+ F \\to_{sb} B \\to_{cob} C，根据归纳假设\n\nbegin(A) \\prec end(F) \\prec begin(B) \\prec end(C)\n\n\n- 如果目前处理这段结尾是 Fence，处理方法完全一样。\n\n\n无 bwcb 边\n此时成环直接由 ppsc 成环。在讨论这样的环的存在性时，可以只考虑只有一个 Fence 的情况，因为如果有多于一个 Fence，由于 Fence 在一个时刻发生，所以两个 Fence 一定能比较先后，把环的其中一半换成 bwcb 即可。\n所以只需证明，不存在这样的环：\n\nF \\to_{sb} A \\to_{cob} B \\to_{sb} F\n\n其中 A 和 B 无须是 SeqCst 操作，但 F 一定是 SeqCst Fence。使用前述引理，这一性质是显然的。\n---\n- [1] 这里依赖不是指 C++ 的没人用的 consume，而是说为了完成这个读一定需要某个操作带有的值。\n\n- [2] 这一条是没办法完全在局部实现的，在总线上需要灌一个 Barrier 下去。不过目前唯一不支持 MCA 的（还勉强活着的）架构是 POWER，其实现仅会在 SMT 共享 Store buffer 时发生 Non-MCA 的现象，外面的缓存还是 Fully coherent and MCA 的，所以这个 Barrier 直接做成清空核心 Store Buffer 即可，代价和复杂度也不是特别高。 \n\n- [3] N4917 [atomics.order] & [intro.race]\n\n- [4] 特别注意，如果把条件扩张成 Coherence-ordered before 之后并不能保证这件事情！核心是因为 Coherence-ordered before 是 rf \\cup fr \\cup co 的一个传递闭包。C++ 标准做了这个闭包，结果导致了 C++ 目前标准过强，在 x86 上目前的编译是 Unsound 的，将会在下篇文章中具体讨论。搞清楚这个细节是这篇文章拖了一周的原因…\n\n- [5] 注意，AMO 操作可能实际执行的操作不依赖之前的值（例如 exchange），但是为了保证这样的 AMO 链对于其他内存操作的排序总都有如同 carry dependency 的排序能力，内存模型通常禁止这样的 AMO 提前做 forward。其中一个例子是 RVWMO 不允许 amoswap 做 local-bypass。\n另一方面，通常所有的内存模型（语言或者硬件）都会要求对同一对象（地址）的操作有一个统一的修改顺序（Write coherence）。如果有些线程（核心）对部分距离较近的修改可见了，那么硬件必须要求这个线程（核心）之后不会忽然看到一个更老的来自其他写入突然可见。（比如如果一个 Store 从一个做 bypass 的 Store buffer 进入了一个不做 bypass 的 Store buffer，就会有这个问题）。 如果某个有 Store 成分的内存访问在其他核心变得可见的时刻一定是在自己的执行时段内（a.k.a. 上篇博客提到的“有效的回应”），那么也可以保证这样的 AMO 链能保证头尾两个访问的相互顺序（因为最后一个读取的完成时刻，一定在最早一个写入在读取发生的缓存结构处生效的时刻之后）。\nWrite coherence 规则的存在导致硬件实现不能干这种事情：对于一个还没有 Commit 的写先去请求 Shared Grant，然后假装已经写入了。当这个 Grant 被 Revoke 的时候，把这个还没有发出的写直接丢掉。这种实现下，这个被丢掉的写 Effectively 被别的核心观测到的时候是在它还没开始执行时就发生了。\n\n- [6] 见上方 [5] 中第二段开始的对于 Write coherence 的说明。\n\n"},{"metadata":{"id":"seqcst-fences","lang":"zh-CN","title":"硬件视角下的 C++ SeqCst Fences","tags":["微架构","Fences"],"publish_time":"2025-05-12T23:56:43+08:00","update_time":"2025-05-22T10:41:22+08:00","title_outline":{"groups":[{"chars":[{"char":"硬","components":[["M 145 -759C 128 -566 89 -347 16 -196L 29 -187C 169 -334 253 -521 284 -743L 284 -759Z",[0.232,0.748]],["M 24 -759L 32 -731L 412 -731C 426 -731 437 -736 440 -747C 398 -786 327 -842 327 -842L 265 -759Z",[0.801,0.061]],["M 217 -485L 230 -485L 162 -511L 97 -414L 97 41L 119 41C 180 41 217 14 217 5Z",[0.02,0.773]],["M 158 -485L 158 -457L 337 -457L 337 -485Z",[0.705,0.008]],["M 158 -101L 158 -73L 337 -73L 337 -101Z",[0.842,0.0]],["M 276 -485L 276 -1L 297 -1C 338 -1 398 -26 399 -33L 399 -440C 417 -443 429 -451 435 -459L 322 -545L 266 -485Z",[0.009,0.755]],["M 612 -759L 612 -358C 612 -147 569 -19 316 85L 322 94C 705 17 747 -147 747 -360L 747 -759Z",[0.155,0.743]],["M 433 -759L 441 -731L 957 -731C 972 -731 983 -736 986 -747C 942 -789 866 -850 866 -850L 800 -759Z",[0.81,0.084]],["M 436 -614L 436 -216L 458 -216C 521 -216 558 -236 558 -245L 558 -586L 807 -586L 807 -231L 829 -231C 895 -231 935 -253 935 -258L 935 -577C 958 -581 967 -588 974 -596L 862 -682L 803 -614L 569 -614L 436 -664ZM 498 -464L 498 -436L 863 -436L 863 -464ZM 498 -307L 498 -279L 863 -279L 863 -307Z",[0.306,0.034]],["M 517 -231L 506 -224C 568 -24 697 50 893 95C 905 30 937 -15 990 -32L 989 -44C 785 -51 594 -86 517 -231Z",[-0.626,0.269]]],"bbox":{"top":-850,"bottom":95,"left":16,"right":990},"hadv":1000}],"text":"硬","hadv":1000,"breakAfter":true},{"chars":[{"char":"件","components":[["M 192 -854C 160 -664 87 -465 14 -339L 25 -332C 162 -431 264 -572 336 -767C 360 -765 373 -773 378 -785Z",[0.321,0.659]],["M 138 -522L 138 93L 165 93C 222 93 281 63 283 53L 283 -527C 303 -531 311 -538 314 -547L 191 -592Z",[0.011,0.78]],["M 389 -800C 377 -650 343 -483 305 -372L 317 -365C 412 -452 481 -574 530 -723C 553 -723 566 -731 570 -744Z",[0.235,0.644]],["M 306 -324L 314 -296L 960 -296C 975 -296 986 -301 989 -312C 941 -357 858 -425 858 -425L 785 -324Z",[0.87,0.063]],["M 403 -595L 403 -567L 932 -567C 946 -567 957 -572 960 -583C 914 -626 835 -691 835 -691L 765 -595Z",[0.804,0.019]],["M 567 -842L 567 94L 598 94C 655 94 718 66 718 54L 718 -795C 747 -799 753 -810 756 -824Z",[0.009,0.825]]],"bbox":{"top":-854,"bottom":94,"left":14,"right":989},"hadv":1000}],"text":"件","hadv":1000,"breakAfter":true},{"chars":[{"char":"视","components":[["M 234 -637L 247 -637C 217 -497 127 -324 8 -200L 16 -192C 180 -279 314 -435 380 -577C 405 -580 416 -583 425 -593L 306 -707Z",[0.403,0.64]],["M 327 -637L 33 -637L 42 -609L 327 -609Z",[0.75,0.004]],["M 132 -855L 124 -851C 140 -809 153 -753 149 -697C 256 -588 419 -791 132 -855Z",[-0.059,0.355]],["M 285 51L 285 -459L 152 -350L 152 92L 177 92C 243 92 285 59 285 51Z",[0.03,0.736]],["M 267 -427L 257 -422C 281 -377 306 -312 310 -254C 406 -171 518 -357 267 -427Z",[-0.216,0.385]],["M 765 -651L 596 -666C 596 -287 623 -73 306 78L 314 92C 742 -28 723 -243 729 -623C 751 -626 762 -636 765 -651Z",[0.218,0.723]],["M 428 -820L 428 -229L 450 -229C 514 -229 553 -251 553 -260L 553 -741L 779 -741L 779 -240L 802 -240C 868 -240 910 -264 910 -271L 910 -730C 933 -734 944 -742 951 -751L 837 -840L 775 -769L 564 -769Z",[0.075,0.018]],["M 802 -326L 653 -339L 653 -30C 653 46 668 69 757 69L 824 69C 944 69 987 42 987 -5C 987 -27 982 -41 953 -54L 950 -188L 939 -188C 921 -129 905 -77 896 -60C 890 -50 886 -48 876 -47C 868 -47 854 -47 838 -47L 792 -47C 774 -47 771 -51 771 -63L 771 -301C 791 -304 800 -313 802 -326Z",[-0.212,0.334]]],"bbox":{"top":-855,"bottom":92,"left":8,"right":987},"hadv":1000}],"text":"视","hadv":1000,"breakAfter":true},{"chars":[{"char":"角","components":[["M 184 -589L 184 -358C 184 -201 167 -38 28 89L 34 97C 302 -13 326 -204 326 -358L 326 -579L 347 -579L 207 -626Z",[0.133,0.748]],["M 504 -806L 308 -856C 258 -716 144 -557 29 -472L 35 -464C 207 -526 367 -656 463 -792C 492 -790 500 -795 504 -806Z",[0.496,0.521]],["M 759 -238L 265 -238L 265 -210L 759 -210Z",[0.917,0.004]],["M 759 -411L 265 -411L 265 -383L 759 -383Z",[0.867,0.005]],["M 759 -579L 265 -579L 265 -551L 759 -551Z",[0.762,0.015]],["M 619 -728L 326 -728L 306 -700L 619 -700Z",[0.627,0.041]],["M 589 22L 589 -571L 454 -561L 454 58L 479 58C 547 58 589 30 589 22Z",[0.002,0.798]],["M 567 -728L 579 -728C 562 -688 522 -610 488 -568L 499 -568C 576 -593 664 -640 727 -679C 748 -681 758 -684 767 -693L 641 -801Z",[0.373,0.358]],["M 712 -579L 722 -579L 722 -81C 722 -69 718 -62 703 -62C 683 -62 592 -67 592 -67L 592 -54C 640 -45 658 -29 673 -8C 687 13 692 47 695 94C 846 81 867 29 867 -65L 867 -531C 885 -535 896 -543 902 -550L 774 -648Z",[0.05,0.746]]],"bbox":{"top":-856,"bottom":97,"left":28,"right":902},"hadv":1000}],"text":"角","hadv":1000,"breakAfter":true},{"chars":[{"char":"下","components":[["M 831 -861L 747 -753L 25 -753L 33 -725L 952 -725C 968 -725 980 -730 983 -741C 926 -789 831 -861 831 -861Z",[0.83,0.048]],["M 557 52L 557 -753L 402 -753L 402 95L 431 95C 508 95 557 62 557 52Z",[0.002,0.818]],["M 540 -554L 533 -547C 630 -467 743 -346 805 -235C 979 -151 1056 -488 540 -554Z",[-0.44,0.388]]],"bbox":{"top":-861,"bottom":95,"left":25,"right":1056},"hadv":1000}],"text":"下","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708}],"text":"C","hadv":708,"breakAfter":false},{"chars":[{"char":"+","components":[["M 579 -340L 579 -395L 36 -395L 36 -340Z",[0.871,0.002]],["M 279 -87L 338 -87L 338 -642L 279 -642Z",[-0.006,0.909]]],"bbox":{"top":-642,"bottom":-87,"left":36,"right":579},"hadv":615}],"text":"+","hadv":615,"breakAfter":true},{"chars":[{"char":"+","components":[["M 579 -340L 579 -395L 36 -395L 36 -340Z",[0.871,0.002]],["M 279 -87L 338 -87L 338 -642L 279 -642Z",[-0.006,0.909]]],"bbox":{"top":-642,"bottom":-87,"left":36,"right":579},"hadv":615}],"text":"+","hadv":615,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"q","components":[["M 261 17C 335 17 400 -16 448 -84L 455 -84L 440 -95C 408 -66 380 -54 343 -54C 264 -54 208 -109 208 -270C 208 -434 264 -494 342 -494C 377 -494 409 -482 442 -450L 460 -461L 455 -465C 416 -530 356 -563 289 -563C 146 -563 35 -450 35 -267C 35 -86 133 17 261 17Z",[0.019,0.474]],["M 344 259L 646 259L 646 230L 544 219L 444 219L 344 230Z",[0.875,0.002]],["M 420 259L 586 259C 583 180 582 101 582 22L 582 -398L 586 -552L 571 -561L 420 -478L 420 -77L 424 -63L 424 22C 424 101 423 180 420 259Z",[0.007,0.803]]],"bbox":{"top":-563,"bottom":259,"left":35,"right":646},"hadv":657},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"SeqCst","hadv":3481,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Fences","hadv":3617,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>考虑典中典 Store buffering litmus test，在 C++ 中的实现。</p>\n<pre><code>x.store(1, relaxed)  |  y.store(1, relaxed)\na = y.load(relaxed)  |  b = x.load(relaxed)\n</code></pre>\n<p>在 Sequentially consistent 的内存模型 (SC) 下，是肯定不会发生 <code>a == b == 0</code> 的，但是现实是一个远比 SC 更丑恶的地方。Store buffer 导致弱内存序中，特别是在 TSO 上也会发生 <code>a == b == 0</code> 的情况，而 TSO 中所有 Acquire 和 Release 语义全都是 No-op，所以两个线程两个访存之间分别加上 AcqRel Fence 也无法避免这个行为。</p>\n<p>一种恢复 SC 中这段代码的行为的方法是把所有访问的 relaxed 都换成 <code>seq_cst</code>，C++ 标准要求所有 SeqCst Atomic 操作都在同一个全序内。另一种方法在两侧两个访存中间分别加上一个 SeqCst Fence，因此一种常见的定义/解释 SeqCst Fence 的方法是：</p>\n<blockquote>\n<p>它是 AcqRel Fence，并且额外保证 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 顺序。</p>\n</blockquote>\n<p>这是一个来自 ISA 和硬件视角的定义方法。但是 Virtually 没有任何一个语言的内存模型是直接这么定义的。这个刻画准确吗？它 Sound &amp; complete 吗？</p>\n<p>作为一个工科猪还是以 C++ 为例。这句话的前一半首先是对的，标准里说使用 <code>std::memory_order_seq_cst</code> 的 Fence 是一个…</p>\n<blockquote>\n<p>…sequentially consistent acquire and release atomic fence<sup>[1]</sup>…</p>\n</blockquote>\n<p>…That’s a long name. Anyway，这意味着需要仔细看的只有后半部分。先说结论，在 <a href=\"/post/mca\">MCA</a> 系统中，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 是一个充分条件，但不必要。在更弱的系统中（e.g. IRIW 允许不同观测顺序），这个“先后”就很难定义了。</p>\n<h2>In MCA Environment</h2>\n<p>在前一篇博文中简要提及了，如果满足 MCA，那么存在一个 Global total order <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>G</mi></mrow><annotation encoding=\"application/x-tex\">G</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">G</span></span></span></span> 对所有线程的所有内存操作排序。这一排序中的一部分可以使用访存观测到，这个可以被观测结果确认的子序就是如下三者的并的闭包：</p>\n<ul>\n<li><code>rf</code> / Read from: [atomic.order] <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">¶</mi><mn>3.1</mn></mrow><annotation encoding=\"application/x-tex\">\\P 3.1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">¶3.1</span></span></span></span></li>\n<li><code>mo</code> / Modification: [atomic.order] <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">¶</mi><mn>3.2</mn></mrow><annotation encoding=\"application/x-tex\">\\P 3.2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">¶3.2</span></span></span></span></li>\n<li><code>rb</code> / Read before 或者部分文献叫作 <code>fr</code> / From read: [atomic.order] <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">¶</mi><mn>3.3</mn></mrow><annotation encoding=\"application/x-tex\">\\P 3.3</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">¶3.3</span></span></span></span></li>\n</ul>\n<p>C++ 标准把这个叫作 <em>Coherence-ordered before</em><sup>[2]</sup>。C++ 对于 SeqCst 操作的要求是所有 SeqCst 操作构成一个全序 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span>，然后 $S + $sequenced-before 和 Coherence-ordered before 兼容 ([atomics.order] <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">¶</mi></mrow><annotation encoding=\"application/x-tex\">\\P</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">¶</span></span></span></span> 4)。但是如果保持 SeqCst Fence 保持 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span>，那么它会在 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>G</mi></mrow><annotation encoding=\"application/x-tex\">G</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">G</span></span></span></span> 中保证有一个位置正好可以把这个 Fence 插入进去。这个时候注意到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span> 和 Coherence-ordered before 都是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>G</mi></mrow><annotation encoding=\"application/x-tex\">G</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">G</span></span></span></span> 的一个子序，一定兼容。</p>\n<figure>\n<svg class=\"inline-svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 333.81818182 101.45454545\"><defs><style>.cls-1{fill:#231f20;}.cls-2{fill:#ed1c24;}</style></defs><path class=\"cls-1\" d=\"M32.69598586,52.22019527c-1.38301334-.0123821-2.86089079-.00341099-4.12894488-.27793462-1.1675919-.25277436-2.13185397-.67090319-2.78090367-1.29164451-.07623533-.07291031-.55060832-.60475731-.37685777-.37355586-.17704037-.23557906-.33306296-.50128649-.45819123-.76702518-.12671998-.26911904-.00580825-.03305764.00922281.01380909-.03860572-.12037234-.06867907-.24241798-.10433309-.36340661-.11582415-.39303862.00136787.32717675-.02724791-.0851087-.01196918-.1724475-.01165274-.34420737-.00139331-.51672165.01813381-.3049235.00601267-.03674933-.00501615.01808567.03372986-.16770385.08337223-.33294463.13388999-.49597507.0011042-.00356348.16176441-.37568061.06650555-.17656566-.09848506.2058585.10591671-.16760787.10248513-.16267484.09881484-.14205016.17934791-.29747437.27780832-.44041178-.03117643.04525958-.17267156.20949679.01119614-.017842.2253143-.27858444.48250856-.53494777.74437899-.7785343.74798144-.69575707,1.789463-1.33073585,2.89597554-1.91220463,1.17534199-.61763844,2.45063054-1.14375663,3.81242601-1.30738824.31099036-.03736821,1.081459-.04580153,1.57174038-.00198307.29726871.02656812.0181346.0021175-.0350012-.00732657.16709643.02969881.33420572.0638503.49915587.10422653.32866836.0804509.6599926.17770926.97325267.30626035-.31473832-.12915771.23729386.13263201.32220525.18001381.11029161.06154434.21840587.12687003.32520422.19422675.04309682.02718076.46465225.32388895.25962745.16614771-.079674-.0612993.30839073.28405581.40159339.37927418.03699368.03779375.37393349.41864167.2097712.21362481-.12399905-.15485831.13788413.21147659.16175556.25016739.06518825.10565709.12447689.21358266.1849638.3219664.3424344.61359267-.02044435-.14536678.07838103.19699663.03086269.10691845.05652423.21587464.08836274.32242259.13307052.44532208.01931217-.16302119.00986607.10810106-.00593493.1703446-.05958085.80881632.02230897.33863528-.05140344.29513954-.132037.583845-.23270668.86575278.15081776-.42233869-.15611422.24301714-.24446168.39758718-.01792554.03136198-.23734515.31062187-.06538325.10065143.19149826-.23382489-.24916213.23629574-.24333671.23012697-.03073291.03254428-.30570674.23154273-.08098147.07538364.23122789-.16067769-.15178297.074341-.19476441.09629757-.33772753.17252421.33745764-.18359877.00717978-.0002047-.10260398.05697313-.60974472.1177988-.08436536.05917159-1.34170958.1497217-2.5,1.04184118-2.5,2.5,0,1.23528695,1.14945026,2.65070817,2.5,2.5,2.04215251-.2278843,3.67577246-1.15197574,4.85446336-2.85574942.91059133-1.31624122,1.38434019-3.0455821,1.23745779-4.64125895-.35427175-3.84867916-3.72038253-6.68933394-7.41172068-7.27079987-6.76810669-1.0661238-19.07375367,5.50559237-14.791933,13.73276968,2.30367924,4.42633615,7.56054511,5.03281384,12.00636448,5.07261721,1.35101965.01209566,2.5-1.15767647,2.5-2.5,0-1.36556845-1.14428351-2.48786229-2.5-2.5h0Z\"/><path class=\"cls-1\" d=\"M47.72306277,51.75668575c10.542117-.41197666,21.09059019-.63528841,31.64069739-.66983527,3.21677299-.01053349,3.22301127-5.01055391,0-5-10.55010721.03454686-21.09858039.25785861-31.64069739.66983527-3.2069467.12532466-3.22310496,5.12595611,0,5h0Z\"/><path class=\"cls-2\" d=\"M91.85900578,49.73371439c-1.23261258.10980078-2.47395992.21706211-3.7114164.12426726-.13537282-.01015139-.27236668-.01873319-.40694183-.0370577.12663565.01724342.34821361.07302557-.13900776-.03648799-.26530094-.05963214-.52508528-.12898179-.78660506-.203085.00147923.00041915-.42066907-.14445136-.19014446-.05451911.23720713.09253924-.18795718-.09422977-.23652403-.12041951-.11739767-.06330686-.67879234-.43654143-.34945875-.17962942-.21173816-.16517621-.39223957-.36132175-.58207646-.54971099-.19551797-.19402701-.00284583.02527453.02989101.06826603-.06789063-.08915706-.12901335-.18475028-.18870502-.27946649-.09320446-.14789287-.31383458-.73392153-.18306304-.29616252-.02832537-.09481944-.04897017-.22569202-.09243752-.31328172-.13287788-.26775805-.0203134.32196063-.0129013.02363801.00247913-.09978026.00612132-.22674335-.0069069-.32549875.04549515.34485845-.04783023.22103835.00043085.00916697-.00359965.01580285.12119537-.40202439.04807175-.20605088-.07130031.19108699.10312931-.19456257.09850208-.18652278.06191095-.10757011.12582847-.2138318.19380373-.3176489.0441269-.06739403.32157542-.39390929.11163687-.16444441-.16568016.18109003.27971512-.26343395.36281081-.3500042.07066099-.07361561.36503547-.30365824-.03270345-.0017595.08172306-.06203087.16687645-.11999763.25207734-.1770769.17133398-.11478307.34794855-.22061441.52958757-.31825892.16363891-.08796811.71221708-.28175105.25305063-.13248071.23272686-.07565713.46111904-.15761199.69823643-.21976576.23868925-.06256579.47874731-.10451675.72023039-.15249574-.44034079.08748897-.03667685.01154025.17530047.00035076.24637085-.01300501.49327565-.01323323.73971602-.0027729.20462017.00868524.76376625.11733448.27885073.0080457.47880334.10791124.94596118.20799443,1.40964042.37404739.05879076.02105417.50968042.21047668.24988642.09290644-.23609089-.10684335.11576968.06100943.13127543.06907245.24495633.12737775.4888856.25368605.72627991.39501623.23817488.14179488.46683783.29555258.69635756.45052704.36663997.24755969-.08846662-.09863818.25130459.18672807.42874923.36009691.83854082.73969139,1.22444202,1.14553097.22080372.232212.43424601.47170206.6404799.7169413.07729226.09191067.15306312.1850642.22848011.27850934.27354614.33893635-.31920164-.45708818.11890828.15954114.07177119.10101624.14561085.20038609.21423872.30361685.17026156.2561092.14752393.52345725.13345339.0570066-.01088429-.36082366-.04102251-.6015973.11436562-.97044407.18447054-.19457246.21331499-.22582593.08653335-.09376042-.10092249.09662925-.09761872.10110628.00991132.01343111.23207124-.19522653-.10323347.04761265-.10459724.04998327.06553665-.11392127.33119283-.08720741-.00242464-.00819993-.32585443.07716903-.65113201.13732972-.98204879.18773757-.81961711.12485052-1.5128721.33528881-2.28196612.66002956-1.20964447.5107579-1.56321987,2.38692818-.89687884,3.42047458.81132964,1.25843495,2.12612018,1.4434045,3.42047458.89687884-.36036536.15215996.049892.01933324.10417536.01362484.20266494-.02131208.40916133-.08223007.61163987-.11441546.37032169-.05886524.746148-.0977417,1.11178426-.18311199.90773897-.21194269,1.80282062-.66802996,2.47228892-1.32502487,1.67083207-1.63970149,1.48150462-3.8538417.16435995-5.62377102-1.92941334-2.59267285-4.41099304-4.80390041-7.56374385-5.74825545-2.76178575-.82724784-6.10033126-.45107717-8.45926586,1.27248067-1.41794952,1.03602619-2.6529931,2.4678259-3.07992122,4.21458604-.40925846,1.6744654-.06432033,3.52568474.9231653,4.94204063,1.15881164,1.66208969,2.80221678,2.82849054,4.77209532,3.33700448,1.96327543.50680938,3.98574997.39795938,5.98200122.22013389,1.29906094-.11571998,2.56418697-1.06693908,2.5-2.5-.05621405-1.25505454-1.10502901-2.62426362-2.5-2.5h0Z\"/><path class=\"cls-1\" d=\"M101.9980981,51.02648585c5.43887666-.53974709,10.89992668-.80286929,16.3654993-.78851637,1.30779651.00343435,2.56036171-1.15234323,2.5-2.5-.06080017-1.35744591-1.09839871-2.49631931-2.5-2.5-5.4655741-.01435292-10.92662411.24876942-16.3654993.78851637-1.29745092.12875735-2.56460646,1.05757357-2.5,2.5.05570978,1.24379609,1.10632794,2.63830621,2.5,2.5h0Z\"/><path class=\"cls-1\" d=\"M129.15062465,50.771595c.22211143.17127687-.26058312-.20872918-.32548622-.26069565-.20615114-.16506064-.41102545-.33174691-.61456936-.50001213-.47493609-.3926191-.94274286-.79393298-1.40304597-1.20360937-.82199101-.73158383-1.62004346-1.49005272-2.39264763-2.27360414-.17858503-.18111546-.35800925-.36187725-.5297582-.54953312-.0813295-.08886202-.17246387-.17781473-.24335276-.27542289.13359429.18394833.02299189.06368962.04104542.00972038.02674642-.07995575-.07891048-.14394624.01265595.06011507-.02891923-.06444826-.04067212-.3783314-.03271636-.10678833.00962504.32851861.03629096-.11547248.02630068-.11351342.00784353-.00153809-.11130325.40532491.03108532-.00218793.17024142-.48722706.05172681-.11047181.00843225-.03723828.05787468-.09789606.12198387-.19519079.17729928-.29413305.13674556-.24459574-.00332963.02178767-.04217469.0579414.08236267-.07665628.1561631-.16279015.23811972-.24023002.08169682-.07719439.16522282-.15384536.25315861-.22399489-.0543876.04338694-.28280261.16861031-.04981119.05733056.23597523-.11270486.45384351-.28002718.68838723-.40047166.12526797-.06432845.61794384-.28622386.23313366-.1251574.23855159-.09984835.48281248-.1886949.72745752-.27234853.53152799-.18175003,1.07476543-.32972385,1.62597783-.43814332.05438016-.01069618.57986856-.09900667.3056667-.05982744-.24306257.0347299.17576237-.01617184.18050428-.0165333.25714338-.01960113.51415874-.03601309.77214012-.03882012.25795801-.00280678.51461111.00959029.77207719.02290904.00448064.00023178.42496245.04111217.18038541.01076382-.21201956-.02630846.20938038.0406306.24880509.04864861.43704808.08888474.85057932.22787194,1.27181907.37027779.27099302.0916129-.05085614-.01686877-.08837338-.03680461.0973368.05172267.19868534.09629261.29651481.14727048.22878443.11921708.44491891.25523185.66447639.39004537.02472261.01518027.32877627.2202478.10351727.06065164-.24270234-.17195478.11986721.10283342.17237161.14951168.16369795.14553324.31984396.29860305.46804867.45989723.07416195.08071195.14510871.16365238.21651117.24680167-.03791757-.0441556-.1859021-.30421318-.06155192-.06748016.05475208.10423488.13290105.20816829.19744169.30701244.05914294.09057757.19131879.33991494.08403496.09179138.04962955.11478208.0629171.2513592.11502435.3630494.13570732.29088426.0147015-.23429444.01231115.08412077-.002472.32929126.02104825-.0694217.03517333-.11776303-.03949334.13516108-.06846461.27119018-.11870705.40337719.19770521-.5201591-.2577713.24386449-.09042034.06060909.20871995-.22855595-.5287691.45523897-.07722403.10000315-.23920532.18818564-.51791185.33098626-.78983672.4652283.33866199-.16718837-.30093603.1006918-.42586369.13923088-.58639022.18089621-1.18806353.30511303-1.78845177.42917062-1.28278416.26506034-2.14311394,1.84847792-1.74609855,3.07529661.43937264,1.35770701,1.70094083,2.03008024,3.07529661,1.74609855,1.44937343-.29948251,2.97243092-.66712802,4.19854986-1.53767155,1.48713994-1.05586824,2.5673428-2.56825935,2.70910771-4.42493183.26050283-3.41176412-2.73601906-6.10996984-5.62737203-7.27382313-2.83150186-1.13976149-6.16163908-.82928208-8.94851138.29098609-1.60949008.64698354-3.06319331,1.47182334-4.10794094,2.89594227-.99316998,1.35381229-1.4372696,3.28358025-.84030553,4.89579688.6371902,1.72085505,2.13319427,2.99846433,3.44446317,4.22178932,1.34903774,1.25856075,2.77298972,2.42059235,4.23332985,3.546705,1.04006447.80202532,2.84474293.19280877,3.42047458-.89687884.70058664-1.32600071.21348352-2.56424043-.89687884-3.42047458h0Z\"/><path class=\"cls-1\" d=\"M144.54045366,47.65878135c11.72140841-.50897927,23.45604478-.63695134,35.18576512-.38371837,3.21875384.06948969,3.21808674-4.93052472,0-5-11.72972072-.25323297-23.46435709-.12526088-35.18576512.38371837-3.20519852.13917949-3.22255524,5.13993317,0,5h0Z\"/><path class=\"cls-1\" d=\"M184.1690338,45.04305376l1.12858347.4812888.17901894.23414723c-.01681689.00563791-.13646609-.23267813-.15822481-.26773413-.23577657-.37986536.10771213.13768856.07188966.17408302-.00003659.00003717-.07150935-.25800146-.08328964-.29366542-.13315613-.40312028.05993026.15268663.01726841.21144121.01578987-.02174606-.01390133-.25580176-.01409521-.30779014.00001405.003768.02652256-.29332616.01197516-.31013418-.05961336.3793624-.07238709.4715532-.03832121.27657242.01291767-.07781822.02875305-.15505744.04750612-.23171768.04752411-.20161069.15768294-.40534409.19174655-.60645185-.01376357.08125856-.26723628.5061711-.05142997.16017418.05653643-.09064346.10299031-.18815079.15904361-.27932484.04430695-.07206791.15839294-.19638879.17822508-.267501-.02008143.07200607-.38598439.42090716-.08961614.13101959.07623764-.07457055.14500834-.15554911.22216024-.22967679.07120905-.06841778.43202589-.29588852.1235214-.12002453-.31271166.1782623.04113495-.01344213.11972721-.06234668.10537364-.06556944.21269048-.12717177.32232039-.18534091.07551312-.04006693.43470004-.22633615.12036601-.07208578-.31078888.15251069.0478556-.01331518.13342653-.04262508.26503373-.09077981.53548299-.16383168.80956953-.22161277.05008533-.01055865.36529395-.05581943.36980718-.06779574-.03033462.08049589-.55182982.05553852-.00715914.01267531.50664027-.03987038,1.01570429-.03668273,1.52247184-.00070115.12645094.00897829.25265346.02006215.37875195.03307871l.09436971.00975397c.24204514.02926965.25056495.02985202.02555943.00174712l-.16237039-.02059217c.07714586.01211761.15404233.02562992.23068941.04053695.12897729.02624714.25811751.05115749.38624097.08148048.20737219.04907879.41324286.10531135.61633606.16988997.08722499.02773539.54597742.25115088.60337723.21804364-.10788209.06222457-.47735759-.22368056-.16060818-.05671818.09327495.04916633.18817082.09455334.28057096.14539624.14156785.07789729.50880261.41715089.65344446.41692738-.06507114.00010055-.43925687-.40028581-.15453281-.10393526.06864259.07144555.14525179.13518293.21414159.20673041.03909805.0406064.1611716.20899874.19621902.21910267-.0670877-.01934091-.31761141-.50665255-.13356696-.15404023.04293328.08225623.09670103.17239963.14465077.25018705.17138109.27802639-.15367737.00567448-.07927528-.19847868-.0086099.02362484.0836887.2822612.08342273.28149107.14330283.41494495.00388764-.46088556-.01028261-.12911791-.00493595.11556512-.00542799.24007117.00036103.3555386.01685962.3362809.12815075-.45891207.01533307-.14369095-.03797359.10610108-.07157112.2275763-.094515.33795777-.06766859.32554902.2203484-.39578242.05011118-.10602972-.1205836.20523962-.24883565.41449223-.36537046.62168755-.16723543.29733949.29124387-.32071336.05817922-.06775009-.10426266.11316442-.20063494.23364303-.30694765.34526283-.16956808.17803286-.3479105.3480087-.53310011.50970796-.06989231.06102683-.1888302.1874545-.27901302.23388798.40909921-.21063764.1580512-.11717647.03847853-.03213564-.47879005.34051849-.96800046.66107816-1.48086185.94835546-.54225403.30374147-1.10206946.56672046-1.66838317.82165879-.33219541.14954493.39491235-.15097157.05273821-.02450052-.15396292.05690627-.30535233.12135047-.45888151.1796109-.3079737.1168682-.61817432.22782079-.92992824.33417694-1.18696731.40493884-2.3966089.73861709-3.60764739,1.06273048-1.26311408.33805052-2.159809,1.79688845-1.74609855,3.07529661.41962858,1.29669581,1.7215784,2.1083977,3.07529661,1.74609855,2.85482088-.76404317,5.77301315-1.61865621,8.31222413-3.1737549,2.8187299-1.72628553,5.46024023-4.5039973,4.73131223-8.07872675-.58412583-2.86460639-3.56632397-4.64837715-6.25130445-5.12824091-3.07482621-.54953758-6.68377408-.26561404-8.9818391,2.10835131-1.22006218,1.2603583-1.98921378,3.01464615-1.98262219,4.77992204.00775528,2.07692121,1.37398035,4.99274506,3.85884917,4.76822943,1.29886602-.11735659,2.56423962-1.06576364,2.5-2.5-.05615078-1.25364195-1.10518576-2.62602581-2.5-2.5h0Z\"/><path class=\"cls-1\" d=\"M203.17790087,48.77785694c11.266269-.50897728,22.54582957-.64870038,33.82124946-.41895336,3.21874954.06558497,3.2184192-4.93442176,0-5-11.27541978-.22974702-22.55498035-.09002392-33.82124946.41895336-3.20445877.14476813-3.22229899,5.1455741,0,5h0Z\"/><path class=\"cls-2\" d=\"M245.83767931,45.18478867c-.20238015.06200967-.40482717.11322117-.61095195.1608954-.46729678.10808023.30955487.0120719-.1700705.01288156-.21111874.00035639-.42028883.00072608-.63142652-.00525835-.04886955-.00138514-.39812346-.0433848-.08663408-.00056064.31949827.04392523-.12946811-.03323454-.18662908-.04618866-.20415566-.04626682-.40463276-.13225342-.60839715-.17225055-.26101449-.05123482.05639962.03887511.10642417.06066572-.09646937-.04202189-.19101875-.08906969-.28465862-.13696115-.22008189-.11255937-.41821268-.2557212-.63290818-.37584082.03308521.01851079.29441756.26275915.08811524.07165538-.10315447-.09555495-.21133785-.18441977-.31148313-.28357189-.07777758-.07700624-.14962897-.15862703-.2257047-.23720033.04311012.04452542.17443397.29663741.05066873.05765296-.05483272-.10587922-.29531867-.59982257-.23369468-.39921693.08063765.26250116.00832351-.09292449-.01409188-.12017362.03058612.03718181.00173956.41977193.02085307.13115571.0198375-.29954846-.03081825.11223297-.03988005.13671746.08727448-.23581093.09156627-.1956151-.00815049.00294558-.02593819.05164933-.26794589.26516396-.06323416.09489995.21599072-.17964504-.07476667.02201286-.10184245.04404249.16589895-.13498015.36530115-.24182354.55176349-.34515306.20071941-.11123019.40782375-.21167054.61508398-.30999528.11575174-.0549129.23251292-.10754626.34912741-.16057135.38823095-.17653022-.28566657.11038588.11021782-.04816346.99104068-.39690588,2.01566312-.70873086,3.05915624-.93399325.29219193-.06307646.58597535-.11856961.88081375-.16771835.12631652-.02105661.25280139-.04193057.37961862-.05979864-.05514338.0077695-.32589578.03904087-.02934041.00779809.55235061-.05819137,1.10539962-.09981659,1.66081695-.11293626.51211913-.01209691,1.02505467-.00346025,1.53643732.02668685.13686203.00806831.72757342.06953961.30304761.00396618.1175708.01816031.2343638.04164129.35008146.06901724.04865848.0115114.49216081.09614048.26092393.06116598-.19031312-.0287848.01218173.01889526.0758535.05723768-.00630582-.00379729-.36314483-.30251453-.15260497-.12070737.0652668.05635974.11917556.13567548.18756047.18672534-.00139426-.00104082-.29473578-.38057276-.12486715-.1543339.01501732.02000075.14632286.21091124.13519514.22935337-.01621669.02687616-.13648984-.48236788-.07320128-.18638677.03174505.14846181.2157197.4665336.16146893.61538911-.00752899.02065835.01580862-.50197831-.0411327-.20675146-.01689777.08761082-.01724395.28264799.00025608.3700711.05625565.28103057.04121923-.20647899.04180306-.20408472.02953849.12113622-.07481188.33520364-.10397507.44943207-.02270281.08892397-.05614268.17514279-.08669827.26154696.08227611-.23265791.12496066-.2516677-.01698551-.02948273-.05647881.08840493-.12939966.18842954-.17405271.28276549-.14099876.29788005.2224312-.21244692-.00891587.02293505-.18221104.18538896-.35671506.37537259-.54420205.55628079-.01741594.01680482-.29653526.26381592-.09237085.09130468.19581951-.16546011-.16011543.11314843-.19997057.14038847-.46808997.31992837-.96575612.58786477-1.47655088.83253406-1.18259062.56645767-1.58697471,2.35008257-.89687884,3.42047458.78308487,1.21462513,2.15555227,1.50277317,3.42047458.89687884,2.71463265-1.30030161,5.14518383-3.71015249,5.14254353-6.90613031-.00122652-1.48465547-.53570806-3.01345297-1.58747035-4.0813454-1.27692453-1.29650784-3.01298526-1.59334765-4.75518611-1.6714804-3.0219483-.13552578-6.12590649.41397142-8.91626288,1.57785386-1.5309826.63858644-3.22441763,1.36202477-4.09385422,2.87668873-.93189809,1.62347947-.76584203,3.63274266.21253084,5.20137324,1.88124885,3.01621656,5.86153385,4.31305638,9.21264043,3.28627085,1.24886117-.38265347,2.17016307-1.76489331,1.74609855-3.07529661-.40737887-1.25884293-1.73615861-2.15641302-3.07529661-1.74609855h0Z\"/><path class=\"cls-1\" d=\"M261.81818182,47.77272727h30.54545455c3.2172614,0,3.22259025-5,0-5h-30.54545455c-3.2172614,0-3.22259025,5,0,5h0Z\"/><path class=\"cls-1\" d=\"M296.79367903,48.05243384c-.14279266.32852065.29982605-.31379225.3938848-.3906452.10309227-.10814706.22597712-.1844563.36865455-.22892772.23775165-.08741361.26938285-.11192627.09489361-.07353796l.66459903-.08930242c-.07112377.00774283-.14220217.00734803-.2132352-.00118442l.66459903.08930242c-.23911207-.05206733-.1464698-.00244856.27792682.14885629-.2159456-.13451536-.14672957-.07863347.20764811.16764568-.17030846-.18869044-.11906614-.11900855.15372696.20904565-.0462328-.07184867-.0885596-.14592899-.1269804-.22224096-.22653558-.3772325.21096863.64912366.03913929.05087988-.04229545-.14725652-.07128571-.29641028-.09556408-.44751622l.08930242.66459903c-.04369673-.34482496-.0418686-.6843852.00175067-1.0289982l-.08930242.66459903c.02690022-.17098952.06046268-.33994239.10749395-.50665769.02088334-.07402675.043895-.14724629.06910891-.21991214.14125537-.4070945-.03521986.16948075-.10074111.2234775.0974125-.08027865.18110915-.34472136.25069458-.45241406.05302114-.08205727.23284009-.31800832-.02954112.01914809-.28438435.36543015-.03423069.05201036.0242946-.01102223.10356539-.11154144.23157231-.20218801.33289463-.31382531-.39343612.43348934-.38568763.28577589-.1803935.15609954.06610032-.04175301.13349055-.08077823.20244407-.11762371.39884584-.21312422-.12980706.09871974-.21020786.07504837.0407112.01198607.18423516-.06484415.22828641-.07836317.19248659-.05907282.38864607-.09746547.58748349-.12704466l-.66459903.08930242c.36417968-.0424485.7232213-.03907555,1.08697619.00490829l-.66459903-.08930242c.26404411.03937845.52236954.09500147.77691456.17604134.25089059.07987641.51284857.3175454-.07825197-.05327493.103093.06467425.22537382.1069804.33239506.16575851.10848747.05958338.21504661.12316595.31870211.19081813.21932833.14314762.3076156.34578733-.10661877-.09949273.18534212.19923298.40390155.36140759.58393081.57007207.35413706.41046564-.19639368-.29572339-.06288879-.08451014.08307184.13142495.17300653.25752686.25158491.39207996.06715119.11498586.13023851.23239883.18942654.3516706.09100488.18338699.17814735.58522754-.03575662-.10911295.17461908.56682025.34694939,1.10226675.43018429,1.69359734l-.08930242-.66459903c.08379448.67888138.09195397,1.35970481.01718124,2.03987995l.08930242-.66459903c-.02013034.14237764-.05207963.27846202-.07710547.41962246-.06198656.19235208-.0504584.18157364.03458448-.03233532.09726737-.20887602.09938969-.22353125.00636696-.0439657-.19145653.34510867.33615912-.40451678.14763967-.19289335-.32059551.35988605.35886654-.20186808.15886985-.11441529-.07824635.03421488-.17628124.08454955-.24735183.13423935.4463332-.31205885.45892191-.1781537.16329964-.09161866-.23061103.06750484-.4670577.10859666-.70458207.14232585l.66459903-.08930242c-.27818147.03426883-.55640846.05483209-.8362967.06864585-1.30413904.06436523-2.56253643,1.10378973-2.5,2.5.05819514,1.29928512,1.1010213,2.56904601,2.5,2.5,1.20244256-.05934605,2.49390081-.20728852,3.53133279-.87651124,1.45902964-.94118535,2.00208839-2.40498528,2.10641022-4.07699127.15277142-2.44852628-.61255909-4.94512798-2.24573814-6.78748542-1.64457367-1.85521149-4.35990732-2.68965775-6.76080517-2.12535526-1.11547815.26217987-2.22325143.92087234-2.96207659,1.79982651-.91523956,1.08882815-1.39637323,2.29629796-1.55346452,3.70252193-.16391479,1.46730549.33193842,2.99587838,1.28524613,4.11056157.65050864.76062644,1.67070698,1.2204746,2.67031714,1.20474974,1.10475419-.01737888,2.38717912-.63501075,2.84866625-1.69674636.27824153-.64014556.44544802-1.22399329.25202087-1.9263969-.15969159-.57989764-.60807206-1.20833377-1.14889971-1.49407768-.58020013-.30654619-1.28307569-.46020846-1.9263969-.25202087-.57671455.18663275-1.24118359.56707055-1.49407768,1.14889971h0Z\"/><path class=\"cls-1\" d=\"M30.35031904,10.00755918c-2.82212636-.48317056-5.89184194-.96697604-8.67650894-.01497981-3.06327467,1.04724404-5.17891902,3.63509074-6.56983378,6.47104523-.75151943,1.5322829-1.50437149,3.27534433-1.52678397,5.0119019-.01937397,1.5011284.62536495,2.96394989,1.68407413,4.01636748,2.13158027,2.11891291,5.35306304,2.5011965,8.13435336,1.67316053,1.6385754-.4878309,3.14498257-1.32097168,4.71184369-1.98756423-.31626896.13455087.1133094-.0329611.13126506-.05045858.56101674-.14533002.28982644-.37188217-.81357089-.67965643-.72066966-.059966-1.06450677-.35256274-1.03151131-.87779022-.1011444.28170125.00503342.84577087-.0148051,1.15447217-.00877853.13660001-.01955122.27298164-.03252772.40925767-.07717673.81049068.09970014-.37832029-.0672035.4186701-.09387634.44827385-.20098738.88785868-.33251802,1.32682959-.37529568,1.25251338.44996759,2.78007939,1.74609855,3.07529661,1.34604023.30658496,2.67340849-.40483544,3.07529661-1.74609855.42264741-1.41054526.69614542-2.9637946.6349559-4.44138648-.08739307-2.11034983-1.47585833-3.93590285-3.76114015-3.62882869-1.41796069.1905319-2.80191652,1.07235854-4.09971329,1.65493874-.04141039.0185891-.53592511.23274972-.30451343.13611096.20082944-.08386745-.19673102.07673121-.18658634.07287617-.32494895.12348276-.65130314.24245282-.98456812.341936-.29129505.0869547-.58593701.15250302-.88197303.21959167-.40973554.09285561.26216763-.01102886-.07715115.0206693-.16333676.01525844-.32721323.02272628-.49131218.0221278-.09954932-.00036306-.19862557-.00755205-.29801178-.01042826-.09489309-.00274618-.49867868-.08646468-.16451125-.00997792.32423072.07421237-.01400457-.01107658-.06268881-.02521278-.12829542-.03725252-.25994165-.06263909-.38818261-.10091192-.12832497-.03829791-.25235779-.08359857-.37845504-.12776827.09465943.03315757.44091242.23385615.05499661.01147326-.17277969-.0995638-.71166558-.47870637-.30216847-.13482659-.16605422-.13944588-.30266875-.32439322-.47004745-.45679287-.27233267-.21542018.30742263.29983669.06481032.06044891-.06201004-.06118587-.08640931-.16842195-.13373298-.24026214.24136867.36641223.10623449.27298364.05495569.08044147-.05914625-.22208295.03452398-.29197861-.00767143.10318761.01993522-.18669631-.01927864-.36838567.00709358-.55893554-.03614061.26113036.04614132-.10202821.06447239-.16334033.10514904-.35169309.21017086-.70031473.33573919-1.04553593.04568762-.12560759.09361173-.25036226.14223469-.37485131.16035422-.41055382-.12153839.26027855.05903719-.14178971.29205777-.65029366.62806829-1.28054862,1.00343877-1.88653687.16422044-.26511316.33557786-.52575453.51485231-.78095611.10209251-.14533119.20507267-.29263477.31449098-.43228115-.03683875.04701588-.16664795.2090177.01497808-.00622884.19660368-.23299668.39895616-.4610511.61667153-.67470274.12247272-.12018672.25069569-.2431097.38399225-.35233953-.22957954.1881289.11208892-.07282586.1992824-.12797297.13198965-.08347926.26660271-.16154977.40451647-.2348265.08451281-.04490359.55872979-.23975649.13993241-.08274159.28857487-.10819207.58321792-.19913673.88277809-.27171601.1703148-.04126492.94181322-.14378094.48652307-.10640436.35684539-.02929486.71049728-.05559463,1.06888365-.0600096.68828537-.00847901,1.37618582.03693813,2.06023025.11088067.1621089.01752334.32415344.03678175.48585845.05758266-.26926087-.03463636-.11964268-.016139.06056466.01204922.39725252.06213864.79393758.12633663,1.19027234.19419231,1.28416645.21985955,2.75510417-.34031562,3.07529661-1.74609855.27606805-1.21205783-.36774707-2.83931184-1.74609855-3.07529661h0Z\"/><path class=\"cls-2\" d=\"M96.5370648,58.00706031c14.14030874,7.34166633,28.67438881,13.90734586,43.5179811,19.69595596,1.25827803.4906953,2.74382117-.53973032,3.07529661-1.74609855.3889322-1.41547574-.48322463-2.58280904-1.74609855-3.07529661-14.44203409-5.63201298-28.56625206-12.04909023-42.32358342-19.19191422-2.85204602-1.48078593-5.38347181,2.83250213-2.52359574,4.31735343h0Z\"/><path class=\"cls-2\" d=\"M136.46662457,69.30790065c1.95363442,2.847267,4.01732976,5.61579818,6.16670791,8.3181769l.50596908-3.92644367c-.73433712.38180468-1.47629102.74818605-2.22803435,1.09454704-.35952998.16565117-.72148587.32547066-1.08415225.4840821-.6582181.28787041.46694394-.18733593-.19838795.08368672-.19994823.08144882-.39976054.16306954-.60043653.242721-1.5388404.61078997-3.10788756,1.14057358-4.69879197,1.59838855-1.25586798.36140145-2.16521497,1.78018345-1.74609855,3.07529661.41323412,1.27693627,1.72902057,2.13351675,3.07529661,1.74609855,3.45580622-.99447824,6.8139204-2.34874133,10.00420074-4.00746714.68744694-.35742501,1.09426382-1.08747094,1.19355092-1.8263772.11343513-.84419754-.17245693-1.45240817-.68758184-2.10006647-.25204444-.31689143-.50313586-.63452564-.75257248-.9534753-.11337966-.14497632-.22625275-.29034351-.33927934-.43559442.32414969.416566-.12099444-.15841087-.14815549-.19391007-.46971165-.61390814-.93401935-1.23195208-1.39304693-1.85388824-.93996101-1.27355254-1.8563082-2.56421277-2.75183414-3.86937071-.73845105-1.07623375-2.22889746-1.66510436-3.42047458-.89687884-1.07068871.69028716-1.68817626,2.26722144-.89687884,3.42047458h0Z\"/><path class=\"cls-2\" d=\"M174.22311304,79.87988872c2.63101377-2.55431661,6.75100212-3.6017601,10.08848874-4.89473001,3.97741013-1.54088158,7.97059121-3.04105489,11.97873014-4.50014169,8.01627405-2.9181722,16.09232361-5.67217613,24.22135954-8.25967589,4.60141087-1.46464472,9.22014143-2.87409285,13.85374171-4.23340736,3.08103929-.9038547,1.76982126-5.7305245-1.32919806-4.82139517-16.83591727,4.93899024-33.46543662,10.57401855-49.82869496,16.90600522-4.27006229,1.65235902-9.15846552,3.00430705-12.51996102,6.26781099-2.31284559,2.24542341,1.22460702,5.77909454,3.53553391,3.53553391h0Z\"/><path class=\"cls-2\" d=\"M227.72676418,54.04477399c1.47243739.01011554,2.94307036.08871417,4.40744148.24416097.15910997.01688994.31810764.03481531.47701835.05348088.07583864.00890797.72332056.08751933.33445297.03918946-.38731161-.04813648.16030586.02326832.23821513.03468529.18997268.02783894.37977247.05689823.56935624.08727638.7179464.11504088,1.43670944.24078597,2.14646789.39937386.0622608.01391151.2894528.11455651.34840108.08845125-.34924254-.16728314-.43943912-.20589635-.27058974-.11583963.16504138.09381278.08947056.03307736-.22671243-.18220626-.15928972-.15231258-.585857-.7613557-.43928014-1.01978011-.0340822.06008911-.00445235.57848841.01492824.09807191.01765248-.43757906-.03480728.05323315-.07041182.17001702-.0377447.12380366-.08125781.24557452-.12529945.36724536-.05819513.16077168-.12198083.31925062-.18279721.47899157-.21123647.55483592.23718672-.50545336-.01409938.03243121-.55782746,1.19404449-1.20663351,2.31953185-2.00128506,3.37300022-.36433471.48299798-.40457982,1.37240043-.25202087,1.9263969.15969159.57989764.60807206,1.20833377,1.14889971,1.49407768.58020013.30654619,1.28307569.46020846,1.9263969.25202087.65927884-.21335169,1.07991483-.59984464,1.49407768-1.14889971,1.03236301-1.3686021,1.80993673-2.8567199,2.45527869-4.4414242.32411645-.79590164.58598486-1.58754808.60772817-2.46038855.03262656-1.30972611-.65603603-2.61638255-1.81180729-3.25690734-.81866495-.45370153-1.75406675-.58630934-2.66142313-.74797706-.97613173-.17392173-1.95869882-.31122642-2.94253724-.43337004-1.7155995-.21299182-3.4418528-.32020295-5.17039878-.33207793-1.30794357-.00898548-2.56018387,1.15631369-2.5,2.5.06101304,1.36219848,1.09831737,2.49037054,2.5,2.5h0Z\"/><path class=\"cls-1\" d=\"M275.99695758,25.92705402c4.25760875-.4652173,8.53987146-.63552397,12.82097627-.50989389,1.30833849.03839352,2.5592423-1.17733563,2.5-2.5-.0621399-1.38735716-1.09822273-2.4588645-2.5-2.5-4.28110692-.12563014-8.56336962.04467682-12.82097627.50989389-1.295739.14158187-2.56501927,1.04835688-2.5,2.5.05521316,1.23270842,1.1077183,2.65213083,2.5,2.5h0Z\"/><path class=\"cls-1\" d=\"M285.8656149,17.77772551l4.02897331,2.72242898,2.06893224,1.39800407.98002054.66221245c.18148356.12263077.36327329.24482036.54445585.36789581.05166131.035093.55939735.39631106.27007857.17376665-.26118878-.20090677.06387158.08215153.10897263.11307719.12842009.13392587.09496626.08347968-.10036147-.15133858l-.10777181-.27863855c-.06975281-.34205661-.00590955-.72897009.11715133-1.04638468-.1631952.42093421.1421719-.10014913-.02286827.02567387-.61454.46851181-1.13601417,1.21983643-1.66335878,1.78556206-1.12474269,1.20660335-2.2494852,2.41320685-3.37422772,3.61981036-.89199511.95691628-1.01882577,2.60027058,0,3.53553391.9691327.889646,2.5830853,1.0217697,3.53553391,0,1.30233344-1.39711985,2.60466688-2.7942397,3.90700059-4.19135931.66514661-.71355703,1.42416931-1.41388991,1.9352737-2.25162514.70338249-1.15289227.65538172-2.66697088-.06118665-3.79604431-.57742216-.90982528-1.47292314-1.48528738-2.3473138-2.07612438l-2.39560575-1.61874155-4.90010268-3.31106227c-1.0863207-.73404084-2.81790934-.24359671-3.42047458.89687884-.66760115,1.26356906-.26246345,2.63709212.89687884,3.42047458h0Z\"/><path class=\"cls-1\" d=\"M304.62573169,21.77161597c2.17647303-.24753376,4.36873304-.30078106,6.55465535-.15920496.61449652.03979923,1.34279064-.30725673,1.76776695-.73223305.4336057-.4336057.76012615-1.14501564.73223305-1.76776695-.06391167-1.42691449-1.09922373-2.40927562-2.5-2.5-2.18592406-.14157621-4.37818407-.08832861-6.55465535.15920496-.68396813.07778879-1.2627244.22719049-1.76776695.73223305-.4336057.4336057-.76012615,1.14501564-.73223305,1.76776695.02895947.64655933.24134366,1.31713952.73223305,1.76776695.45649719.41905603,1.12317524.8055435,1.76776695.73223305h0Z\"/><path class=\"cls-1\" d=\"M303.79114549,12.27352752c-.30852816,5.10895442-.18117605,10.23694315.40864737,15.32183249.15858481,1.36716549.20969171,2.82766124,1.19273067,3.90021,1.12034834,1.22236073,2.60298017,1.23865499,4.11849908.97050023,2.32361852-.41113929,4.58615075-1.35989879,6.55446681-2.65286468,1.12724652-.74047625,1.60377638-2.21191097.89687884-3.42047458-.6553721-1.12047197-2.2870594-1.64140722-3.42047458-.89687884-1.52413291,1.0011867-2.98156403,1.64300789-4.75571341,2.02931256-.199148.04336264-.40218783.09287102-.60435572.11951038l.08869578-.00310027c-.54082247-.03578968-.40200544.13517672.41645108.51289921,1.1306164.82277839.63277991.63510055.60625776.16050397-.0260487-.14546631-.02942651-.15446533-.01013345-.02699704l-.04235359-.34622612c-.12124466-1.03950512-.23093456-2.07996249-.3179651-3.12294219-.34822602-4.17316375-.38403212-8.36575378-.13163153-12.54528512.08147732-1.34919259-1.20734262-2.5-2.5-2.5-1.42123413,0-2.41828274,1.14683416-2.5,2.5h0Z\"/><path class=\"cls-2\" d=\"M34.78223005,86.53757743c12.05935271-9.67816561,25.21779084-17.96757147,39.10037157-24.77016482,1.21225318-.59401531,1.54280393-2.31615391.89687884-3.42047458-.72335662-1.23670328-2.20368951-1.49311482-3.42047458-.89687884-14.28437785,6.99947766-27.70869491,15.5975331-40.11230973,25.55198434-1.05383696.84575092-.88143045,2.65410346,0,3.53553391,1.04134419,1.04134419,2.4790368.8478858,3.53553391,0h0Z\"/><path class=\"cls-2\" d=\"M65.99664711,57.07942182l10.12258173.87990945c.3843218.03340733.76851235.07143927,1.15320551.10024285.57164331.04280131-.41249813-.0370089-.07157071-.00341996.35073302.034555.2005329.08931622-.04839068-.05420477-.28311147-.1547461-.44710702-.40187387-.49198663-.74138332-.16546754-.59144473-.24511592-.73545077-.23894513-.43201812-.05436263.17696417-.0539673.48573118.00031734.12168972-.05683655.381155-.12739666.76047231-.20936417,1.13701025-.16394145.75310547-.3780903,1.49576742-.63896414,2.22099021-.05219888.14511159-.10783813.2888578-.1622196.43314805-.25672107.68115755.11987134-.22781371-.05922993.14991769-.18206495.3839819-.35907266.76672119-.55661548,1.14339751-.60696969,1.157375-.33405315,2.77011708.89687884,3.42047458,1.15247629.60890578,2.771939.33975435,3.42047458-.89687884.92155545-1.7572298,1.64101276-3.64274448,2.0137691-5.59498671.22965972-1.20280022.49126092-2.46108925-.00143454-3.62860033-.48488586-1.14900514-1.55082337-1.90569919-2.76467391-2.13303749-2.02544177-.3793387-4.16187656-.40929251-6.21340278-.58762225l-6.1504294-.53462853c-1.30639965-.11355931-2.5568399,1.23097252-2.5,2.5.06501535,1.45155553,1.10056522,2.37835357,2.5,2.5h0Z\"/><path class=\"cls-2\" d=\"M255.71720341,57.1808308c13.58397164,5.13073067,27.31263307,9.87115929,41.16825629,14.2151645,3.07746674.9648452,4.39411849-3.86048348,1.32919806-4.82139517-13.85562344-4.34400528-27.58428487-9.08443391-41.16825629-14.2151645-1.26334057-.47716974-2.74111864.52989477-3.07529661,1.74609855-.3858398,1.40422127.47817474,2.59639576,1.74609855,3.07529661h0Z\"/><path class=\"cls-2\" d=\"M294.83788956,63.8006524c2.54913771,2.31738524,5.09092773,4.64859629,7.56976654,7.04135273.10030402.09682077.29882493.24098096.35611248.36443274l-.16728035-.18983337c-.32649696-.97155402-.1926448-1.69162438.40155647-2.16021108.16296727-.12442245.1470935-.1298646-.04762133-.01632643l-.16095058.0707245c-.2232343.09971279-.45129098.19097765-.67645443.2862625-.78919683.33397292-1.57839364.66794587-2.36759044,1.00191884-1.61597439.68384941-3.23194875,1.3676989-4.8479231,2.0515484-1.20920801.51171374-1.56362169,2.38630491-.89687884,3.42047458.8108513,1.25769301,2.12660033,1.44442172,3.42047458.89687884,1.87903995-.79517383,3.7580799-1.59034766,5.63711991-2.38552136.84914718-.3593428,1.76439096-.66343783,2.5747916-1.10442436,1.46364431-.79645473,2.13603009-2.57456763,1.48434443-4.1188283-.45011977-1.066622-1.32174264-1.795127-2.1444545-2.57383405-.70668709-.66888816-1.41558612-1.33543991-2.12668098-1.99964026-1.48145728-1.38375977-2.97279582-2.75687734-4.47279756-4.12050783-.96761947-.87964925-2.59248841-1.02730325-3.53553391,0-.88022111.95886573-1.03347442,2.59601685,0,3.53553391h0Z\"/><path class=\"cls-2\" d=\"M25.91947921,74.59723327c-2.38284408,7.54780237.76554395,16.05677153,7.21950809,20.50651192,1.11211936.76676014,2.77490021.20685841,3.42047458-.89687884.72555699-1.24048337.21782372-2.65193344-.89687884-3.42047458-.1718527-.1184853-.34341655-.23718203-.51028205-.36268936-.35602974-.26778656.40234495.36583086-.17974879-.15179154-.28014567-.24911739-.5614751-.49330682-.82893186-.75661542-.26653025-.26239646-.52320338-.53463733-.76958891-.81604829-.13689629-.15635706-.27022755-.31584514-.40031016-.47790154-.26041343-.32442205.17801668.25034444-.06424015-.0881214-.46121287-.6443773-.88328964-1.31222546-1.25086661-2.01471717-.09666664-.18474366-.18934554-.37151609-.27890171-.55979991-.01818793-.03823848-.21293847-.45950086-.13067198-.27197302.09934622.22646138-.13716318-.34537676-.15669164-.39712896-.07367312-.19524051-.14320808-.39198873-.20947427-.58985738-.23851595-.71220074-.42869181-1.44007665-.56829973-2.17807804-.03872703-.20472049-.07497957-.41009437-.10491947-.61631664.03959999.2727597.00952872.08405273-.00456897-.07923783-.03583896-.41511509-.06915932-.82881266-.0787431-1.24566142-.01714848-.74587695.01057062-1.49975288.11030481-2.23973735-.0579604.43004106.02972186-.11944618.04423148-.19791329.03782761-.20456934.07948119-.40836442.12613241-.61112625.0935852-.40675264.20824364-.8073418.33386203-1.20524562.40637923-1.28723071-.4788893-2.7271038-1.74609855-3.07529661-1.34587928-.36980909-2.66736331.4539452-3.07529661,1.74609855h0Z\"/><path class=\"cls-2\" d=\"M141.91987424,63.02141932c4.67857218,7.49121994,5.44904734,16.78713637,2.21936403,24.98871852-.49486667,1.25668348.5427697,2.7446563,1.74609855,3.07529661,1.41895417.38988797,2.57861662-.48481026,3.07529661-1.74609855,3.68173626-9.34954281,2.59005257-20.33372757-2.72340577-28.84151232-1.70079477-2.72327266-6.02844759-.21616807-4.31735343,2.52359574h0Z\"/><path class=\"cls-2\" d=\"M167.2507335,66.40010818c-3.61594211,6.61383947-3.51233567,14.91547036.36465996,21.39857359,1.64986784,2.75890523,5.97450139.24748329,4.31735343-2.52359574-2.98070174-4.98432263-3.13311995-11.28765338-.36465996-16.35138211.64756461-1.18444606.29144118-2.72542786-.89687884-3.42047458-1.14289292-.66847647-2.77066242-.29167817-3.42047458.89687884h0Z\"/><path class=\"cls-2\" d=\"M304.61463664,62.043563c1.23158871,5.36355559,1.40676776,10.97818893.44458148,16.40202993-.2355829,1.32798006.3588885,2.69413102,1.74609855,3.07529661,1.20831816.33201123,2.83819588-.40956246,3.07529661-1.74609855,1.12557694-6.34487366.99874056-12.77477408-.44458148-19.06042606-.30225256-1.31630666-1.81373916-2.09279322-3.07529661-1.74609855-1.35096741.37126585-2.04926444,1.75501244-1.74609855,3.07529661h0Z\"/><path class=\"cls-2\" d=\"M156.22727273,60.81818182v30.54545455c0,3.2172614,5,3.22259025,5,0v-30.54545455c0-3.2172614-5-3.22259025-5,0h0Z\"/></svg>\n<figcaption>\n高亮颜色表示 Fence 发生的线程的访存，G 的定义来自访存拿到 Grant 的 Wall-clock，因此可能不直接反映核心视角的真实执行时间，但这个拿到 Grant 的时刻一定在核心视角中的 Inflight 时段内。箭头表示请求、回应的方向，括号表示核心视角对应访存的执行时间。\n</figcaption>\n</figure>\n<p>讨论另一个方向是，第一个遇到的问题是什么叫必要性？删掉这个条件的话，直接恢复成 AcqRel Fence 那么一开始的 SB 就是一个反例。但是硬件实现确实可以比 AcqRel + preserves <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 要更弱，例如如果整个系统现在只有一个 Inflight SeqCst 操作就是这个 Fence，那么硬件可以不保证任何序，然后一对 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 在 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>G</mi></mrow><annotation encoding=\"application/x-tex\">G</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">G</span></span></span></span> 中被交换顺序后被另一对访存观测到：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>R</mi><msub><mo>→</mo><mrow><mi>r</mi><mi>b</mi></mrow></msub><msup><mi>W</mi><mo mathvariant=\"normal\" lspace=\"0em\" rspace=\"0em\">′</mo></msup><msub><mo>→</mo><mrow><mi>h</mi><mi>b</mi></mrow></msub><msup><mi>R</mi><mo mathvariant=\"normal\" lspace=\"0em\" rspace=\"0em\">′</mo></msup><msub><mo>→</mo><mrow><mi>r</mi><mi>b</mi></mrow></msub><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">\nR \\to_{rb} W&#x27; \\to_{hb} R&#x27; \\to_{rb} W\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8333em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9519em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8019em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">′</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">hb</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9519em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8019em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">′</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mrel\">→</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3361em;\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal mtight\">b</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span></span></p>\n<p>事实上这是 C++ 标准中明确允许的一件事：[atomics.order] <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">¶</mi></mrow><annotation encoding=\"application/x-tex\">\\P</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">¶</span></span></span></span> 6</p>\n<blockquote>\n<p>Note 4 : We do not require that S be consistent with “happens before” (6.9.2.2). This allows more efficient implementation of <code>memory_order::acquire</code> and <code>memory_order::release</code> on some machine architectures. It can produce surprising results when these are mixed with <code>memory_order::seq_cst</code> accesses. — end note</p>\n</blockquote>\n<p>在 MCA + perserves <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 时，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span> 和 Happens before 也一致了。我暂时没有找到这里并未指名道姓的架构是啥，是否需要 Non-MCA，如果后续想通了将会更新本文。</p>\n<h2>In Non-MCA Environment</h2>\n<p>在非 MCA 的系统中，“先后”变得模糊了，但是上述 Coherence-ordered before (cob) 是使用内存访问观测到的一个序，因此还是可以定义的，只不过这个序并不需要作为某个全局序的子序，本身也不一定是一个全序。此时，如果我们能明确定义“先后”，那么也许还可以说明保证 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 顺序是一个充分条件。</p>\n<p><strong>Edit (2025-05-22)</strong>: 这里原来有一个简短的证明，尝试说明保证 SeqCst Store 本身 MCA 就可以实现 SeqCst 的语义。<strong>这是错误的</strong>，部分原因是目前 C++ 标准过强，只通过写无法提供 C++ 要求的语义。一个正确的证明见<a href=\"non-mca-seqcst-fences\">后续文章</a>，关于为什么 C++ 标准太强的解释我有时间再写（</p>\n<details>\n<summary>错误的证明</summary>\n<p>从硬件实现的角度，如果我们把“先后”的视角放在在核心上，即把这个先后解读为之前所有的访存都已经全局可见，后续访存才开始执行的话，可以把这些 Fence 发生的时间定义为这个同步点的 Wall-clock。对于其他 Sequentially-consisten 的 AMO，如果在其本身已经有一个全序 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span><sup>[3]</sup> 以后也是以类似的方式控制前后的其他访存，那么可以在 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span> 的基础上扩展，把 Fence 都加进去：</p>\n<p>逐个处理每个 Fence F。可以找到目前 S 中所有和 F 相关的其他 SeqCst 访存或者 Fence K，相关指在 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo>∪</mo><mo stretchy=\"false\">(</mo><mi>s</mi><mi>b</mi><mo separator=\"true\">;</mo><mo stretchy=\"false\">(</mo><mi>r</mi><mi>f</mi><mo>∪</mo><mi>r</mi><mi>b</mi><mo>∪</mo><mi>m</mi><mi>o</mi><msup><mo stretchy=\"false\">)</mo><mo>+</mo></msup><mo separator=\"true\">;</mo><mi>s</mi><mi>b</mi><mo stretchy=\"false\">)</mo><msup><mo stretchy=\"false\">)</mo><mo>+</mo></msup></mrow><annotation encoding=\"application/x-tex\">(sb \\cup (sb ; (rf \\cup rb \\cup mo)^+ ; sb))^+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0213em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">o</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">)</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7713em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span></span></span></span> 序的前驱或后继。上述阻塞所有访存的实现方式保证了这是一个和 S 兼容的序，并且这里是一个传递闭包，这是为了避免首先添加的两个本身不直接通过观测相关的 SeqCst 操作后续由于倒序导致第三个和两者都相关的 SeqCst 访存无法插入。</p>\n</details>\n<hr />\n<p>[1] N4917 [atomics.fence]</p>\n<p>[2] 注意到，在不考虑 Mix-sized access 时 (effectively all general-purposed hardware, 因为大家的缓存都是按缓存行访问的)，这个子序中的每一个连通分量只包含一个地址。所以基本所有硬件内存续都包含一个公理叫作：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>a</mi><mi>c</mi><mi>y</mi><mi>c</mi><mi>l</mi><mi>i</mi><mi>c</mi><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">(</mo><mi>r</mi><mi>f</mi><mo>∪</mo><mi>r</mi><mi>b</mi><mo>∪</mo><mi>m</mi><mi>o</mi><msup><mo stretchy=\"false\">)</mo><mo>+</mo></msup><mo separator=\"true\">;</mo><mi>p</mi><mi>o</mi><mi mathvariant=\"normal\">_</mi><mi>l</mi><mi>o</mi><mi>c</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\nacyclic((rf \\cup rb \\cup mo)^+ ; po\\_loc)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">cyc</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">c</span><span class=\"mopen\">((</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.1313em;vertical-align:-0.31em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">o</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8213em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord\" style=\"margin-right:0.02778em;\">_</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">oc</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>意思是LSU、缓存等部件不能让相同地址的访存莫名其妙换顺序，用 C++ 术语是 Coherence-ordered before 和 Sequenced before 兼容 ([intro.races] <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">¶</mi></mrow><annotation encoding=\"application/x-tex\">\\P</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">¶</span></span></span></span> 14-17)。PTX 的文章中直接把这个叫 SC-per-location。这是 Full SC 的一个弱化：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>S</mi><mi>C</mi><mo>=</mo><mi>a</mi><mi>c</mi><mi>y</mi><mi>c</mi><mi>l</mi><mi>i</mi><mi>c</mi><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">(</mo><mi>r</mi><mi>f</mi><mo>∪</mo><mi>r</mi><mi>b</mi><mo>∪</mo><mi>m</mi><mi>o</mi><msup><mo stretchy=\"false\">)</mo><mo>+</mo></msup><mo separator=\"true\">;</mo><mi>p</mi><mi>o</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\nSC = acyclic((rf \\cup rb \\cup mo)^+ ; po)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">SC</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">cyc</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">c</span><span class=\"mopen\">((</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0713em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">o</span><span class=\"mclose\"><span class=\"mclose\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8213em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span></span></span></span></span><span class=\"mpunct\">;</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>[3] 对于其他带访存的 SeqCst AMO，这个序的存在不是自然的，比如在 IRIW 中，两个写入线程只有一个写，前后没有别的访存需要进行排序。所以需要额外进行跨线程的同步。</p>\n","plain":"考虑典中典 Store buffering litmus test，在 C++ 中的实现。\nx.store(1, relaxed)  |  y.store(1, relaxed)\na = y.load(relaxed)  |  b = x.load(relaxed)\n\n在 Sequentially consistent 的内存模型 (SC) 下，是肯定不会发生 a == b == 0 的，但是现实是一个远比 SC 更丑恶的地方。Store buffer 导致弱内存序中，特别是在 TSO 上也会发生 a == b == 0 的情况，而 TSO 中所有 Acquire 和 Release 语义全都是 No-op，所以两个线程两个访存之间分别加上 AcqRel Fence 也无法避免这个行为。\n一种恢复 SC 中这段代码的行为的方法是把所有访问的 relaxed 都换成 seq_cst，C++ 标准要求所有 SeqCst Atomic 操作都在同一个全序内。另一种方法在两侧两个访存中间分别加上一个 SeqCst Fence，因此一种常见的定义/解释 SeqCst Fence 的方法是：\n它是 AcqRel Fence，并且额外保证 W \\to R 顺序。\n\n这是一个来自 ISA 和硬件视角的定义方法。但是 Virtually 没有任何一个语言的内存模型是直接这么定义的。这个刻画准确吗？它 Sound & complete 吗？\n作为一个工科猪还是以 C++ 为例。这句话的前一半首先是对的，标准里说使用 std::memory_order_seq_cst 的 Fence 是一个…\n…sequentially consistent acquire and release atomic fence[1]…\n\n…That’s a long name. Anyway，这意味着需要仔细看的只有后半部分。先说结论，在 MCA 系统中，W \\to R 是一个充分条件，但不必要。在更弱的系统中（e.g. IRIW 允许不同观测顺序），这个“先后”就很难定义了。\n\nIn MCA Environment\n在前一篇博文中简要提及了，如果满足 MCA，那么存在一个 Global total order G 对所有线程的所有内存操作排序。这一排序中的一部分可以使用访存观测到，这个可以被观测结果确认的子序就是如下三者的并的闭包：\n- rf / Read from: [atomic.order] \\P 3.1\n- mo / Modification: [atomic.order] \\P 3.2\n- rb / Read before 或者部分文献叫作 fr / From read: [atomic.order] \\P 3.3\nC++ 标准把这个叫作 Coherence-ordered before[2]。C++ 对于 SeqCst 操作的要求是所有 SeqCst 操作构成一个全序 S，然后 $S + $sequenced-before 和 Coherence-ordered before 兼容 ([atomics.order] \\P 4)。但是如果保持 SeqCst Fence 保持 W \\to R，那么它会在 G 中保证有一个位置正好可以把这个 Fence 插入进去。这个时候注意到 S 和 Coherence-ordered before 都是 G 的一个子序，一定兼容。\n讨论另一个方向是，第一个遇到的问题是什么叫必要性？删掉这个条件的话，直接恢复成 AcqRel Fence 那么一开始的 SB 就是一个反例。但是硬件实现确实可以比 AcqRel + preserves W \\to R 要更弱，例如如果整个系统现在只有一个 Inflight SeqCst 操作就是这个 Fence，那么硬件可以不保证任何序，然后一对 W \\to R 在 G 中被交换顺序后被另一对访存观测到：\n\nR \\to_{rb} W' \\to_{hb} R' \\to_{rb} W\n\n事实上这是 C++ 标准中明确允许的一件事：[atomics.order] \\P 6\nNote 4 : We do not require that S be consistent with “happens before” (6.9.2.2). This allows more efficient implementation of memory_order::acquire and memory_order::release on some machine architectures. It can produce surprising results when these are mixed with memory_order::seq_cst accesses. — end note\n\n在 MCA + perserves W \\to R 时，S 和 Happens before 也一致了。我暂时没有找到这里并未指名道姓的架构是啥，是否需要 Non-MCA，如果后续想通了将会更新本文。\n\nIn Non-MCA Environment\n在非 MCA 的系统中，“先后”变得模糊了，但是上述 Coherence-ordered before (cob) 是使用内存访问观测到的一个序，因此还是可以定义的，只不过这个序并不需要作为某个全局序的子序，本身也不一定是一个全序。此时，如果我们能明确定义“先后”，那么也许还可以说明保证 W \\to R 顺序是一个充分条件。\nEdit (2025-05-22): 这里原来有一个简短的证明，尝试说明保证 SeqCst Store 本身 MCA 就可以实现 SeqCst 的语义。这是错误的，部分原因是目前 C++ 标准过强，只通过写无法提供 C++ 要求的语义。一个正确的证明见后续文章，关于为什么 C++ 标准太强的解释我有时间再写（\n从硬件实现的角度，如果我们把“先后”的视角放在在核心上，即把这个先后解读为之前所有的访存都已经全局可见，后续访存才开始执行的话，可以把这些 Fence 发生的时间定义为这个同步点的 Wall-clock。对于其他 Sequentially-consisten 的 AMO，如果在其本身已经有一个全序 S[3] 以后也是以类似的方式控制前后的其他访存，那么可以在 S 的基础上扩展，把 Fence 都加进去：\n逐个处理每个 Fence F。可以找到目前 S 中所有和 F 相关的其他 SeqCst 访存或者 Fence K，相关指在 (sb \\cup (sb ; (rf \\cup rb \\cup mo)^+ ; sb))^+ 序的前驱或后继。上述阻塞所有访存的实现方式保证了这是一个和 S 兼容的序，并且这里是一个传递闭包，这是为了避免首先添加的两个本身不直接通过观测相关的 SeqCst 操作后续由于倒序导致第三个和两者都相关的 SeqCst 访存无法插入。\n---\n[1] N4917 [atomics.fence]\n[2] 注意到，在不考虑 Mix-sized access 时 (effectively all general-purposed hardware, 因为大家的缓存都是按缓存行访问的)，这个子序中的每一个连通分量只包含一个地址。所以基本所有硬件内存续都包含一个公理叫作：\n\nacyclic((rf \\cup rb \\cup mo)^+ ; po\\_loc)\n\n意思是LSU、缓存等部件不能让相同地址的访存莫名其妙换顺序，用 C++ 术语是 Coherence-ordered before 和 Sequenced before 兼容 ([intro.races] \\P 14-17)。PTX 的文章中直接把这个叫 SC-per-location。这是 Full SC 的一个弱化：\n\nSC = acyclic((rf \\cup rb \\cup mo)^+ ; po)\n\n[3] 对于其他带访存的 SeqCst AMO，这个序的存在不是自然的，比如在 IRIW 中，两个写入线程只有一个写，前后没有别的访存需要进行排序。所以需要额外进行跨线程的同步。\n"},{"metadata":{"id":"mca","lang":"zh-CN","title":"Multi-copy atomicity","tags":["微架构","Fences"],"publish_time":"2025-05-04T13:34:54+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358}],"text":"Multi","hadv":2835,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"y","components":[["M -7 -516L 95 -505L 204 -505L 298 -516L 298 -546L -7 -546Z",[0.917,0.005]],["M 108 271C 193 271 259 216 325 41L 543 -546L 501 -546L 421 -298L 335 -61L 324 -31L 293 41C 250 145 214 201 152 233L 171 250L 208 224L 177 184C 152 152 123 128 83 128C 44 128 5 148 -3 193C 0 241 52 271 108 271Z",[0.424,0.695]],["M 293 83L 365 -107L 359 -117L 204 -546L 29 -546Z",[-0.264,0.699]],["M 389 -516L 494 -505L 513 -505L 595 -516L 595 -546L 389 -546Z",[-0.927,0.015]]],"bbox":{"top":-546,"bottom":271,"left":-7,"right":595},"hadv":598}],"text":"copy","hadv":2503,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"y","components":[["M -7 -516L 95 -505L 204 -505L 298 -516L 298 -546L -7 -546Z",[0.917,0.005]],["M 108 271C 193 271 259 216 325 41L 543 -546L 501 -546L 421 -298L 335 -61L 324 -31L 293 41C 250 145 214 201 152 233L 171 250L 208 224L 177 184C 152 152 123 128 83 128C 44 128 5 148 -3 193C 0 241 52 271 108 271Z",[0.424,0.695]],["M 293 83L 365 -107L 359 -117L 204 -546L 29 -546Z",[-0.264,0.699]],["M 389 -516L 494 -505L 513 -505L 595 -516L 595 -546L 389 -546Z",[-0.927,0.015]]],"bbox":{"top":-546,"bottom":271,"left":-7,"right":595},"hadv":598}],"text":"atomicity","hadv":4966,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>之前<a href=\"/post/hardware-fences\">关于硬件 Fences</a>的文章中简单提及了丢失 Multi-copy atomicity 之后可能带来的麻烦，本文具体讨论一下 Multi-copy atomicity，其硬件实现及后果。</p>\n<h2>定义</h2>\n<p>MCA 这个概念本身一开始其实大家不怎么集中讨论，直到 ARMv8 made it popular<sup>[1]</sup>。According to [1][2], Multi-copy atomicity (MCA) 的定义其实不是很统一，本文遵从 [2] 中的非正式定义，因为这是现在 ARMv8, RISC-V 和 x86 及 TL, CHI 和 ACE 都遵从的定义，即 Multi-copy atomicity 指：</p>\n<ul>\n<li>除了本地以外，一个写在所有其他 Agent 看来同时生效。</li>\n<li>执行这个写的 Agent 本身可以提前看到它。</li>\n</ul>\n<p>在并行系统中，“同时”事实上是一个不太好定义的东西，因为实际上即使遵从 MCA 的系统在实际执行中对不同位置的写也是并行处理的，这好像不太“原子”。更形式化的说法应该是：</p>\n<ul>\n<li>除了参与写的 Agent 以外，所有其他 Agent 对于多个写存在一个一致的观测顺序。</li>\n</ul>\n<p>也就是某个写不能“出现在一个 Agent 处太晚，结果排到了另一个写后面”。</p>\n<h2>实现</h2>\n<p>首先，如果硬件本身拓扑足够简单，那么 MCA 是 Free 的。例如所有核心没有 L1，共享 L2，一个 Store buffer 打到 L2 上，那在核心看起来访存就是 MCA 的。当拓扑更加麻烦，例如存在多级缓存，或者存在 Slices，那就需要总线协议额外打补丁。</p>\n<p>传统的 CPU 缓存层级中的一致性协议是最经典的在一个原生不支持 MCA 的拓扑上实现一个 MCA 系统的方式。最重要的观察是，因为 Writer 在执行写入的时候一定持有 Exclusive 权限，因此在一致性域内，除了 Agent 自用的局部 Store buffer 以外， <strong>在某个特定时间，所有可以回应读取的器件里面，同一行的值肯定是一样的。</strong> 对于 Tilelink 而言，就是所有 Thunk Tip 和 Branch 状态的缓存。对于其他 MESI 缓存，所有的 M/E/S 状态并且自己上级没有 M/E 状态的缓存。</p>\n<p>这样所有的写入的顺序可以被整个系统 Agrees on。准确来说，写生效的时刻可以认为是最终写穿透到达的缓存拿到 Grant 的时刻，原子性由任何时刻在整个缓存层级中同一行在任何地方读到的值都相同而保证。写生效的顺序也可以直接通过这件事情发生的 wall-clock 时间定义。</p>\n<h2>影响</h2>\n<p>如果一个系统保证 MCA，例如某个 ISA 对软件保证 MCA，或者某个总线协议对 Master 保证 MCA，那么内存模型会简化非常多。有两个很直接的结果：</p>\n<ol>\n<li>\n<p>所有访存存在一个 Global total order，除了 Local bypass 以外，Load 读到的值就是这个全局序下同一个地址最接近的前一个 Store 的值。<sup>[3]</sup></p>\n<p>以上面具体的 CPU 一致性协议实现为例，定义某个访存行为“发生”的时刻是这个行为穿透到的最下级缓存拿到所需的 Grant 的 wall-clock 时刻，通过这个 wall-clock 时刻可以定义一个 Global total order。</p>\n<p>在这一定义下，忽然内存模型就 Sane 了很多，因为支持 MCA 的整个子系统可以当成一大块儿黑箱，这个黑箱的行为很像一个单独的，可能乱序处理的缓存。Operational model 也非常好定义了，每个 Agent 局部有个 store buffer，然后连接到一个共享存储上，Store buffer 到这个存储的请求发送可能乱序。因为用着方便，RVWMO 的形式化 Spec 直接就规定有这样一个 Global total order。</p>\n<p>特别注意，这里虽然有个 Global total order，但这不是 Total store order，TSO 要求 Global total order 和 PO 一致，也就是上述这个看上去像单独一个缓存的黑箱不能乱序处理了。</p>\n</li>\n<li>\n<p>Acq/Rel semantics <em>mostly likely</em> 好处理一些了。\nMCA 是子系统顺序处理访存请求的前提，如果连 MCA 都没有，那肯定是不保序的。所以根据<a href=\"/post/hardware-fences\">之前文章</a>的讨论，如果 Master 现在要处理一个 Barrier，有两（三）个选择：</p>\n<ol>\n<li>把 Barrier 通过总线灌下去，让下级缓存处理。</li>\n<li>通过某种方式“等待访存结束”，并且等待的访存完成回应必须有效，也就是必须能保证这个访存真的执行完了，效果扩散足够广泛（e.g. 保证全局可见了）。</li>\n<li>决定躺平，把自己也划成不支持 MCA 的一部分，让自身的 Master 通过（2）处理。</li>\n</ol>\n<p>因此，在 Pre-ARMv8 时代，总线不一定有 MCA，所以 CHI 总线 (CHI-A 版本) 是有 Barrier 的</p>\n<p>In contrast, 如果有 MCA，虽然因为可能请求还是会乱序因此还是需要进行额外同步，但是 (2) 中的有效“回应”会非常好构造，通常就是写入请求在总线上的回应信号，在 CPU 经典的一致性协议中，这个回应带有 Grant，也就保证了全局可见性。在 ARMv8 之后因为直接要求了所有外设和总线 IP 都必须保证 MCA，Barrier 就被 Deprecate 了<sup>[4]</sup>，Barrier 全部在请求源头处理，处理方式是 (2)。</p>\n<p>Remark: ARM 关于 MCA 的文档<sup>[1]</sup>中看似混淆了两个概念：缺乏 MCA 和缺乏有效的访存完成回应。这可能是由于通常的破坏 MCA 的方法同时也会破坏有效的访存完成回应，这些方法将在下面讨论。严格来说，即使缺乏 MCA，如果一个 Master 可以确定什么时候一个访存变得全局可见了，那么也可以通过等待达成全局可见来实现 Barrier，进而实现 Acq/Rel semantics。</p>\n</li>\n</ol>\n<h2>放松</h2>\n<p>[5] 中讨论了两种可能破坏 MCA 的常见的优化方法：</p>\n<ol>\n<li>\n<p>允许在除了 L1DC 以外的更下级缓存添加 Store buffer。这样不仅发送写的核心本身可以提前观测到，相邻的共享同一级缓存的核心也可以提前看到这个写了。</p>\n<p>为了让这个优化有用，请求进入 Store buffer 之后就会发送回应了，这个回应是无效的。如果要等待写真的进入缓存之后再发回应，那就和普通的总线上加个 Buffer 基本无异，只是多了一个对相邻核心的 S-L Bypass，而且还没有额外同步，很难想象什么时候这是有用的。</p>\n<p>Remark: 这指明了一个坑：如果 SMT 共享了 Store buffer 但是没有做隔离，那么会破坏 MCA。所幸此时外面的缓存结构还是保证 MCA 的，所以访存回应还是有效的，可以通过传统的清空 Store buffer + 等待回应进行同步。</p>\n</li>\n<li>\n<p>允许缓存在没有收到所有 Probe 的情况下提前回应 Grant。这会导致整个缓存层级中可能在同一时刻在不同位置对同一行读出来不同值，并且如果允许总线上消息乱序的话，是很容易打破 MCA 的。</p>\n<p>此时，也许可以将写回应拆成两个：发送 Grant 以及完成 Probe，Barrier 可以通过后者同步。此外这也说明缓存如何 Co-operatively 处理 Barrier，也就是上面提到的方法 (1)：等待下级缓存对之前所有请求完成 Probe 的回应，以及本级缓存自己收到了所有之前请求所需的 Probe。</p>\n<p>总线上不允许消息换序的话，疑似是能够保持 MCA 的。但是这里有很多具体的细节，例如不同类别的消息（Grant vs. Probe）是否也必须保序传递（这会影响能不能不等待 GrantAck 就抢发 Probe），还是说只保证同一个类型，甚至同一个 ID。总之，需要确认的是进行 Grant 仲裁的器件所确定的序，能否反映到所有上级缓存上。</p>\n</li>\n</ol>\n<hr />\n<p>[1] https://developer.arm.com/documentation/ka002179/latest/</p>\n<p>[2] https://github.com/riscv/riscv-isa-manual/issues/1205#issuecomment-1913698656</p>\n<p>[3] 此事 A primer on memory consistency 亦有提及</p>\n<p>[4] https://developer.arm.com/documentation/101569/0100/Functional-description/Transaction-handling/Barriers</p>\n<p>[5] Christopher Pulte, Shaked Flur, Will Deacon, Jon French, Susmit Sarkar, and Peter Sewell. 2017. Simplifying ARM concurrency: multicopy-atomic axiomatic and operational models for ARMv8. Proc. ACM Program. Lang. 2, POPL, Article 19 (January 2018), 29 pages. <a href=\"https://doi.org/10.1145/3158107\">https://doi.org/10.1145/3158107</a></p>\n","plain":"之前关于硬件 Fences的文章中简单提及了丢失 Multi-copy atomicity 之后可能带来的麻烦，本文具体讨论一下 Multi-copy atomicity，其硬件实现及后果。\n\n定义\nMCA 这个概念本身一开始其实大家不怎么集中讨论，直到 ARMv8 made it popular[1]。According to [1][2], Multi-copy atomicity (MCA) 的定义其实不是很统一，本文遵从 [2] 中的非正式定义，因为这是现在 ARMv8, RISC-V 和 x86 及 TL, CHI 和 ACE 都遵从的定义，即 Multi-copy atomicity 指：\n- 除了本地以外，一个写在所有其他 Agent 看来同时生效。\n- 执行这个写的 Agent 本身可以提前看到它。\n在并行系统中，“同时”事实上是一个不太好定义的东西，因为实际上即使遵从 MCA 的系统在实际执行中对不同位置的写也是并行处理的，这好像不太“原子”。更形式化的说法应该是：\n- 除了参与写的 Agent 以外，所有其他 Agent 对于多个写存在一个一致的观测顺序。\n也就是某个写不能“出现在一个 Agent 处太晚，结果排到了另一个写后面”。\n\n实现\n首先，如果硬件本身拓扑足够简单，那么 MCA 是 Free 的。例如所有核心没有 L1，共享 L2，一个 Store buffer 打到 L2 上，那在核心看起来访存就是 MCA 的。当拓扑更加麻烦，例如存在多级缓存，或者存在 Slices，那就需要总线协议额外打补丁。\n传统的 CPU 缓存层级中的一致性协议是最经典的在一个原生不支持 MCA 的拓扑上实现一个 MCA 系统的方式。最重要的观察是，因为 Writer 在执行写入的时候一定持有 Exclusive 权限，因此在一致性域内，除了 Agent 自用的局部 Store buffer 以外， 在某个特定时间，所有可以回应读取的器件里面，同一行的值肯定是一样的。 对于 Tilelink 而言，就是所有 Thunk Tip 和 Branch 状态的缓存。对于其他 MESI 缓存，所有的 M/E/S 状态并且自己上级没有 M/E 状态的缓存。\n这样所有的写入的顺序可以被整个系统 Agrees on。准确来说，写生效的时刻可以认为是最终写穿透到达的缓存拿到 Grant 的时刻，原子性由任何时刻在整个缓存层级中同一行在任何地方读到的值都相同而保证。写生效的顺序也可以直接通过这件事情发生的 wall-clock 时间定义。\n\n影响\n如果一个系统保证 MCA，例如某个 ISA 对软件保证 MCA，或者某个总线协议对 Master 保证 MCA，那么内存模型会简化非常多。有两个很直接的结果：\n- 所有访存存在一个 Global total order，除了 Local bypass 以外，Load 读到的值就是这个全局序下同一个地址最接近的前一个 Store 的值。[3]\n以上面具体的 CPU 一致性协议实现为例，定义某个访存行为“发生”的时刻是这个行为穿透到的最下级缓存拿到所需的 Grant 的 wall-clock 时刻，通过这个 wall-clock 时刻可以定义一个 Global total order。\n在这一定义下，忽然内存模型就 Sane 了很多，因为支持 MCA 的整个子系统可以当成一大块儿黑箱，这个黑箱的行为很像一个单独的，可能乱序处理的缓存。Operational model 也非常好定义了，每个 Agent 局部有个 store buffer，然后连接到一个共享存储上，Store buffer 到这个存储的请求发送可能乱序。因为用着方便，RVWMO 的形式化 Spec 直接就规定有这样一个 Global total order。\n特别注意，这里虽然有个 Global total order，但这不是 Total store order，TSO 要求 Global total order 和 PO 一致，也就是上述这个看上去像单独一个缓存的黑箱不能乱序处理了。\n\n- Acq/Rel semantics mostly likely 好处理一些了。 MCA 是子系统顺序处理访存请求的前提，如果连 MCA 都没有，那肯定是不保序的。所以根据之前文章的讨论，如果 Master 现在要处理一个 Barrier，有两（三）个选择：\n- 把 Barrier 通过总线灌下去，让下级缓存处理。\n- 通过某种方式“等待访存结束”，并且等待的访存完成回应必须有效，也就是必须能保证这个访存真的执行完了，效果扩散足够广泛（e.g. 保证全局可见了）。\n- 决定躺平，把自己也划成不支持 MCA 的一部分，让自身的 Master 通过（2）处理。\n因此，在 Pre-ARMv8 时代，总线不一定有 MCA，所以 CHI 总线 (CHI-A 版本) 是有 Barrier 的\nIn contrast, 如果有 MCA，虽然因为可能请求还是会乱序因此还是需要进行额外同步，但是 (2) 中的有效“回应”会非常好构造，通常就是写入请求在总线上的回应信号，在 CPU 经典的一致性协议中，这个回应带有 Grant，也就保证了全局可见性。在 ARMv8 之后因为直接要求了所有外设和总线 IP 都必须保证 MCA，Barrier 就被 Deprecate 了[4]，Barrier 全部在请求源头处理，处理方式是 (2)。\nRemark: ARM 关于 MCA 的文档[1]中看似混淆了两个概念：缺乏 MCA 和缺乏有效的访存完成回应。这可能是由于通常的破坏 MCA 的方法同时也会破坏有效的访存完成回应，这些方法将在下面讨论。严格来说，即使缺乏 MCA，如果一个 Master 可以确定什么时候一个访存变得全局可见了，那么也可以通过等待达成全局可见来实现 Barrier，进而实现 Acq/Rel semantics。\n\n\n放松\n[5] 中讨论了两种可能破坏 MCA 的常见的优化方法：\n- 允许在除了 L1DC 以外的更下级缓存添加 Store buffer。这样不仅发送写的核心本身可以提前观测到，相邻的共享同一级缓存的核心也可以提前看到这个写了。\n为了让这个优化有用，请求进入 Store buffer 之后就会发送回应了，这个回应是无效的。如果要等待写真的进入缓存之后再发回应，那就和普通的总线上加个 Buffer 基本无异，只是多了一个对相邻核心的 S-L Bypass，而且还没有额外同步，很难想象什么时候这是有用的。\nRemark: 这指明了一个坑：如果 SMT 共享了 Store buffer 但是没有做隔离，那么会破坏 MCA。所幸此时外面的缓存结构还是保证 MCA 的，所以访存回应还是有效的，可以通过传统的清空 Store buffer + 等待回应进行同步。\n\n- 允许缓存在没有收到所有 Probe 的情况下提前回应 Grant。这会导致整个缓存层级中可能在同一时刻在不同位置对同一行读出来不同值，并且如果允许总线上消息乱序的话，是很容易打破 MCA 的。\n此时，也许可以将写回应拆成两个：发送 Grant 以及完成 Probe，Barrier 可以通过后者同步。此外这也说明缓存如何 Co-operatively 处理 Barrier，也就是上面提到的方法 (1)：等待下级缓存对之前所有请求完成 Probe 的回应，以及本级缓存自己收到了所有之前请求所需的 Probe。\n总线上不允许消息换序的话，疑似是能够保持 MCA 的。但是这里有很多具体的细节，例如不同类别的消息（Grant vs. Probe）是否也必须保序传递（这会影响能不能不等待 GrantAck 就抢发 Probe），还是说只保证同一个类型，甚至同一个 ID。总之，需要确认的是进行 Grant 仲裁的器件所确定的序，能否反映到所有上级缓存上。\n\n---\n[1] https://developer.arm.com/documentation/ka002179/latest/\n[2] https://github.com/riscv/riscv-isa-manual/issues/1205#issuecomment-1913698656\n[3] 此事 A primer on memory consistency 亦有提及\n[4] https://developer.arm.com/documentation/101569/0100/Functional-description/Transaction-handling/Barriers\n[5] Christopher Pulte, Shaked Flur, Will Deacon, Jon French, Susmit Sarkar, and Peter Sewell. 2017. Simplifying ARM concurrency: multicopy-atomic axiomatic and operational models for ARMv8. Proc. ACM Program. Lang. 2, POPL, Article 19 (January 2018), 29 pages. https://doi.org/10.1145/3158107\n"},{"metadata":{"id":"hardware-fences","lang":"zh-CN","title":"Fences 的硬件实现","tags":["微架构","Fences"],"publish_time":"2025-05-02T19:13:26+08:00","update_time":"2025-07-20T15:33:33+08:00","title_outline":{"groups":[{"chars":[{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Fences","hadv":3617,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"硬","components":[["M 145 -759C 128 -566 89 -347 16 -196L 29 -187C 169 -334 253 -521 284 -743L 284 -759Z",[0.232,0.748]],["M 24 -759L 32 -731L 412 -731C 426 -731 437 -736 440 -747C 398 -786 327 -842 327 -842L 265 -759Z",[0.801,0.061]],["M 217 -485L 230 -485L 162 -511L 97 -414L 97 41L 119 41C 180 41 217 14 217 5Z",[0.02,0.773]],["M 158 -485L 158 -457L 337 -457L 337 -485Z",[0.705,0.008]],["M 158 -101L 158 -73L 337 -73L 337 -101Z",[0.842,0.0]],["M 276 -485L 276 -1L 297 -1C 338 -1 398 -26 399 -33L 399 -440C 417 -443 429 -451 435 -459L 322 -545L 266 -485Z",[0.009,0.755]],["M 612 -759L 612 -358C 612 -147 569 -19 316 85L 322 94C 705 17 747 -147 747 -360L 747 -759Z",[0.155,0.743]],["M 433 -759L 441 -731L 957 -731C 972 -731 983 -736 986 -747C 942 -789 866 -850 866 -850L 800 -759Z",[0.81,0.084]],["M 436 -614L 436 -216L 458 -216C 521 -216 558 -236 558 -245L 558 -586L 807 -586L 807 -231L 829 -231C 895 -231 935 -253 935 -258L 935 -577C 958 -581 967 -588 974 -596L 862 -682L 803 -614L 569 -614L 436 -664ZM 498 -464L 498 -436L 863 -436L 863 -464ZM 498 -307L 498 -279L 863 -279L 863 -307Z",[0.306,0.034]],["M 517 -231L 506 -224C 568 -24 697 50 893 95C 905 30 937 -15 990 -32L 989 -44C 785 -51 594 -86 517 -231Z",[-0.626,0.269]]],"bbox":{"top":-850,"bottom":95,"left":16,"right":990},"hadv":1000}],"text":"硬","hadv":1000,"breakAfter":true},{"chars":[{"char":"件","components":[["M 192 -854C 160 -664 87 -465 14 -339L 25 -332C 162 -431 264 -572 336 -767C 360 -765 373 -773 378 -785Z",[0.321,0.659]],["M 138 -522L 138 93L 165 93C 222 93 281 63 283 53L 283 -527C 303 -531 311 -538 314 -547L 191 -592Z",[0.011,0.78]],["M 389 -800C 377 -650 343 -483 305 -372L 317 -365C 412 -452 481 -574 530 -723C 553 -723 566 -731 570 -744Z",[0.235,0.644]],["M 306 -324L 314 -296L 960 -296C 975 -296 986 -301 989 -312C 941 -357 858 -425 858 -425L 785 -324Z",[0.87,0.063]],["M 403 -595L 403 -567L 932 -567C 946 -567 957 -572 960 -583C 914 -626 835 -691 835 -691L 765 -595Z",[0.804,0.019]],["M 567 -842L 567 94L 598 94C 655 94 718 66 718 54L 718 -795C 747 -799 753 -810 756 -824Z",[0.009,0.825]]],"bbox":{"top":-854,"bottom":94,"left":14,"right":989},"hadv":1000}],"text":"件","hadv":1000,"breakAfter":true},{"chars":[{"char":"实","components":[["M 170 -743L 160 -743C 161 -704 116 -667 84 -652C 42 -634 11 -597 24 -546C 40 -492 106 -473 145 -496C 199 -528 224 -619 170 -743Z",[0.171,0.314]],["M 662 -617L 466 -634C 465 -297 489 -83 24 82L 30 95C 625 -23 616 -247 626 -589C 649 -593 660 -602 662 -617Z",[0.325,0.62]],["M 818 -365L 741 -257L 56 -257L 64 -229L 927 -229C 942 -229 954 -234 957 -245C 906 -293 818 -365 818 -365Z",[0.899,0.048]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 170 -453L 164 -448C 202 -410 240 -349 250 -290C 384 -206 491 -461 170 -453Z",[-0.27,0.26]],["M 244 -618L 237 -612C 271 -578 307 -520 316 -467C 439 -390 540 -622 244 -618Z",[-0.187,0.226]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 512 -188L 509 -178C 648 -96 756 17 795 79C 937 157 1059 -145 512 -188Z",[-0.529,0.36]],["M 780 -680L 791 -680C 790 -638 784 -567 777 -520L 783 -514C 834 -541 899 -587 937 -622C 958 -623 968 -626 976 -635L 851 -752Z",[-0.442,0.364]]],"bbox":{"top":-871,"bottom":157,"left":11,"right":1059},"hadv":1000}],"text":"实","hadv":1000,"breakAfter":true},{"chars":[{"char":"现","components":[["M 9 -125L 81 34C 94 29 104 18 108 4C 252 -91 348 -167 406 -218L 404 -227C 242 -181 75 -139 9 -125Z",[0.589,0.284]],["M 303 -838L 238 -749L 16 -749L 24 -721L 391 -721C 405 -721 416 -726 419 -737C 376 -778 303 -838 303 -838Z",[0.608,0.079]],["M 325 -541L 278 -460L 28 -460L 36 -432L 381 -432C 395 -432 404 -437 407 -448C 379 -484 325 -541 325 -541Z",[0.72,0.084]],["M 269 -746L 130 -746L 130 -90L 269 -130Z",[0.006,0.782]],["M 773 -661L 601 -676C 600 -310 627 -86 244 77L 252 91C 745 -36 729 -265 737 -633C 760 -636 770 -646 773 -661Z",[0.261,0.692]],["M 423 -827L 423 -224L 447 -224C 514 -224 554 -248 554 -257L 554 -746L 787 -746L 787 -236L 811 -236C 881 -236 925 -262 925 -269L 925 -735C 948 -739 959 -747 966 -756L 848 -848L 783 -774L 565 -774Z",[0.092,0.019]],["M 804 -326L 655 -339L 655 -30C 655 46 670 69 758 69L 822 69C 940 69 982 42 982 -5C 982 -27 977 -41 949 -54L 946 -188L 935 -188C 917 -129 901 -77 892 -60C 886 -50 882 -48 872 -47C 865 -47 852 -47 836 -47L 793 -47C 776 -47 773 -51 773 -63L 773 -301C 793 -304 802 -313 804 -326Z",[-0.198,0.323]]],"bbox":{"top":-848,"bottom":91,"left":9,"right":982},"hadv":1000}],"text":"现","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>最近在研究小栅栏。本文简单介绍一下注意到的普通的小栅栏的硬件实现注意事项。</p>\n<p>这里普通的小栅栏指普通的 Acquire / Release Fences，暂时先不考虑 SeqCst，将后续有文章具体讨论它。</p>\n<p>Acquire / Release semantics 的定义比较简单，在大多数 ISA / 编译器 / 高级语言实现中都是一致的，大概都会是如下形式：</p>\n<ul>\n<li>在线程 1 中，A 内存操作发生在 X Release Store “之前”</li>\n<li>在线程 2 中，B 内存操作发生在 Y Acquire Load “之后”</li>\n<li>Y 观测到 X 的值</li>\n<li>那么 B 必须发生在 A “之后”</li>\n</ul>\n<p>这里一堆 “之前之后” 取决于不同的层级，在这一系列事件中担当的职责，或者针对不同种类的指令定义有所不同。通常而言，同一个线程内的先后关系由 Program order 指定，不同线程之间的“先后关系”并不是全序，但是被确定的部分会反映到修改序或者观测序上，例如如果对同一个地址的 Store A 发生在 Load B 之前，那么 B 可能读到 A 的值，或者 A 之后，B 之前另一个 Store 的值。<sup>[1]</sup></p>\n<p>注意这里真正建立先后关系的是生效的 Rel-Acq 对。在处理器眼里，如果 Acq Ld 读到了 Rel St，那么这个“读到了”一定发生在某个硬件结构上，他自然有个先后关系：Rel St “先”在这个器件上生效了，Acq Ld “后”读到了这个器件上的值，Whatever it means。微架构实现 AMO 序的关键就在于把这个器件上“读到了”这个自然的先后关系沿着 Program order 在两个核心上向两侧扩展。</p>\n<p>因此本文接下来讨论的主要是两件事儿：</p>\n<ul>\n<li>怎么扩展 Program order</li>\n<li>More subtly, 怎么捕捉这个“读到了”的先后关系，把这个序变成一个可以扩展的基础</li>\n</ul>\n<h2>AMO 操作的实现框架</h2>\n<p>写锁的时候通常不会直接用 Fence，原因是 AMO 写起来直觉多了，而且大多数时候只有一个 Sentinel，所以同步操作可以和某个特定的内存地址/内存操作绑定。相比之下，Fence 的形式化定义会复杂很多，主要困难的地方就在于它没有像上文例子中一个绑定明确的，构成 Rel-Acq pair。然而在硬件实现上，通常是将 AMO + Order 实现为 Relaxed AMO + Fence 副作用，这里 Fence 副作用指影响不同访存指令的生效顺序。</p>\n<p>举个例子。RISC-V 微架构实现 Acquire Load 的时候，通常会执行这个 Load，然后等待 Load queue 全部清空（或者如果 L1 保证顺序处理请求，全部发往 L1）。这个正好和进行一个普通的 Load，然后进行一个 <code>fence.r.rw</code> 是一样的。</p>\n<p>之所以这么做，是因为硬件上本来已经知道了 Program order，但是现代处理器会做很多优化，导致动态执行时，内存操作生效的真实顺序和 Program order 不同。所以硬件实现“用 Program order 扩展先后关系”，其实是“保持生效顺序和 Program order 一致”，因此所有的 Ordering 会变成类似 Fence 的操作是自然的。</p>\n<p>考虑到 Rel 和写入绑定，Acq 和读取绑定<sup>[2]</sup>，因此最终硬件需要做的是这两件事情<sup>[3]</sup>：</p>\n<ul>\n<li>对于 Rel Fence，保证<strong>之后发生的写</strong>都在之前发生的任意访存之后生效：保证 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>→</mo><mi>W</mi><mo separator=\"true\">,</mo><mi>W</mi><mo>→</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">R \\to W, W \\to W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 顺序</li>\n<li>对于 Acq Fence，保证<strong>之前发生的读</strong>都在之后发生的任意访存之前生效：保证 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>→</mo><mi>W</mi><mo separator=\"true\">,</mo><mi>R</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">R \\to W, R \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 顺序</li>\n</ul>\n<h2>硬件保持顺序的实现</h2>\n<p>考虑一个典型的乱序处理器架构。硬件中缓存层级的存在，导致每一个访存操作通常是沿着多级执行/缓存结构发放下去的，而唯一知道 Program order 的器件是 LSU，它可以看到 ROB Index。</p>\n<p>如下描述中，“下级”指更接近主存，例如 Store buffer 是 LSU 下级，L2 是 L1DC 下级。下级对应系统中更广泛的可见范围，例如 L1DC 只在本核心可见，LLC 在所有 Coherent core 可见。</p>\n<p>如下列表基本涵盖了每一级器件的不同选择：</p>\n<ul>\n<li>(1) 如果下级器件唯一，并且可以保证生效顺序保持接受请求的顺序，那么可以由 Fence 同步下级<strong>接收请求</strong>的顺序，Fence 不发往下一级。\n<ul>\n<li>Note: 如果总线保序，由 Fence 同步发送请求的顺序即可。总线不保序的典型例子：Congestion-aware Routing NoC</li>\n</ul>\n</li>\n<li>(2) 如果下级器件不唯一，或不能保证生效顺序保持接受请求的顺序，那么有两个选择：\n<ul>\n<li>(2.i) 如果下级器件都可以保证产生一个回应，能够有效刻画这个请求的在系统全局的生效情况（e.g. 收到回应的时候保证已经生效了），那么可以由 Fence 同步下级<strong>完成请求</strong>的顺序。Fence 不发往下一级。</li>\n<li>(2.ii) 由下级器件协助执行 Fence。</li>\n</ul>\n</li>\n</ul>\n<p>导致实现会这么复杂，是因为存在一些常见的坑，总体而言有两个：Multi-copy atomicity 和提交保序。</p>\n<h3>NUMA / LLC Slices</h3>\n<details>\n<summary>2025-07-20 更新说明</summary>\n<p>在更新前，本段文字对于 MCA 的说明不准确。即使在存在写请求<strong>到达</strong>不同 Coherence home 的延迟不同，只要要求写 Ack 保证写全局可见即可，这个系统依旧是保持 MCA 的。特别地，即使 Unified LLC 的系统中，如果 NoC 存在任何动态路由，都可能导致请求换序。</p>\n</details>\n<p>考虑一个 NUMA 结构，LLC 有多个 Slice，不同的 L2 到不同的 Slice 的延迟不同。这个时候，即使总线保证每个器件按顺序处理请求<sup>[5]</sup>，也无法只通过发送顺序进行同步，因为这个请求真正到达对应 Slice 的时间可能不同。常见的总线协议会通过写回应保证某个写一定生效，但是也存在系统不包含写回应，或者写回应收到时并不能保证所有系统内的 Agent 都可以读到写入的数据<sup>[10]</sup>。用 AMBA 的术语，这一系统中的访存缺乏 Multi-copy atomicity。一个后果是不同的写可能会以不同顺序被不同核心观测到。</p>\n<p>考虑如下例子：</p>\n<pre><code>Initial\n[x] = [lock] = 0\n\nTh 0               Th 1\nST [x] &lt;- 1        LD L &lt;- [lock]\nFence Release      Fence Acquire\nST [lock] &lt;- 1     LD R &lt;- [x]\n</code></pre>\n<p>如果 <code>lock</code> 的 Home line 距离 Th 0 更近，[x] 距离 Th 1 更近，那么如果只保证 L2 发往各个 LLC Slice 的顺序和 Program order 一致，也可能会发生 <code>R = 0, L = 1</code> 的结果。加个 <code>if</code> 也不行（分支预测 Yes！）。注意到，这里由于缓存是一个层级结构，LLC 有多个 Slice 导致了 L2 本身无法保证请求按顺序生效，因此要不然 L2 本身需要 Fence-aware，要不然上级结构需要根据 L2 的回应进行同步。</p>\n<p>关于 Multi-copy atomicity 的实现和影响将也会有<a href=\"mca\">后续文章</a>讨论。无论如何，在总线缺乏 MCA 的情况下，肯定需要在某一级 Block 请求了，最简单的方法是所有级别都不 Fence aware，直接在 LSU 上一把大锁：Fence 等待先前的所有请求完成之后，再开始之后的请求。</p>\n<p>然而检测访存完成也需要小心处理。等待请求完成需要依赖“完成”是准确有效的。Load 的完成是自然的，因为 Load 有一个返回值，当这个值回到 LSU 自然整个访存子系统都完成了。<small>什么？Load value prediction？唉搞微架构的，下次聊</small></p>\n<p>对于写入，常见架构设计上是一个 Fire-and-forget 的设计，提交到 Store buffer 内就是胜利，认为就全局生效了，实际上并没有。如果外面的缓存不支持 MCA，那么需要有特殊的 Barrier 消息，或者等待总线上保证全局可见的 Ack<sup>[6]</sup>。</p>\n<h3>Request reorder</h3>\n<p>那么如果总线和 L1 外面的缓存层级保证 MCA 呢？所幸 RV (Tilelink) 和 ARMv8 (AMBA) 都保证 MCA。然而即使有 MCA，也需要考虑可能把请求交换顺序的地方，保证了原子性也可以把整个两大块儿副作用完全交换顺序，例如 Tilelink。</p>\n<p>在总线以内，如果 Store buffer 到 L1 这段结构可以保持生效顺序，由于唯一一个需要保持的 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mo>∗</mo></mrow><annotation encoding=\"application/x-tex\">W \\to *</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4653em;\"></span><span class=\"mord\">∗</span></span></span></span> 序是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">W \\to W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 序，这部分请求会全部经过 Store buffer，那么这段结构至少也许至少不需要做额外处理。麻烦的是，有两个经典的设计会打乱这两个结构中的请求处理顺序：Write buffer coalescing 和 MSHR out-of-order issue。</p>\n<p>因此，即使总线具有 MCA，LSU 还是需要分别阻止总线上可能发生的请求交换顺序的情况。</p>\n<ul>\n<li>如果总线或者 L2 及以下的结构可以交换请求顺序，那么还是得在 L1 MSHR 这里跟踪一下请求的完成情况，这也许就是最好的做法</li>\n<li>如果总线是保序的，那么 LSU 还是得处理一下 Store buffer 和 L1 的顺序问题。当然，LSU 自己的请求提交顺序也要保证。下面具体讨论一下上述的两个经典设计：</li>\n</ul>\n<h3>Write buffer coalescing</h3>\n<p>因为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 序不被保证，所以按顺序处理的 (Committed) write buffer 是无须清空的。但是如果 Write buffer 可能合并请求的话，那就可能导致 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">W \\to W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 序被打破，此时进行 Release fence 时 Write buffer 需要清空，或者至少等到不存在可能合并的行之后再 enqueue。</p>\n<p>在 MICRO 2024 现场看到了一个非常有趣的论文，通过修改 Coherence protocol 解决了这个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>W</mi></mrow><annotation encoding=\"application/x-tex\">W \\to W</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span></span></span></span> 保序的问题，有兴趣的同学可以阅读。<sup>[4]</sup></p>\n<h3>MSHR scheduling</h3>\n<p>另一个可能出现的问题是，MSHR Scheduling 也可能不会遵循一开始进入该级缓存的顺序。还是上面那个锁的例子中：</p>\n<pre><code>Initial\n[x] = [lock] = 0\n\nTh 0               Th 1\nST [x] &lt;- 1        LD L &lt;- [lock]\nFence Release      Fence Acquire\nST [lock] &lt;- 1     LD R &lt;- [x]\n</code></pre>\n<p>如果只清空了 Write buffer, 那么最极端的情况下可能发生的事情是，Th 0 的 L1DC 中 <code>x, lock</code> 都 Miss，进入 MSHR，先发送 <code>lock</code> 的 Probe, 完成，Replay 也完成，之后被 Th 1 一侧 Probe 回去，完成写回，在这段时间中 <code>x</code> 的 Probe 一直没有发生，因此随后 Th 1 中的 <code>x</code> 无论是 Hit 还是从 LLC Refill，都可以有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>R</mi><mo>=</mo><mn>0</mn><mo separator=\"true\">,</mo><mi>L</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">R = 0, L = 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span>。</p>\n<p>因此，在 MSHR 可能被乱序 Sequence 时，LSU &amp; L1DC 通常需要做两件事情：</p>\n<ol>\n<li>MSHR 在总线给出回应时再释放。由于一般 L1 设计都是 Write-allocate 的，MSHR 需要等待 Refill 结果，所以这里会更类似读取的回应。</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mo>∗</mo></mrow><annotation encoding=\"application/x-tex\">W \\to *</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4653em;\"></span><span class=\"mord\">∗</span></span></span></span> Fence 等待 MSHR 清空。</li>\n</ol>\n<p>Alternatively, Write buffer 当 Miss 的时候等待 Refill 完成再释放，相当于 Store buffer 做 Replay，那等待 Store buffer 清空就好了。这一设计在 TSO 上更常见一点。</p>\n<h3>Termination?</h3>\n<p>如果需要保序的两个请求有一个请求在某一级缓存终止了，但是这一级缓存不是 LLC，那它的全局可见性如何呢？</p>\n<p>对于 Fully-coherent cache，这个问题不大。在某一级缓存终止代表这一级缓存持有足够强的权限，这一请求的全局可见性及其相关的序会由一致性协议保证——虽然这里也有一些坑，一致性协议本身必须有足够强的序。<sup>[7]</sup></p>\n<p>对于不 Coherent 的缓存，例如 GPU，通常需要这个操作一直穿透到有一致性的地方，比如 GPU 的所有 Store 都需要一直写到 L2。</p>\n<h2>“读取”序与 Coherence</h2>\n<p>最后简单讨论一下 Rel-Acq 对之间读取关系的序是怎么建立的。注意到，由于 Acq Ld 读取到了 Rel St 的值，因此 Acq Ld 的生效时间一定不早于 Rel St 的生效时间，在 Rel-Acq 对前后扩展其他内存操作时根据生效即可扩展出其他内存操作之间生效的先后关系。</p>\n<p>如果再靠近一些硬件实现，并且放松一些，Acq Rl 的<strong>结束</strong>一定晚于 Rel St <strong>开始</strong>。因此在最暴力的实现中，直接等待前序指令完全结束，再开始执行后续指令是正确的。</p>\n<hr />\n<div class=\"footnotes\">\n[1] 在三个 Context 下具体讨论一下这些都在鬼扯什么：\n<p><strong>首先讨论在 C++ 标准中的定义。</strong> 以下章节号以 <a href=\"https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4917.pdf\">N4917 C++26 Draft</a> 为准，因为穷学生买不起标准。</p>\n<p>C++ 执行的单位是表达式，因此 Program order 这里其实指 “Sequenced before” 关系。“Happens before” 的定义正好就是我们这里的“先后关系”，由 “Sequenced before” 和 “Inter-thread happens before” 取并，后者刻画了跨线程的先后关系。“Inter-thread happens before” 关系生成时用到的 “Synchronized with” 包含了例子中生效的 Rel-Acq 对。这些定义全部来自 6.9.2.2 [intro.races] Paragraph (10).</p>\n<p>关于这个先后关系怎么反映到副作用的最终效果和表达式的求值结果上，见同一节 Paragraph (14 - 20)。特别地，对于<strong>同一个</strong>原子对象，Modification order 是一个全序(6.9.22 [intro.races] Paragraph 4)。<strong>同一个</strong>这个条件非常关键，</p>\n<p><strong>其次，讨论一下 RISC-V 中的定义。</strong> RVWMO 是好东西，定义了一个 Global memory order，概念上比较简单：写就是写生效的时刻，读取需要根据 Bypass 决定是否需要根据写向后延迟。这里先后关系直接就是这个 Global memory order 上的序了。因为 Rel-Acq pair 有一个“读取到”的关系，它直接固定了这两个访存在 Global memory order 上的相对位置，随后通过 Preserved Program Order 在两侧扩展 Program Order。</p>\n<p><strong>最后，讨论一下在 NVIDIA PTX 中的定义。</strong> NVIDIA PTX 属于一个不上不下的环境，它到硬件上还需要编译一次。PTX 的内存序定义中，通过 Rel-Acq pair / chain 生成的关系称作 Causality order，Coherence order 指所有对相同地址写入的一个全序。要求 Causality order 是 Coherence order 的子集，并且和 read from / from read (read before) 兼容。这里有点麻烦的地方是由于 PTX 的内存模型允许 Non-coherent caches，所以引入了 Scope 的概念，指令内部编码可见域，然后生成 Causality order 的时候只能用互相可见的 Rel-Acq pair。具体见 NV 的文章<sup>[8]</sup></p>\n<p>[2] Fences 也是这样的。 C++ 标准见 33.5.11 [atomics.fences]，RV 里 <code>fence.aq</code> 和 <code>fence.rl</code> 分别是 <code>fence.r.rw</code> 和 <code>fence.rw.w</code> 的别名。这里有一点有趣的地方，就是因为 Rel 和 Acq 一个是挡前面，一个是挡后面，如果真的用 Fence 写的话，需要挂到 AMO 不同的两侧，Rel Fences 挂前面，Acq Fences 挂后面。这个可以参考 NV 的论文中对于 Acquire / Release Pattern 的定义，以及查看 PTX <code>ld.acquire</code> / <code>st.release</code> 编译出的 SASS 指令，可以对其他一些拧巴底层原因略窥一二。</p>\n<p>[3] Remark: 注意到上述的这些 AMO 操作或者 Fence 中没有任何一个会保证 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> 顺序，这也是为什么在 x86-TSO 上除了 SeqCst 操作其他所有序都是 No-op，因为 x86-TSO 只会违背 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>W</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding=\"application/x-tex\">W \\to R</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">W</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span></span></span></span> PO 序。但是 SeqCst 在各种各样地方上的定义都不太一样，具体在属于它的那篇文章再细节讨论把…</p>\n<p>[4] J. M. Cebrian, M. Jahre and A. Ros, “Temporarily Unauthorized Stores: Write First, Ask for Permission Later,” 2024 57th IEEE/ACM International Symposium on Microarchitecture (MICRO), Austin, TX, USA, 2024, pp. 810-822, doi: <a href=\"https://doi.org/10.1109/MICRO61859.2024.00065\">10.1109/MICRO61859.2024.00065.</a></p>\n<p>[5] 比如 AXI。In contrast, Tilelink 不保证 (SiFive Tilelink Spec 1.9.3, 6.5 P45)</p>\n<p>[6] CHI-A 是一个不保证 Mdan但有特殊 Barrier 的总线。相比下，CHI-B 要求了 MCA 并且 Deprecate 了 Barrier 消息。对于 Ack 所保证的全局可见性，可以参考 SiFive Tilelink Spec 1.9.3, 6.5 P45 要求回应必须有效反应请求的生效情况，并且如果已经给出一个请求回应，后续收到的请求生效一定在前面已给出回应的请求之后。</p>\n<p>[7] 这里“足够强”指的是内存一致性协议必须有效保证各种序，尤其是 Coherence order 是成立的，例如 Tilelink 中需要一个 E channel 发送 GrantAck，以避免总线上消息换序导致 Total coherence order 的丢失。如下是一个例子，在没有 GrantAck 时，两个 Master 都想要写权限，所有消息针对的是同一个 Block。</p>\n<pre><code>Master A            Slave              Master B\n                      &lt;--- Acquire --------\n    &lt;--- Probe -------\n    ---- ProbeAck ---&gt;\n    ---- Acquire ----&gt;\n                      -- Grant ----\\/-----&gt;\n                      -- Probe ----/\\\n                      &lt;- ProbeAck - | -----\n                                    \\-----&gt;\n    &lt;--- Grant -------\n</code></pre>\n<p>最后由 Master B 收到的 Grant 要不然完全不 Make sense，要不然就是两个 Master 都认为自己有写权限，但 Slave 觉得 B 没有。</p>\n<p>另一个可以考虑的假设情况是 Coherence master 不等待 ProbeAck 就下发 Grant，这个时候破坏的是 MCA。关于这点的简述见<sup>[9]</sup>。</p>\n<p>[8] Daniel Lustig, Sameer Sahasrabuddhe, and Olivier Giroux. 2019. A Formal Analysis of the NVIDIA PTX Memory Consistency Model. In Proceedings of the Twenty-Fourth International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS ’19). Association for Computing Machinery, New York, NY, USA, 257–270. <a href=\"https://doi.org/10.1145/3297858.3304043\">https://doi.org/10.1145/3297858.3304043</a></p>\n<p>[9] Christopher Pulte, Shaked Flur, Will Deacon, Jon French, Susmit Sarkar, and Peter Sewell. 2017. Simplifying ARM concurrency: multicopy-atomic axiomatic and operational models for ARMv8. Proc. ACM Program. Lang. 2, POPL, Article 19 (January 2018), 29 pages. <a href=\"https://doi.org/10.1145/3158107\">https://doi.org/10.1145/3158107</a></p>\n<p>[10] 一个例子是 PowerPC 下的共享 Store buffer。这可以导致 SMT 的邻居可以早于其他核心上的线程观测到一个写入。与之对比，x86-TSO 实际上要求 SMT 中的 Store buffer 必须拆分。</p>\n</div>","plain":"最近在研究小栅栏。本文简单介绍一下注意到的普通的小栅栏的硬件实现注意事项。\n这里普通的小栅栏指普通的 Acquire / Release Fences，暂时先不考虑 SeqCst，将后续有文章具体讨论它。\nAcquire / Release semantics 的定义比较简单，在大多数 ISA / 编译器 / 高级语言实现中都是一致的，大概都会是如下形式：\n- 在线程 1 中，A 内存操作发生在 X Release Store “之前”\n- 在线程 2 中，B 内存操作发生在 Y Acquire Load “之后”\n- Y 观测到 X 的值\n- 那么 B 必须发生在 A “之后”\n这里一堆 “之前之后” 取决于不同的层级，在这一系列事件中担当的职责，或者针对不同种类的指令定义有所不同。通常而言，同一个线程内的先后关系由 Program order 指定，不同线程之间的“先后关系”并不是全序，但是被确定的部分会反映到修改序或者观测序上，例如如果对同一个地址的 Store A 发生在 Load B 之前，那么 B 可能读到 A 的值，或者 A 之后，B 之前另一个 Store 的值。[1]\n注意这里真正建立先后关系的是生效的 Rel-Acq 对。在处理器眼里，如果 Acq Ld 读到了 Rel St，那么这个“读到了”一定发生在某个硬件结构上，他自然有个先后关系：Rel St “先”在这个器件上生效了，Acq Ld “后”读到了这个器件上的值，Whatever it means。微架构实现 AMO 序的关键就在于把这个器件上“读到了”这个自然的先后关系沿着 Program order 在两个核心上向两侧扩展。\n因此本文接下来讨论的主要是两件事儿：\n- 怎么扩展 Program order\n- More subtly, 怎么捕捉这个“读到了”的先后关系，把这个序变成一个可以扩展的基础\n\nAMO 操作的实现框架\n写锁的时候通常不会直接用 Fence，原因是 AMO 写起来直觉多了，而且大多数时候只有一个 Sentinel，所以同步操作可以和某个特定的内存地址/内存操作绑定。相比之下，Fence 的形式化定义会复杂很多，主要困难的地方就在于它没有像上文例子中一个绑定明确的，构成 Rel-Acq pair。然而在硬件实现上，通常是将 AMO + Order 实现为 Relaxed AMO + Fence 副作用，这里 Fence 副作用指影响不同访存指令的生效顺序。\n举个例子。RISC-V 微架构实现 Acquire Load 的时候，通常会执行这个 Load，然后等待 Load queue 全部清空（或者如果 L1 保证顺序处理请求，全部发往 L1）。这个正好和进行一个普通的 Load，然后进行一个 fence.r.rw 是一样的。\n之所以这么做，是因为硬件上本来已经知道了 Program order，但是现代处理器会做很多优化，导致动态执行时，内存操作生效的真实顺序和 Program order 不同。所以硬件实现“用 Program order 扩展先后关系”，其实是“保持生效顺序和 Program order 一致”，因此所有的 Ordering 会变成类似 Fence 的操作是自然的。\n考虑到 Rel 和写入绑定，Acq 和读取绑定[2]，因此最终硬件需要做的是这两件事情[3]：\n- 对于 Rel Fence，保证之后发生的写都在之前发生的任意访存之后生效：保证 R \\to W, W \\to W 顺序\n- 对于 Acq Fence，保证之前发生的读都在之后发生的任意访存之前生效：保证 R \\to W, R \\to R 顺序\n\n硬件保持顺序的实现\n考虑一个典型的乱序处理器架构。硬件中缓存层级的存在，导致每一个访存操作通常是沿着多级执行/缓存结构发放下去的，而唯一知道 Program order 的器件是 LSU，它可以看到 ROB Index。\n如下描述中，“下级”指更接近主存，例如 Store buffer 是 LSU 下级，L2 是 L1DC 下级。下级对应系统中更广泛的可见范围，例如 L1DC 只在本核心可见，LLC 在所有 Coherent core 可见。\n如下列表基本涵盖了每一级器件的不同选择：\n- (1) 如果下级器件唯一，并且可以保证生效顺序保持接受请求的顺序，那么可以由 Fence 同步下级接收请求的顺序，Fence 不发往下一级。- Note: 如果总线保序，由 Fence 同步发送请求的顺序即可。总线不保序的典型例子：Congestion-aware Routing NoC\n\n- (2) 如果下级器件不唯一，或不能保证生效顺序保持接受请求的顺序，那么有两个选择：- (2.i) 如果下级器件都可以保证产生一个回应，能够有效刻画这个请求的在系统全局的生效情况（e.g. 收到回应的时候保证已经生效了），那么可以由 Fence 同步下级完成请求的顺序。Fence 不发往下一级。\n- (2.ii) 由下级器件协助执行 Fence。\n\n导致实现会这么复杂，是因为存在一些常见的坑，总体而言有两个：Multi-copy atomicity 和提交保序。\n\nNUMA / LLC Slices\n在更新前，本段文字对于 MCA 的说明不准确。即使在存在写请求到达不同 Coherence home 的延迟不同，只要要求写 Ack 保证写全局可见即可，这个系统依旧是保持 MCA 的。特别地，即使 Unified LLC 的系统中，如果 NoC 存在任何动态路由，都可能导致请求换序。\n考虑一个 NUMA 结构，LLC 有多个 Slice，不同的 L2 到不同的 Slice 的延迟不同。这个时候，即使总线保证每个器件按顺序处理请求[5]，也无法只通过发送顺序进行同步，因为这个请求真正到达对应 Slice 的时间可能不同。常见的总线协议会通过写回应保证某个写一定生效，但是也存在系统不包含写回应，或者写回应收到时并不能保证所有系统内的 Agent 都可以读到写入的数据[10]。用 AMBA 的术语，这一系统中的访存缺乏 Multi-copy atomicity。一个后果是不同的写可能会以不同顺序被不同核心观测到。\n考虑如下例子：\nInitial\n[x] = [lock] = 0\n\nTh 0               Th 1\nST [x] <- 1        LD L <- [lock]\nFence Release      Fence Acquire\nST [lock] <- 1     LD R <- [x]\n\n如果 lock 的 Home line 距离 Th 0 更近，[x] 距离 Th 1 更近，那么如果只保证 L2 发往各个 LLC Slice 的顺序和 Program order 一致，也可能会发生 R = 0, L = 1 的结果。加个 if 也不行（分支预测 Yes！）。注意到，这里由于缓存是一个层级结构，LLC 有多个 Slice 导致了 L2 本身无法保证请求按顺序生效，因此要不然 L2 本身需要 Fence-aware，要不然上级结构需要根据 L2 的回应进行同步。\n关于 Multi-copy atomicity 的实现和影响将也会有后续文章讨论。无论如何，在总线缺乏 MCA 的情况下，肯定需要在某一级 Block 请求了，最简单的方法是所有级别都不 Fence aware，直接在 LSU 上一把大锁：Fence 等待先前的所有请求完成之后，再开始之后的请求。\n然而检测访存完成也需要小心处理。等待请求完成需要依赖“完成”是准确有效的。Load 的完成是自然的，因为 Load 有一个返回值，当这个值回到 LSU 自然整个访存子系统都完成了。什么？Load value prediction？唉搞微架构的，下次聊\n对于写入，常见架构设计上是一个 Fire-and-forget 的设计，提交到 Store buffer 内就是胜利，认为就全局生效了，实际上并没有。如果外面的缓存不支持 MCA，那么需要有特殊的 Barrier 消息，或者等待总线上保证全局可见的 Ack[6]。\n\nRequest reorder\n那么如果总线和 L1 外面的缓存层级保证 MCA 呢？所幸 RV (Tilelink) 和 ARMv8 (AMBA) 都保证 MCA。然而即使有 MCA，也需要考虑可能把请求交换顺序的地方，保证了原子性也可以把整个两大块儿副作用完全交换顺序，例如 Tilelink。\n在总线以内，如果 Store buffer 到 L1 这段结构可以保持生效顺序，由于唯一一个需要保持的 W \\to * 序是 W \\to W 序，这部分请求会全部经过 Store buffer，那么这段结构至少也许至少不需要做额外处理。麻烦的是，有两个经典的设计会打乱这两个结构中的请求处理顺序：Write buffer coalescing 和 MSHR out-of-order issue。\n因此，即使总线具有 MCA，LSU 还是需要分别阻止总线上可能发生的请求交换顺序的情况。\n- 如果总线或者 L2 及以下的结构可以交换请求顺序，那么还是得在 L1 MSHR 这里跟踪一下请求的完成情况，这也许就是最好的做法\n- 如果总线是保序的，那么 LSU 还是得处理一下 Store buffer 和 L1 的顺序问题。当然，LSU 自己的请求提交顺序也要保证。下面具体讨论一下上述的两个经典设计：\n\nWrite buffer coalescing\n因为 W \\to R 序不被保证，所以按顺序处理的 (Committed) write buffer 是无须清空的。但是如果 Write buffer 可能合并请求的话，那就可能导致 W \\to W 序被打破，此时进行 Release fence 时 Write buffer 需要清空，或者至少等到不存在可能合并的行之后再 enqueue。\n在 MICRO 2024 现场看到了一个非常有趣的论文，通过修改 Coherence protocol 解决了这个 W \\to W 保序的问题，有兴趣的同学可以阅读。[4]\n\nMSHR scheduling\n另一个可能出现的问题是，MSHR Scheduling 也可能不会遵循一开始进入该级缓存的顺序。还是上面那个锁的例子中：\nInitial\n[x] = [lock] = 0\n\nTh 0               Th 1\nST [x] <- 1        LD L <- [lock]\nFence Release      Fence Acquire\nST [lock] <- 1     LD R <- [x]\n\n如果只清空了 Write buffer, 那么最极端的情况下可能发生的事情是，Th 0 的 L1DC 中 x, lock 都 Miss，进入 MSHR，先发送 lock 的 Probe, 完成，Replay 也完成，之后被 Th 1 一侧 Probe 回去，完成写回，在这段时间中 x 的 Probe 一直没有发生，因此随后 Th 1 中的 x 无论是 Hit 还是从 LLC Refill，都可以有 R = 0, L = 1。\n因此，在 MSHR 可能被乱序 Sequence 时，LSU & L1DC 通常需要做两件事情：\n- MSHR 在总线给出回应时再释放。由于一般 L1 设计都是 Write-allocate 的，MSHR 需要等待 Refill 结果，所以这里会更类似读取的回应。\n- W \\to * Fence 等待 MSHR 清空。\nAlternatively, Write buffer 当 Miss 的时候等待 Refill 完成再释放，相当于 Store buffer 做 Replay，那等待 Store buffer 清空就好了。这一设计在 TSO 上更常见一点。\n\nTermination?\n如果需要保序的两个请求有一个请求在某一级缓存终止了，但是这一级缓存不是 LLC，那它的全局可见性如何呢？\n对于 Fully-coherent cache，这个问题不大。在某一级缓存终止代表这一级缓存持有足够强的权限，这一请求的全局可见性及其相关的序会由一致性协议保证——虽然这里也有一些坑，一致性协议本身必须有足够强的序。[7]\n对于不 Coherent 的缓存，例如 GPU，通常需要这个操作一直穿透到有一致性的地方，比如 GPU 的所有 Store 都需要一直写到 L2。\n\n“读取”序与 Coherence\n最后简单讨论一下 Rel-Acq 对之间读取关系的序是怎么建立的。注意到，由于 Acq Ld 读取到了 Rel St 的值，因此 Acq Ld 的生效时间一定不早于 Rel St 的生效时间，在 Rel-Acq 对前后扩展其他内存操作时根据生效即可扩展出其他内存操作之间生效的先后关系。\n如果再靠近一些硬件实现，并且放松一些，Acq Rl 的结束一定晚于 Rel St 开始。因此在最暴力的实现中，直接等待前序指令完全结束，再开始执行后续指令是正确的。\n---\n首先讨论在 C++ 标准中的定义。 以下章节号以 N4917 C++26 Draft 为准，因为穷学生买不起标准。\nC++ 执行的单位是表达式，因此 Program order 这里其实指 “Sequenced before” 关系。“Happens before” 的定义正好就是我们这里的“先后关系”，由 “Sequenced before” 和 “Inter-thread happens before” 取并，后者刻画了跨线程的先后关系。“Inter-thread happens before” 关系生成时用到的 “Synchronized with” 包含了例子中生效的 Rel-Acq 对。这些定义全部来自 6.9.2.2 [intro.races] Paragraph (10).\n关于这个先后关系怎么反映到副作用的最终效果和表达式的求值结果上，见同一节 Paragraph (14 - 20)。特别地，对于同一个原子对象，Modification order 是一个全序(6.9.22 [intro.races] Paragraph 4)。同一个这个条件非常关键，\n其次，讨论一下 RISC-V 中的定义。 RVWMO 是好东西，定义了一个 Global memory order，概念上比较简单：写就是写生效的时刻，读取需要根据 Bypass 决定是否需要根据写向后延迟。这里先后关系直接就是这个 Global memory order 上的序了。因为 Rel-Acq pair 有一个“读取到”的关系，它直接固定了这两个访存在 Global memory order 上的相对位置，随后通过 Preserved Program Order 在两侧扩展 Program Order。\n最后，讨论一下在 NVIDIA PTX 中的定义。 NVIDIA PTX 属于一个不上不下的环境，它到硬件上还需要编译一次。PTX 的内存序定义中，通过 Rel-Acq pair / chain 生成的关系称作 Causality order，Coherence order 指所有对相同地址写入的一个全序。要求 Causality order 是 Coherence order 的子集，并且和 read from / from read (read before) 兼容。这里有点麻烦的地方是由于 PTX 的内存模型允许 Non-coherent caches，所以引入了 Scope 的概念，指令内部编码可见域，然后生成 Causality order 的时候只能用互相可见的 Rel-Acq pair。具体见 NV 的文章[8]\n[2] Fences 也是这样的。 C++ 标准见 33.5.11 [atomics.fences]，RV 里 fence.aq 和 fence.rl 分别是 fence.r.rw 和 fence.rw.w 的别名。这里有一点有趣的地方，就是因为 Rel 和 Acq 一个是挡前面，一个是挡后面，如果真的用 Fence 写的话，需要挂到 AMO 不同的两侧，Rel Fences 挂前面，Acq Fences 挂后面。这个可以参考 NV 的论文中对于 Acquire / Release Pattern 的定义，以及查看 PTX ld.acquire / st.release 编译出的 SASS 指令，可以对其他一些拧巴底层原因略窥一二。\n[3] Remark: 注意到上述的这些 AMO 操作或者 Fence 中没有任何一个会保证 W \\to R 顺序，这也是为什么在 x86-TSO 上除了 SeqCst 操作其他所有序都是 No-op，因为 x86-TSO 只会违背 W \\to R PO 序。但是 SeqCst 在各种各样地方上的定义都不太一样，具体在属于它的那篇文章再细节讨论把…\n[4] J. M. Cebrian, M. Jahre and A. Ros, “Temporarily Unauthorized Stores: Write First, Ask for Permission Later,” 2024 57th IEEE/ACM International Symposium on Microarchitecture (MICRO), Austin, TX, USA, 2024, pp. 810-822, doi: 10.1109/MICRO61859.2024.00065.\n[5] 比如 AXI。In contrast, Tilelink 不保证 (SiFive Tilelink Spec 1.9.3, 6.5 P45)\n[6] CHI-A 是一个不保证 Mdan但有特殊 Barrier 的总线。相比下，CHI-B 要求了 MCA 并且 Deprecate 了 Barrier 消息。对于 Ack 所保证的全局可见性，可以参考 SiFive Tilelink Spec 1.9.3, 6.5 P45 要求回应必须有效反应请求的生效情况，并且如果已经给出一个请求回应，后续收到的请求生效一定在前面已给出回应的请求之后。\n[7] 这里“足够强”指的是内存一致性协议必须有效保证各种序，尤其是 Coherence order 是成立的，例如 Tilelink 中需要一个 E channel 发送 GrantAck，以避免总线上消息换序导致 Total coherence order 的丢失。如下是一个例子，在没有 GrantAck 时，两个 Master 都想要写权限，所有消息针对的是同一个 Block。\nMaster A            Slave              Master B\n                      <--- Acquire --------\n    <--- Probe -------\n    ---- ProbeAck --->\n    ---- Acquire ---->\n                      -- Grant ----\\/----->\n                      -- Probe ----/\\\n                      <- ProbeAck - | -----\n                                    \\----->\n    <--- Grant -------\n\n最后由 Master B 收到的 Grant 要不然完全不 Make sense，要不然就是两个 Master 都认为自己有写权限，但 Slave 觉得 B 没有。\n另一个可以考虑的假设情况是 Coherence master 不等待 ProbeAck 就下发 Grant，这个时候破坏的是 MCA。关于这点的简述见[9]。\n[8] Daniel Lustig, Sameer Sahasrabuddhe, and Olivier Giroux. 2019. A Formal Analysis of the NVIDIA PTX Memory Consistency Model. In Proceedings of the Twenty-Fourth International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS ’19). Association for Computing Machinery, New York, NY, USA, 257–270. https://doi.org/10.1145/3297858.3304043\n[9] Christopher Pulte, Shaked Flur, Will Deacon, Jon French, Susmit Sarkar, and Peter Sewell. 2017. Simplifying ARM concurrency: multicopy-atomic axiomatic and operational models for ARMv8. Proc. ACM Program. Lang. 2, POPL, Article 19 (January 2018), 29 pages. https://doi.org/10.1145/3158107\n[10] 一个例子是 PowerPC 下的共享 Store buffer。这可以导致 SMT 的邻居可以早于其他核心上的线程观测到一个写入。与之对比，x86-TSO 实际上要求 SMT 中的 Store buffer 必须拆分。\n"},{"metadata":{"id":"about-the-entropy-center","lang":"zh-CN","title":"玩了 The Entropy Center","tags":["游戏屋"],"publish_time":"2025-04-27T06:32:30+08:00","update_time":"2025-04-27T07:19:00+08:00","title_outline":{"groups":[{"chars":[{"char":"玩","components":[["M 14 -166L 77 -7C 90 -10 101 -22 106 -35C 257 -124 358 -195 420 -244L 418 -253C 253 -213 81 -177 14 -166Z",[0.613,0.259]],["M 29 -759L 37 -731L 400 -731C 415 -731 426 -736 428 -747C 385 -789 309 -853 309 -853L 242 -759Z",[0.889,0.087]],["M 34 -475L 42 -447L 393 -447C 407 -447 417 -452 420 -463C 388 -502 328 -564 328 -564L 275 -475Z",[0.968,0.085]],["M 141 -759L 141 -129L 281 -179L 281 -759Z",[0.008,0.769]],["M 464 -495C 469 -257 448 -59 232 84L 237 94C 556 -4 609 -218 614 -495Z",[0.269,0.684]],["M 367 -495L 375 -467L 956 -467C 971 -467 982 -472 985 -483C 938 -528 857 -596 857 -596L 785 -495Z",[0.86,0.073]],["M 416 -750L 424 -722L 915 -722C 930 -722 941 -727 944 -738C 897 -782 817 -848 817 -848L 746 -750Z",[0.637,0.0]],["M 665 -494L 665 -48C 665 37 680 64 773 64L 829 64C 945 64 987 36 987 -14C 987 -39 981 -55 951 -71L 948 -234L 938 -234C 918 -167 899 -101 888 -80C 882 -69 878 -66 869 -66C 863 -66 856 -66 847 -66L 821 -66C 807 -66 804 -71 804 -84L 804 -456C 804 -466 804 -482 804 -494Z",[-0.144,0.526]]],"bbox":{"top":-853,"bottom":94,"left":14,"right":987},"hadv":1000}],"text":"玩","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"The","hadv":2000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"E","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 634 -0L 632 -207L 576 -207L 519 -1L 605 -39L 218 -39Z",[0.604,0.185]],["M 218 -363L 467 -363L 467 -399L 218 -399Z",[-0.86,0.001]],["M 554 -548L 612 -548L 613 -747L 218 -747L 218 -708L 583 -708L 499 -747Z",[-0.58,0.193]],["M 454 -263L 504 -263L 504 -505L 454 -505L 438 -395L 438 -374Z",[0.007,0.742]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":634},"hadv":674},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"y","components":[["M -7 -516L 95 -505L 204 -505L 298 -516L 298 -546L -7 -546Z",[0.917,0.005]],["M 108 271C 193 271 259 216 325 41L 543 -546L 501 -546L 421 -298L 335 -61L 324 -31L 293 41C 250 145 214 201 152 233L 171 250L 208 224L 177 184C 152 152 123 128 83 128C 44 128 5 148 -3 193C 0 241 52 271 108 271Z",[0.424,0.695]],["M 293 83L 365 -107L 359 -117L 204 -546L 29 -546Z",[-0.264,0.699]],["M 389 -516L 494 -505L 513 -505L 595 -516L 595 -546L 389 -546Z",[-0.927,0.015]]],"bbox":{"top":-546,"bottom":271,"left":-7,"right":595},"hadv":598}],"text":"Entropy","hadv":4221,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Center","hadv":3503,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>为啥半个月没更新博客呢？很想说我在科研，但是其实并没有科出来多少，只是动了很多嘴皮子。反而是玩游戏进展很多，例如最近玩完了 <a href=\"https://store.steampowered.com/app/1730590/The_Entropy_Centre\">The Entropy Center</a>。以下是一些简评/笔记。</p>\n<p>本游戏形式上是受 Portal 启发的解谜游戏，还是很原教旨那种——箱子，按钮，门，有一把枪<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⊇</mo><mi>G</mi><mi>r</mi><mi>a</mi><mi>v</mi><mi>i</mi><mi>t</mi><mi>y</mi><mi>G</mi><mi>u</mi><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">\\supseteq Gravity Gun</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">⊇</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">G</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mord mathnormal\">G</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">n</span></span></span></span>，然后看不见主角。但是本游戏也有很多自己的活，例如<del>主角挺话痨的</del> 枪的效果是反转时间，这游戏同时抄了 Portal 和 BRAID，那只能必须好玩了。</p>\n<p>总体而言，游戏本身的执行质量比较高：美术设计和渲染非常点到为止，虽然具体的美术风格玩家各自的评价估计是见仁见智，相比 Portal 相比更乱一点；各个叙事线我觉得还是挺有趣的（虽然主线剧情十万米外就猜出来了，它也没藏）。然后给我最大的印象的特点有：</p>\n<ul>\n<li>道具非常多，关卡非常非常多（包括关键剧情位置不算在 Chamber 里面的那种解谜估计有 80+ 个谜题，这比 Portal 1 + 2 加起来还多一个 Portal Reloaded…），非常量大管饱。</li>\n<li>体感上谜题相对难度不高，最难的关卡大约 5 分钟可以解决。总共主线流程走下来 9hr</li>\n<li>有一段演出效果非常好，因为不剧透只能说懂的都懂了</li>\n</ul>\n<p>所以综合来看，考虑到团队规模，这已经是完成度非常高的游戏了。如果喜欢 Portal 2 的玩家可以考虑玩一下。</p>\n<hr />\n<p>接下来讨论一些细节的感想，这些细节的感想主要来自于和 Portal 2 的对比，毕竟所有在 Portal 2 之后出现的 Portal-like 游戏都是不幸的。看上去会全都像是批评，但是我个人其实上面已经给了一个正面的总体评价了，但是很不幸，因为主要希望讨论游戏设计和机制实现，这类事情如果做的好，不会被单独注意到，但是如果相比另一个游戏有差距，那就很明显了。</p>\n<p>首先是一个可能跟核心机制相关的问题。作为解谜游戏，本游戏中每个关卡是一个规模有限、较为封闭的箱庭，因此这个问题也可以认为是在每个关卡中的迷你 Game loop 的问题。由于枪的作用是反转箱子的时间，使其退回到较早时间的位置上，那么考虑以下情况：关卡有三个需要利用同一个方块通过的 Check（例如门） <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>→</mo><mi>B</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to B \\to C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span>，那么玩家需要提前规划整个房间的解法，然后将箱子依次放在解决下述 Check 的位置上：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>C</mi><mo>→</mo><mi>B</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">C \\to B \\to A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span>。问题在于在初见的时候，玩家是无法有一个完善的整个房间所有 Check 的心理模型的。尤其这又是一个 3D First-person Puzzle Platformer，很多时候就是看不见的头顶上一个平台上有一个按钮。所以玩家通常是到达一个 Check 位置发现过不去才知道这里有个 Check。然而在本游戏的机制下，这会导致需要大量的 Backtracking，在上述三个 Check 的情况下，玩家的典型通关路线是：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><mo>→</mo><mi>B</mi><mo>→</mo><mi>A</mi><mo>→</mo><mi>B</mi><mo>→</mo><mi>C</mi><mo>→</mo><mi>B</mi><mo>→</mo><mi>A</mi><mo>→</mo><mi>B</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A \\to B \\to A \\to B \\to C \\to B \\to A \\to B \\to C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></span></p>\n<p>这是一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"script\">O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\mathcal{O}(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathcal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span> 复杂度的 Trace…更糟糕的是，其中只有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"script\">O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\mathcal{O}(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathcal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span> 的内容是真的在解谜，在一个解谜游戏中，知道解法但是需要重新操作一次是一个非常坐牢并且打破游戏连续体验的经历。</p>\n<p>解决这一问题的方法可以参考其他游戏。2D scroll screen platformer 也有类似的问题，例如 Celeste 允许玩家通过望远镜提前查看整个地图来缓解这个问题。但是 Celeste 更直接的解决这个问题的方法是降低重试的成本。3D fps platformer 搞一个 Free-cam 不是不行，但是确实体验没有那么好，不过降低重试成本的方法非常简单：允许玩家从一个方块的历史位置向前添加历史，但是不丢失之后的历史即可。这个听上去会比较迷惑，估计不太好教会玩家，但是这也不是通关必须的机制，当玩家到了游戏后半程熟悉了操作和逻辑，并且开始遇到长度更长的关卡时，这一机制就可以开始起作用。</p>\n<p>另一方面，降低关卡本身 Check 的复杂程度，通过更多的机制代替（也就是减少 Check 的拧巴程度，但是增加 Check 的可能解法组合的个数），可以鼓励玩家提前观察关卡进行推理。这也是为什么最后两章的关卡，我的平均完成时间长于之前的关卡，但是体验却比中段的关卡好很多。本游戏引入机制的节奏慢于 Portal 2，可以考虑在较早的章节中引入更多机制（对应的，对关卡设计的要求也会更高）。</p>\n<hr />\n<p>玩完本游戏让我充分意识到 Portal funneling 和 Scripted velocity 在 Portal 2 中的重要性了，因为在本游戏中这都是缺失的。这导致通过一个弹跳方块跨过一个深坑都是一个很困难的操作——引擎将 Air strafing 的加速度降得很低，方块的位置也是玩家自己放置的，面积也不大，很多时候直接就踩不到方块上，结果就又要 Backtracking。</p>\n<p>关于 Scripted velocity，有一个我印象非常深刻的关卡，是需要落在弹跳方块上的同时跳才可以稳定获得足够的高度，否则非常抽奖，玩的时候体验非常西西弗斯。总体而言，因为缺乏 Scripted velocity，很多关卡因为各个地形都是对齐到网格的，事实上很多时候正好圆心落地所需要的速度不是玩家最经常实际达到的速度，经常跳过头/跳不到。所以可以理解如果弹跳方块本身是可以移动的，做 Scripted velocity 会比较困难，但是做一个 Funneling 还是可以大大提升游戏体验的。</p>\n<hr />\n<p>最后是一些 QoL 的事情。值得夸奖的是本游戏允许修改键位映射（不像我正在玩的某些 Galgame(?)），如果在 Test chamber 外的谜题前后添加一些存档点，以及提供跳过过场动画的能力，可以降低一些坐牢体验。</p>\n<p>总之，解谜游戏最关键的是高质量的谜题和解答。Skill-test 是一个不必要的东西，为玩家提供辅助以更快构造解答一定是会大大提升游戏体验的。</p>\n","plain":"为啥半个月没更新博客呢？很想说我在科研，但是其实并没有科出来多少，只是动了很多嘴皮子。反而是玩游戏进展很多，例如最近玩完了 The Entropy Center。以下是一些简评/笔记。\n本游戏形式上是受 Portal 启发的解谜游戏，还是很原教旨那种——箱子，按钮，门，有一把枪\\supseteq Gravity Gun，然后看不见主角。但是本游戏也有很多自己的活，例如主角挺话痨的 枪的效果是反转时间，这游戏同时抄了 Portal 和 BRAID，那只能必须好玩了。\n总体而言，游戏本身的执行质量比较高：美术设计和渲染非常点到为止，虽然具体的美术风格玩家各自的评价估计是见仁见智，相比 Portal 相比更乱一点；各个叙事线我觉得还是挺有趣的（虽然主线剧情十万米外就猜出来了，它也没藏）。然后给我最大的印象的特点有：\n- 道具非常多，关卡非常非常多（包括关键剧情位置不算在 Chamber 里面的那种解谜估计有 80+ 个谜题，这比 Portal 1 + 2 加起来还多一个 Portal Reloaded…），非常量大管饱。\n- 体感上谜题相对难度不高，最难的关卡大约 5 分钟可以解决。总共主线流程走下来 9hr\n- 有一段演出效果非常好，因为不剧透只能说懂的都懂了\n所以综合来看，考虑到团队规模，这已经是完成度非常高的游戏了。如果喜欢 Portal 2 的玩家可以考虑玩一下。\n---\n接下来讨论一些细节的感想，这些细节的感想主要来自于和 Portal 2 的对比，毕竟所有在 Portal 2 之后出现的 Portal-like 游戏都是不幸的。看上去会全都像是批评，但是我个人其实上面已经给了一个正面的总体评价了，但是很不幸，因为主要希望讨论游戏设计和机制实现，这类事情如果做的好，不会被单独注意到，但是如果相比另一个游戏有差距，那就很明显了。\n首先是一个可能跟核心机制相关的问题。作为解谜游戏，本游戏中每个关卡是一个规模有限、较为封闭的箱庭，因此这个问题也可以认为是在每个关卡中的迷你 Game loop 的问题。由于枪的作用是反转箱子的时间，使其退回到较早时间的位置上，那么考虑以下情况：关卡有三个需要利用同一个方块通过的 Check（例如门） A \\to B \\to C，那么玩家需要提前规划整个房间的解法，然后将箱子依次放在解决下述 Check 的位置上：C \\to B \\to A。问题在于在初见的时候，玩家是无法有一个完善的整个房间所有 Check 的心理模型的。尤其这又是一个 3D First-person Puzzle Platformer，很多时候就是看不见的头顶上一个平台上有一个按钮。所以玩家通常是到达一个 Check 位置发现过不去才知道这里有个 Check。然而在本游戏的机制下，这会导致需要大量的 Backtracking，在上述三个 Check 的情况下，玩家的典型通关路线是：\nA \\to B \\to A \\to B \\to C \\to B \\to A \\to B \\to C\n这是一个 \\mathcal{O}(n^2) 复杂度的 Trace…更糟糕的是，其中只有 \\mathcal{O}(n) 的内容是真的在解谜，在一个解谜游戏中，知道解法但是需要重新操作一次是一个非常坐牢并且打破游戏连续体验的经历。\n解决这一问题的方法可以参考其他游戏。2D scroll screen platformer 也有类似的问题，例如 Celeste 允许玩家通过望远镜提前查看整个地图来缓解这个问题。但是 Celeste 更直接的解决这个问题的方法是降低重试的成本。3D fps platformer 搞一个 Free-cam 不是不行，但是确实体验没有那么好，不过降低重试成本的方法非常简单：允许玩家从一个方块的历史位置向前添加历史，但是不丢失之后的历史即可。这个听上去会比较迷惑，估计不太好教会玩家，但是这也不是通关必须的机制，当玩家到了游戏后半程熟悉了操作和逻辑，并且开始遇到长度更长的关卡时，这一机制就可以开始起作用。\n另一方面，降低关卡本身 Check 的复杂程度，通过更多的机制代替（也就是减少 Check 的拧巴程度，但是增加 Check 的可能解法组合的个数），可以鼓励玩家提前观察关卡进行推理。这也是为什么最后两章的关卡，我的平均完成时间长于之前的关卡，但是体验却比中段的关卡好很多。本游戏引入机制的节奏慢于 Portal 2，可以考虑在较早的章节中引入更多机制（对应的，对关卡设计的要求也会更高）。\n---\n玩完本游戏让我充分意识到 Portal funneling 和 Scripted velocity 在 Portal 2 中的重要性了，因为在本游戏中这都是缺失的。这导致通过一个弹跳方块跨过一个深坑都是一个很困难的操作——引擎将 Air strafing 的加速度降得很低，方块的位置也是玩家自己放置的，面积也不大，很多时候直接就踩不到方块上，结果就又要 Backtracking。\n关于 Scripted velocity，有一个我印象非常深刻的关卡，是需要落在弹跳方块上的同时跳才可以稳定获得足够的高度，否则非常抽奖，玩的时候体验非常西西弗斯。总体而言，因为缺乏 Scripted velocity，很多关卡因为各个地形都是对齐到网格的，事实上很多时候正好圆心落地所需要的速度不是玩家最经常实际达到的速度，经常跳过头/跳不到。所以可以理解如果弹跳方块本身是可以移动的，做 Scripted velocity 会比较困难，但是做一个 Funneling 还是可以大大提升游戏体验的。\n---\n最后是一些 QoL 的事情。值得夸奖的是本游戏允许修改键位映射（不像我正在玩的某些 Galgame(?)），如果在 Test chamber 外的谜题前后添加一些存档点，以及提供跳过过场动画的能力，可以降低一些坐牢体验。\n总之，解谜游戏最关键的是高质量的谜题和解答。Skill-test 是一个不必要的东西，为玩家提供辅助以更快构造解答一定是会大大提升游戏体验的。\n"},{"metadata":{"id":"小马杯","lang":"zh-CN","title":"25 小马杯","tags":["走路猫"],"publish_time":"2025-04-26T23:16:32+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"25","hadv":1226,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"小","components":[["M 204 -610C 181 -472 118 -272 18 -140L 25 -132C 190 -227 296 -383 360 -514C 385 -514 394 -523 398 -533Z",[0.342,0.601]],["M 436 -840L 436 -88C 436 -75 430 -69 412 -69C 381 -69 227 -77 227 -77L 227 -65C 298 -52 325 -36 349 -13C 373 11 381 44 386 94C 562 78 587 23 587 -77L 587 -794C 612 -798 622 -808 624 -823Z",[0.056,0.791]],["M 661 -594L 651 -588C 727 -476 798 -332 820 -198C 983 -64 1104 -414 661 -594Z",[-0.279,0.504]]],"bbox":{"top":-840,"bottom":94,"left":18,"right":1104},"hadv":1000}],"text":"小","hadv":1000,"breakAfter":true},{"chars":[{"char":"马","components":[["M 614 -297L 539 -201L 36 -201L 44 -173L 722 -173C 736 -173 748 -178 751 -189C 699 -233 614 -297 614 -297Z",[0.879,0.053]],["M 706 -797L 126 -797L 135 -769L 706 -769Z",[0.685,0.009]],["M 438 -690L 254 -725C 250 -654 220 -458 198 -374L 236 -412C 214 -404 188 -386 173 -370L 307 -299L 355 -362L 348 -362C 365 -444 393 -621 402 -689L 393 -665C 423 -664 435 -677 438 -690Z",[0.122,0.614]],["M 868 -390L 297 -390L 297 -362L 868 -362Z",[0.839,0.017]],["M 780 -390L 791 -390C 782 -198 768 -76 740 -54C 731 -47 723 -45 706 -45C 682 -45 599 -49 542 -53L 542 -43C 597 -32 640 -15 662 8C 684 28 689 57 689 97C 771 98 814 88 852 59C 909 16 929 -98 941 -336C 963 -339 975 -346 983 -355L 857 -463Z",[0.192,0.579]],["M 626 -797L 637 -797C 632 -691 618 -510 599 -374C 669 -363 719 -368 754 -388C 768 -494 783 -654 789 -744C 810 -748 823 -757 829 -765L 684 -871Z",[0.076,0.657]]],"bbox":{"top":-871,"bottom":98,"left":36,"right":983},"hadv":1000}],"text":"马","hadv":1000,"breakAfter":true},{"chars":[{"char":"杯","components":[["M 174 -610C 148 -452 95 -276 11 -155L 23 -145C 168 -259 267 -411 311 -594L 311 -610Z",[0.32,0.689]],["M 37 -610L 45 -582L 457 -582C 471 -582 482 -587 484 -598C 446 -637 379 -696 379 -696L 320 -610Z",[0.793,0.054]],["M 178 -853L 178 95L 206 95C 259 95 318 67 318 56L 318 -807C 346 -811 353 -821 355 -836Z",[0.005,0.849]],["M 318 -541L 309 -536C 331 -494 348 -433 345 -378C 442 -284 575 -475 318 -541Z",[-0.148,0.329]],["M 642 -749C 597 -557 490 -352 333 -223L 342 -213C 580 -329 733 -508 801 -733L 801 -749Z",[0.438,0.645]],["M 371 -749L 379 -721L 954 -721C 969 -721 980 -726 983 -737C 936 -781 856 -847 856 -847L 785 -749Z",[0.778,0.023]],["M 598 -501L 598 91L 625 91C 679 91 738 64 740 54L 740 -503C 759 -507 768 -513 771 -523L 649 -568Z",[0.011,0.767]],["M 735 -488L 727 -482C 780 -416 840 -322 863 -238C 998 -147 1096 -413 735 -488Z",[-0.307,0.387]]],"bbox":{"top":-853,"bottom":95,"left":11,"right":1096},"hadv":1000}],"text":"杯","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<style>\n  .label {\n    font-size: 0.7em;\n    text-align: center;\n    opacity: .7;\n    margin-top: -20px;\n  }\n</style>\n<p>今天跑完了 25 年小马杯参加的最后一个项目 10k，算是总算赶在毕业之前在马杯个人项目里拿了点分，算是零的突破。两分也是两分！</p>\n<p><img src=\"https://layered-assets.thu.fail/25-10k.jpg\" alt=\"成绩单图片\" /></p>\n<div class=\"label\">低清成绩图</div>\n<p>相比于 PB 还是有一分钟差距，最近状态不是很好（缺练了），今天也比较热。不过能有分其实已经很开心了。这次小马杯跑了 5k 和 10k 两个项目，5k 在前天，喜提了第九名看了门。</p>\n<p>之前更多是在集体项目上拿分，比如万米，还有每年打卡定向。集体项目总是有大佬带的，比如万米里我应该每年都是最慢一棒，是作为老年人上来凑数的。定向队里的同学 800m 都是 2:10 以内，有点望尘莫及。</p>\n<p>即便如此，今年也是我在春末夏初状态最好的一年，希望能以此为基础多稳定训练把。往年的情况是冬天经常受伤，感觉还是步频太慢导致膝盖压力太大，最近在做步频训练但是被小马杯打断了一下，该恢复了。过两天还有两场半马，今年比较可惜没有报上校马，希望明年作为在校生最后一年校马和小马杯能有点更好的成绩把。</p>\n<p><img src=\"https://layered-assets.thu.fail/sjz-half.jpg\" alt=\"成绩单图片\" /></p>\n<div class=\"label\">石家庄马拉松后吃早餐</div>","plain":"今天跑完了 25 年小马杯参加的最后一个项目 10k，算是总算赶在毕业之前在马杯个人项目里拿了点分，算是零的突破。两分也是两分！\n成绩单图片\n相比于 PB 还是有一分钟差距，最近状态不是很好（缺练了），今天也比较热。不过能有分其实已经很开心了。这次小马杯跑了 5k 和 10k 两个项目，5k 在前天，喜提了第九名看了门。\n之前更多是在集体项目上拿分，比如万米，还有每年打卡定向。集体项目总是有大佬带的，比如万米里我应该每年都是最慢一棒，是作为老年人上来凑数的。定向队里的同学 800m 都是 2:10 以内，有点望尘莫及。\n即便如此，今年也是我在春末夏初状态最好的一年，希望能以此为基础多稳定训练把。往年的情况是冬天经常受伤，感觉还是步频太慢导致膝盖压力太大，最近在做步频训练但是被小马杯打断了一下，该恢复了。过两天还有两场半马，今年比较可惜没有报上校马，希望明年作为在校生最后一年校马和小马杯能有点更好的成绩把。\n成绩单图片\n"},{"metadata":{"id":"rtmps-forward","lang":"zh-CN","title":"RTMP(S) proxy with NGINX","tags":["灵车"],"publish_time":"2025-04-11T03:05:18+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690}],"text":"RTMP","hadv":3188,"breakAfter":false},{"chars":[{"char":"(","components":[["M 206 -315C 206 -504 242 -638 376 -803L 352 -825C 180 -684 86 -529 86 -315C 86 -101 180 53 352 195L 376 173C 249 12 206 -126 206 -315Z",[-0.002,0.755]]],"bbox":{"top":-825,"bottom":195,"left":86,"right":376},"hadv":418}],"text":"(","hadv":418,"breakAfter":false},{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612}],"text":"S","hadv":612,"breakAfter":false},{"chars":[{"char":")","components":[["M 212 -315C 212 -126 176 8 42 173L 66 195C 238 54 332 -101 332 -315C 332 -529 238 -683 66 -825L 42 -803C 169 -642 212 -504 212 -315Z",[-0.001,0.755]]],"bbox":{"top":-825,"bottom":195,"left":42,"right":332},"hadv":418}],"text":")","hadv":418,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617},{"char":"y","components":[["M -7 -516L 95 -505L 204 -505L 298 -516L 298 -546L -7 -546Z",[0.917,0.005]],["M 108 271C 193 271 259 216 325 41L 543 -546L 501 -546L 421 -298L 335 -61L 324 -31L 293 41C 250 145 214 201 152 233L 171 250L 208 224L 177 184C 152 152 123 128 83 128C 44 128 5 148 -3 193C 0 241 52 271 108 271Z",[0.424,0.695]],["M 293 83L 365 -107L 359 -117L 204 -546L 29 -546Z",[-0.264,0.699]],["M 389 -516L 494 -505L 513 -505L 595 -516L 595 -546L 389 -546Z",[-0.927,0.015]]],"bbox":{"top":-546,"bottom":271,"left":-7,"right":595},"hadv":598}],"text":"proxy","hadv":3061,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"with","hadv":2357,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"G","components":[["M 441 20C 536 20 607 -0 685 -46L 685 -95C 685 -193 687 -280 689 -367L 521 -367C 523 -275 525 -190 525 -100L 525 -9L 581 -40C 542 -26 503 -18 460 -18C 326 -18 221 -151 221 -374C 221 -614 330 -729 470 -729C 527 -729 567 -713 622 -670L 622 -712L 539 -743L 599 -530L 661 -530L 665 -713C 603 -747 534 -767 448 -767C 207 -767 43 -617 43 -376C 43 -128 204 20 441 20Z",[-0.048,0.116]],["M 416 -333L 555 -316L 624 -316L 750 -333L 750 -367L 416 -367Z",[0.82,0.005]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":750},"hadv":766},{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"X","components":[["M 10 -0L 253 -0L 253 -34L 147 -50L 121 -50L 10 -34Z",[0.806,0.001]],["M 19 -713L 167 -698L 220 -698L 368 -713L 368 -747L 19 -747Z",[-0.791,0.001]],["M 493 -0L 680 -0L 246 -747L 59 -747Z",[-0.426,0.698]],["M 67 -0L 127 -0L 340 -347L 360 -382L 366 -382L 337 -401Z",[0.49,0.755]],["M 370 -0L 727 -0L 727 -34L 579 -50L 530 -50L 370 -34Z",[0.867,0.001]],["M 402 -395L 634 -747L 579 -747L 395 -444L 376 -410L 370 -410Z",[0.484,0.763]],["M 457 -713L 559 -699L 586 -699L 695 -713L 695 -747L 457 -747Z",[-0.19,0.031]]],"bbox":{"top":-747,"bottom":0,"left":10,"right":727},"hadv":739}],"text":"NGINX","hadv":3592,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>由于最近 Tunight 会议软件换成了腾讯会议，已经很久没办法直接推 YouTube 流了，十分头疼。在一个腾讯会议服务器可以摸到的服务器上设置一个 RTMP Proxy，既可以解决推流问题，这样以后不再需要 OBS 直播腾讯会议窗口了，以后也可以在多个平台上同时推流。</p>\n<p>考虑到 Stream key 的安全性，使用 RTMPS。由于 RTMPS 就是 RTMP 直接套了一层 TLS，使用 NGINX Stream 做 TLS Termination 即可。如下配置是从 <a href=\"https://serverfault.com/a/1019344\">https://serverfault.com/a/1019344</a> 略加修改抄来的：</p>\n<pre><code class=\"language-nginx\">stream {\n    log_format basic '$remote_addr [$time_local] '\n                 '$protocol $status $bytes_sent $bytes_received '\n                 '$session_time';\n    access_log /var/log/nginx/stream.log basic buffer=32k;\n    upstream backend {\n        server 127.0.0.1:1936;\n    }\n    server {\n        listen 1935 ssl;\n        proxy_pass backend;\n        ssl_certificate /etc/letsencrypt/live/rtmp.example.com/fullchain.pem;\n        ssl_certificate_key /etc/letsencrypt/live/rtmp.example.com/privkey.pem;\n    }\n}\n\nrtmp {\n    access_log /var/log/nginx/rtmp.log;\n    server {\n        listen 127.0.0.1:1936;\n        chunk_size 4096;\n\n        application &lt;key&gt; {\n            live on;\n            record off;\n            push rtmp://a.rtmp.youtube.com/live2/&lt;YouTube stream key&gt;;\n        }\n    }\n}\n</code></pre>\n<p><code>&lt;key&gt;</code> 应该是一个随机字符串。在同一个 <code>application</code> 块内添加多个 <code>push</code> directive 可以同时推多个流，添加 <code>application</code> 可以增加一个 proxy endpoint.</p>\n<p>注意事项：</p>\n<ol>\n<li>OBS 填路径的时候，应该把 Stream key 留空，推流地址写 <code>rtmps://rtmp.example.com:1935/&lt;key&gt;</code>。这是因为在上述配置中用于验证的 <code>&lt;key&gt;</code> 随机字符串是在 <code>application</code> 位置，而不是 RTMP URL 的 name 位置。<code>nginx-rtmp-module</code> 缺乏使用 name 做验证的能力，我也没找到通过 name 修改 <code>push</code> 目标的方法，所以只能写在 <code>application</code>.</li>\n<li>默认 RTMPS 端口是 443，如果想用 <code>certbot --nginx</code> 的话它会自己搞出来一个 HTTPS 的 <code>server</code> 块儿，和 Stream 的 <code>server</code> 块儿就冲突了。因此这里使用了 1935 避开了 HTTPS 的端口，代价是写推流地址的时候需要带端口。</li>\n<li>RTMP 监听在 <code>127.0.0.1</code> 上。如果同时希望接受未经加密的 RTMP，<code>listen</code> 只写一个端口即可。</li>\n</ol>\n","plain":"由于最近 Tunight 会议软件换成了腾讯会议，已经很久没办法直接推 YouTube 流了，十分头疼。在一个腾讯会议服务器可以摸到的服务器上设置一个 RTMP Proxy，既可以解决推流问题，这样以后不再需要 OBS 直播腾讯会议窗口了，以后也可以在多个平台上同时推流。\n考虑到 Stream key 的安全性，使用 RTMPS。由于 RTMPS 就是 RTMP 直接套了一层 TLS，使用 NGINX Stream 做 TLS Termination 即可。如下配置是从 https://serverfault.com/a/1019344 略加修改抄来的：\nstream {\n    log_format basic '$remote_addr [$time_local] '\n                 '$protocol $status $bytes_sent $bytes_received '\n                 '$session_time';\n    access_log /var/log/nginx/stream.log basic buffer=32k;\n    upstream backend {\n        server 127.0.0.1:1936;\n    }\n    server {\n        listen 1935 ssl;\n        proxy_pass backend;\n        ssl_certificate /etc/letsencrypt/live/rtmp.example.com/fullchain.pem;\n        ssl_certificate_key /etc/letsencrypt/live/rtmp.example.com/privkey.pem;\n    }\n}\n\nrtmp {\n    access_log /var/log/nginx/rtmp.log;\n    server {\n        listen 127.0.0.1:1936;\n        chunk_size 4096;\n\n        application <key> {\n            live on;\n            record off;\n            push rtmp://a.rtmp.youtube.com/live2/<YouTube stream key>;\n        }\n    }\n}\n\n<key> 应该是一个随机字符串。在同一个 application 块内添加多个 push directive 可以同时推多个流，添加 application 可以增加一个 proxy endpoint.\n注意事项：\n- OBS 填路径的时候，应该把 Stream key 留空，推流地址写 rtmps://rtmp.example.com:1935/<key>。这是因为在上述配置中用于验证的 <key> 随机字符串是在 application 位置，而不是 RTMP URL 的 name 位置。nginx-rtmp-module 缺乏使用 name 做验证的能力，我也没找到通过 name 修改 push 目标的方法，所以只能写在 application.\n- 默认 RTMPS 端口是 443，如果想用 certbot --nginx 的话它会自己搞出来一个 HTTPS 的 server 块儿，和 Stream 的 server 块儿就冲突了。因此这里使用了 1935 避开了 HTTPS 的端口，代价是写推流地址的时候需要带端口。\n- RTMP 监听在 127.0.0.1 上。如果同时希望接受未经加密的 RTMP，listen 只写一个端口即可。\n"},{"metadata":{"id":"android-nfs","lang":"zh-CN","title":"NFS on Android","tags":["灵车"],"publish_time":"2025-04-10T07:15:25+08:00","update_time":"2025-04-10T07:23:47+08:00","title_outline":{"groups":[{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612}],"text":"NFS","hadv":2094,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"Android","hadv":4319,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>出于多设备共享、偷 NAS 上的存储空间等原因，最近折腾了一下 Android 挂载 NFS，简单做一下记录。</p>\n<p>由于 Android 默认的内核没编译 NFS，所以需要自己编译一下内核，并且有一些额外设置以保证 App 可以正常访问挂载的内容。</p>\n<p>因此使用如下方法在 Android 上用 NFS 需要：</p>\n<ul>\n<li>可以刷机</li>\n<li>必须得有 Root，不过形式不一定是类似 Magisk 这样的方案。</li>\n</ul>\n<p>我使用的环境：</p>\n<ul>\n<li>OnePlus 7 (guacamoleb)</li>\n<li><a href=\"https://wiki.lineageos.org/devices/guacamoleb/build/\">LineageOS 22.1 (Android 15)</a></li>\n</ul>\n<h2>内核</h2>\n<p>具体而言，需要至少开 NFS，以及希望支持的 NFS 版本相关的内容。正常 clone AOSP 或者希望使用的 ROM，在内核目录下（<code>$ANDROID_ROOD/kernel/$BRAND/$PRODUCT</code>）执行 <code>make menuconfig</code> 即可。</p>\n<p>我开了以下这些东西：</p>\n<div class=\"highlighted highlighted-diff\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-diff\"><span style=\"color:#859900;\">+CONFIG_NFS_FS=y\n</span><span style=\"color:#859900;\">+CONFIG_NFS_V4=y\n</span><span style=\"color:#859900;\">+CONFIG_NFS_V4_1=y\n</span><span style=\"color:#859900;\">+CONFIG_NFS_V4_2=y\n</span><span style=\"color:#859900;\">+CONFIG_NFSD=y\n</span><span style=\"color:#859900;\">+CONFIG_NFSD_V4=y\n</span><span style=\"color:#859900;\">+CONFIG_CIFS=m\n</span><span style=\"color:#859900;\">+CONFIG_AFS_FS=m\n</span></code></pre>\n</div>\n<p>之后直接 Build 出来的 ROM 刷进去，可以看到内核的 NFS 支持已经出来了：</p>\n<pre><code class=\"language-shell\">OnePlus7:# zcat /proc/config.gz | grep CONFIG_NFS_FS=\nCONFIG_NFS_FS=y\n</code></pre>\n<h2>Root</h2>\n<p>后续操作需要 Root，关 SELinux 和挂载这个操作本身都需要，所以基本没法绕过。不过 LineageOS 自带了 Root through ADB。然后不知道为什么，Termux 可以看到本机的 ADB：</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#d33682;\">~</span><span style=\"color:#839496;\"> $ adb devices\n</span><span style=\"color:#b58900;\">List</span><span style=\"color:#839496;\"> of devices attached\n</span><span style=\"color:#b58900;\">emulator-5554</span><span style=\"color:#839496;\"> device\n</span></code></pre>\n</div>\n<p>所以其实直接在 Termux 里面 <code>adb root; adb shell</code> 就提权了，没用到 su…然后再把 Termux 的 PATH 给进去，就可以用 Termux 下面装的 bash 和所有其他二进制了。以后有时间研究一下 Termux 是怎么看到本机的 ADB 的…</p>\n<p>如果上述方法不工作，更通用的方法是开 Wireless debugging，然后在本机连接<sup>[2]</sup>。</p>\n<p>如果其他的 ROM，可以在编译的时候使用 <code>userdebug</code> / <code>eng</code> build variant<sup>[3][4]</sup>，效果也是可以打开 <code>adb root</code>；LineageOS 的 <a href=\"https://github.com/LineageOS/android_packages_modules_adb/\"><code>adbd</code> fork</a> Apparently 加了一些额外的东西，看上去是和开发者选项里的开关相关的。</p>\n<p>当然使用类似 Magisk 的 su-based 方案也可以，或者下面进行挂载的脚本加上 setuid。</p>\n<p>题外话：赞美 LineageOS，自带了 VIM</p>\n<h2>挂载</h2>\n<p>主要参考了 <a href=\"https://gist.github.com/aldur/4a3f90a111b71662f056\">这个 Gist</a>。需要注意的是 Android 自己带的 mount 二进制不认识 NFS，上述 Gist 中给出的方案是使用 <code>busybox mount</code>。使用 termux 安装的 busybox 即可；termux 安装的 mount 二进制应该也可以，但是没有实测。</p>\n<p>另一个需要注意的事情是，由于 <code>/sdcard -&gt; /storage/emulated/0</code> 是一个 FUSE<sup>[1]</sup>，没法直接 mount 进去。上述 Gist 的方案是挂到 <code>/data/media/0</code> 下面，但是实测应用看不到挂载内的内容。可以看到内容的方法是搞一些扭曲 bind mount，相当于绕过了 FUSE 的权限控制：</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#586e75;\">#!/data/data/com.termux/usr/bin/bash\n</span><span style=\"color:#93a1a1;\">export </span><span style=\"color:#268bd2;\">PATH</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">/data/data/com.termux/usr/bin:</span><span style=\"color:#859900;\">$</span><span style=\"color:#268bd2;\">PATH</span><span style=\"color:#839496;\">&quot;\n</span><span style=\"color:#b58900;\">setenforce</span><span style=\"color:#839496;\"> Permissive\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">mkdir</span><span style=\"color:#268bd2;\"> -p</span><span style=\"color:#839496;\"> /tmp/mnt/nfs </span><span style=\"color:#586e75;\"># Ensure /tmp is tmpfs\n</span><span style=\"color:#b58900;\">busybox</span><span style=\"color:#839496;\"> mount</span><span style=\"color:#268bd2;\"> -o</span><span style=\"color:#839496;\"> ro,nolock,local_lock=all 1.2.3.4:/path/to/export /tmp/mnt/nfs\n</span><span style=\"color:#586e75;\"># Mount other subdirectories...\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">mkdir</span><span style=\"color:#268bd2;\"> -p</span><span style=\"color:#839496;\"> /storage/emulated/0/nfs\n</span><span style=\"color:#b58900;\">busybox</span><span style=\"color:#839496;\"> mount</span><span style=\"color:#268bd2;\"> --rbind</span><span style=\"color:#839496;\"> /tmp/mnt/nfs /storage/emulated/0/nfs\n</span></code></pre>\n</div>\n<p>上述例子中给的 Readonly mount，实测 Read-write 也正常<sup>[5]</sup>，App 可以写入。不过 <code>nolock</code> 不能去掉，原因有待研究。脚本放在 <code>/data/media/0</code> 下可以 <code>chmod +x</code>。</p>\n<ul>\n<li>[1] <a href=\"https://blog.xzr.moe/archives/191/\">Android Emulated Storage 结构浅析 - LibXZR 的小本本</a></li>\n<li>[2] <a href=\"https://gist.github.com/kairusds/1d4e32d3cf0d6ca44dc126c1a383a48d\">Instructions for connecting Termux’s android-tools adb to the current device via Wireless debugging and fixing phantom process killing</a></li>\n<li>[3] <a href=\"https://android.googlesource.com/platform//packages/modules/adb/+/1cf2f017d312f73b3dc53bda85ef2610e35a80e9/daemon/main.cpp#87\">AOSP <code>adbd</code> 相关代码</a></li>\n<li>[4] <a href=\"https://github.com/LineageOS/android_vendor_lineage/blob/fac22bf2792973a7bb85b37744ae4cb851174e24/build/envsetup.sh#L53\">LineageOS 设置 Build variant 的位置</a></li>\n<li>[5] 我 <code>rm -rf</code> 了一个 NFS 挂载点…要不是花了两天恢复数据，这篇灵车文章两天前就写出来了。</li>\n</ul>\n","plain":"出于多设备共享、偷 NAS 上的存储空间等原因，最近折腾了一下 Android 挂载 NFS，简单做一下记录。\n由于 Android 默认的内核没编译 NFS，所以需要自己编译一下内核，并且有一些额外设置以保证 App 可以正常访问挂载的内容。\n因此使用如下方法在 Android 上用 NFS 需要：\n- 可以刷机\n- 必须得有 Root，不过形式不一定是类似 Magisk 这样的方案。\n我使用的环境：\n- OnePlus 7 (guacamoleb)\n- LineageOS 22.1 (Android 15)\n\n内核\n具体而言，需要至少开 NFS，以及希望支持的 NFS 版本相关的内容。正常 clone AOSP 或者希望使用的 ROM，在内核目录下（$ANDROID_ROOD/kernel/$BRAND/$PRODUCT）执行 make menuconfig 即可。\n我开了以下这些东西：\n+CONFIG_NFS_FS=y\n+CONFIG_NFS_V4=y\n+CONFIG_NFS_V4_1=y\n+CONFIG_NFS_V4_2=y\n+CONFIG_NFSD=y\n+CONFIG_NFSD_V4=y\n+CONFIG_CIFS=m\n+CONFIG_AFS_FS=m\n\n之后直接 Build 出来的 ROM 刷进去，可以看到内核的 NFS 支持已经出来了：\nOnePlus7:# zcat /proc/config.gz | grep CONFIG_NFS_FS=\nCONFIG_NFS_FS=y\n\n\nRoot\n后续操作需要 Root，关 SELinux 和挂载这个操作本身都需要，所以基本没法绕过。不过 LineageOS 自带了 Root through ADB。然后不知道为什么，Termux 可以看到本机的 ADB：\n~ $ adb devices\nList of devices attached\nemulator-5554 device\n\n所以其实直接在 Termux 里面 adb root; adb shell 就提权了，没用到 su…然后再把 Termux 的 PATH 给进去，就可以用 Termux 下面装的 bash 和所有其他二进制了。以后有时间研究一下 Termux 是怎么看到本机的 ADB 的…\n如果上述方法不工作，更通用的方法是开 Wireless debugging，然后在本机连接[2]。\n如果其他的 ROM，可以在编译的时候使用 userdebug / eng build variant[3][4]，效果也是可以打开 adb root；LineageOS 的 adbd fork Apparently 加了一些额外的东西，看上去是和开发者选项里的开关相关的。\n当然使用类似 Magisk 的 su-based 方案也可以，或者下面进行挂载的脚本加上 setuid。\n题外话：赞美 LineageOS，自带了 VIM\n\n挂载\n主要参考了 这个 Gist。需要注意的是 Android 自己带的 mount 二进制不认识 NFS，上述 Gist 中给出的方案是使用 busybox mount。使用 termux 安装的 busybox 即可；termux 安装的 mount 二进制应该也可以，但是没有实测。\n另一个需要注意的事情是，由于 /sdcard -> /storage/emulated/0 是一个 FUSE[1]，没法直接 mount 进去。上述 Gist 的方案是挂到 /data/media/0 下面，但是实测应用看不到挂载内的内容。可以看到内容的方法是搞一些扭曲 bind mount，相当于绕过了 FUSE 的权限控制：\n#!/data/data/com.termux/usr/bin/bash\nexport PATH=\"/data/data/com.termux/usr/bin:$PATH\"\nsetenforce Permissive\n\nmkdir -p /tmp/mnt/nfs # Ensure /tmp is tmpfs\nbusybox mount -o ro,nolock,local_lock=all 1.2.3.4:/path/to/export /tmp/mnt/nfs\n# Mount other subdirectories...\n\nmkdir -p /storage/emulated/0/nfs\nbusybox mount --rbind /tmp/mnt/nfs /storage/emulated/0/nfs\n\n上述例子中给的 Readonly mount，实测 Read-write 也正常[5]，App 可以写入。不过 nolock 不能去掉，原因有待研究。脚本放在 /data/media/0 下可以 chmod +x。\n- [1] Android Emulated Storage 结构浅析 - LibXZR 的小本本\n- [2] Instructions for connecting Termux’s android-tools adb to the current device via Wireless debugging and fixing phantom process killing\n- [3] AOSP adbd 相关代码\n- [4] LineageOS 设置 Build variant 的位置\n- [5] 我 rm -rf 了一个 NFS 挂载点…要不是花了两天恢复数据，这篇灵车文章两天前就写出来了。\n"},{"metadata":{"id":"on-railroad","lang":"zh-CN","title":"在铁轨上","tags":["扯淡"],"publish_time":"2025-04-05T00:55:03+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":true},{"chars":[{"char":"铁","components":[["M 272 -774C 299 -776 309 -785 313 -798L 134 -854C 121 -751 71 -568 12 -465L 20 -459C 129 -538 227 -667 272 -774Z",[0.311,0.586]],["M 333 -407L 276 -324L 31 -324L 39 -296L 407 -296C 421 -296 431 -301 434 -312C 398 -350 333 -407 333 -407Z",[0.8,0.075]],["M 310 -611L 252 -527L 86 -527L 94 -499L 387 -499C 401 -499 412 -504 414 -515C 376 -553 310 -611 310 -611Z",[0.863,0.079]],["M 262 -526L 161 -526L 161 -119C 161 -96 154 -85 113 -57L 216 77C 243 57 271 3 244 -76L 185 -24L 295 -60L 295 -506Z",[0.031,0.758]],["M 330 -773L 272 -692L 134 -692L 142 -664L 407 -664C 421 -664 431 -669 434 -680C 396 -717 330 -773 330 -773Z",[0.662,0.102]],["M 144 -65L 218 67C 318 -33 394 -130 430 -178L 426 -186C 311 -133 193 -83 144 -65Z",[0.472,0.362]],["M 788 -839L 615 -855C 615 -415 645 -133 346 78L 355 92C 771 -79 746 -367 751 -810C 775 -814 785 -823 788 -839Z",[0.17,0.784]],["M 634 -733L 471 -772C 461 -650 431 -520 396 -432L 409 -425C 489 -490 552 -588 595 -709C 618 -710 630 -719 634 -733Z",[0.27,0.624]],["M 863 -445L 796 -357L 415 -357L 423 -329L 955 -329C 969 -329 980 -334 983 -345C 938 -386 863 -445 863 -445Z",[0.841,0.067]],["M 829 -689L 764 -602L 509 -602L 509 -574L 919 -574C 933 -574 944 -579 947 -590C 903 -630 829 -689 829 -689Z",[0.9,0.069]],["M 741 -354L 727 -351C 739 -214 778 -7 889 88C 895 9 929 -28 992 -43L 992 -56C 838 -120 759 -238 741 -354Z",[-0.297,0.525]]],"bbox":{"top":-855,"bottom":92,"left":12,"right":992},"hadv":1000}],"text":"铁","hadv":1000,"breakAfter":true},{"chars":[{"char":"轨","components":[["M 308 -830L 143 -867C 130 -765 72 -502 33 -388L 70 -427C 48 -419 21 -402 5 -389L 126 -317L 173 -373L 165 -373C 197 -489 252 -732 272 -829L 261 -807C 292 -804 304 -816 308 -830Z",[0.183,0.73]],["M 6 -252L 76 -101C 88 -104 99 -113 105 -126C 285 -197 402 -254 482 -299L 481 -310C 290 -281 93 -258 6 -252Z",[0.705,0.183]],["M 383 -769L 315 -686L 18 -686L 26 -658L 480 -658C 495 -658 506 -663 509 -674C 461 -713 383 -769 383 -769Z",[0.808,0.067]],["M 392 -488L 325 -401L 94 -401L 102 -373L 484 -373C 498 -373 509 -378 512 -389C 467 -429 392 -488 392 -488Z",[0.745,0.079]],["M 343 52L 343 -391L 202 -391L 202 87L 228 87C 301 87 343 59 343 52Z",[0.006,0.703]],["M 380 -588L 225 -604L 225 -386L 254 -386C 300 -386 343 -386 343 -386L 343 -560C 369 -564 377 -575 380 -588Z",[0.033,0.442]],["M 704 -853L 528 -868C 528 -404 545 -110 360 82L 374 94C 683 -57 662 -352 666 -823C 691 -827 702 -837 704 -853Z",[0.112,0.823]],["M 763 -588L 422 -588L 431 -560L 763 -560Z",[0.71,0.06]],["M 712 -588L 724 -588L 724 -43C 724 34 734 61 815 61L 853 61C 940 61 982 37 982 -12C 982 -36 975 -50 948 -65L 944 -176L 934 -176C 921 -134 906 -85 896 -71C 891 -63 884 -62 879 -62C 875 -62 872 -62 870 -62L 865 -62C 857 -62 855 -67 855 -79L 855 -548C 876 -551 886 -558 893 -565L 775 -661Z",[-0.078,0.725]]],"bbox":{"top":-868,"bottom":94,"left":5,"right":982},"hadv":1000}],"text":"轨","hadv":1000,"breakAfter":true},{"chars":[{"char":"上","components":[["M 25 13L 33 41L 947 41C 962 41 974 36 977 25C 920 -23 826 -94 826 -94L 742 13Z",[0.911,0.043]],["M 386 -839L 386 29L 546 29L 546 -792C 574 -796 581 -806 583 -821Z",[0.004,0.811]],["M 477 -453L 477 -425L 876 -425C 891 -425 902 -430 905 -441C 850 -489 758 -559 758 -559L 676 -453Z",[0.76,0.075]]],"bbox":{"top":-839,"bottom":41,"left":25,"right":977},"hadv":1000}],"text":"上","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>还记得在 20 年的时候，第一次坐 S2 线到延庆去跑比赛。回来的路上碰巧天气刚好，经过八达岭长城的时候，太阳正好落山，整片天空都染成金色，山的剪影边缘上又是一条金边。可能是因为平时我起床的时候天都黑了，就在这完全随机的一个场景下，意外见到了我所见过最漂亮的一次晚霞。伴随着车厢缓缓地摇动着，逐渐晚霞褪去，路灯一盏盏地亮起，到达南口站的时候，由于这是一个只有两个站台的小站，视线正好可以穿过站厅，路对面的面馆前摆着几长桌子，几个穿着汗衫的男子端着热腾腾的汤面，一边吃一边聊，津津有味。</p>\n<p>我一直无法忘记这个场景。很遗憾，我当时还在用电池爆炸的 1+7，坐上回程列车的时候早就没电了，所以也没有照片。当时在延庆站的候车厅内忐忑不安因为无法查询车次表，生怕记错了发车时间。一对儿背着徒步包的夫妇上来搭话，原来是周末二人在山上搭帐篷住了一晚，刚刚下山，坐 S2 回北京，回到普通的工作日当中。我也一直想关于此写一篇博客，然而正是因为这段记忆过于超常但又日常，我一直甚至不知道从哪里开始写，拖到了现在，甚至怀疑这段记忆是否真实。</p>\n<p>今天刚刚乘坐了一整天的高铁，从北京一路来到黟县，也是来跑比赛。一路上，高铁站都是又大又气派，候车厅至少两层，以及应该是因为高速客运线的调度要求，无论多小的站都至少有四个站台以上。然而在经过两小时站票，踏上黟县东站台的一刻，看向站外黑漆漆的一片深夜，给我的既视感是那种老客运线的真正的小站，几十个座位的站厅，一个钢架天桥通往对面的站台，就像南口站，或者怀柔站那样。这是一种很奇怪但又很熟悉的感觉──一种温暖的孤独。</p>\n<p>之前跟家里人从北京回老家，列车会在早上五点到县城。在春节期间，天是完全黑的，站长会打着手电筒迎接到站的人们，并且把出发的旅客们送上车。一天一个车对两班车，凌晨来，下午回。火车站就是县城中心，走下火车站的台阶，还要坐上拖拉机，从河套平原爬上黄土坡，穿过两个隔壁村子，才能回到自家的院子里。这是我高中之前几乎每个寒假必须经历的行程。之后渐渐的，家人逐渐失去了回村里的动力，而对我本人而言，我生长的更多时间其实是在北京郊区附近的一个小区，上了幼儿园，上了小学，不是坐绿皮而是坐 13 号线，每周末前往中关村上补习班，然后搬到更接近市中心的地方，被卷入新的生活节奏当中。但是即使这个“老家”对我而言更多是一个符号，我还是很怀念那里的许多人，许多时光──即使是现在作为一个局外人。</p>\n<p>跑定向和马拉松导致很多时候需要全国遍地跑，尤其是定向，场地一般都在一些犄角旮旯的地方，普速车和大巴有的时候不可避免。在这些时候，坐火车前往新的目的地是一个很令人期待的事情，透过车窗看着未曾见过的城市的天际线，或者在第一次到达的火车站附近四处寻找吃的。另外，由于拖延症，几乎所有时候都会把打包拖到最后一刻，从而要不是误车改签，要不是最后一两分钟勉勉强强挤进检票口，所以上车的过程本来就是很刺激的一件事情。与之对应，回程的心态则苦涩的多。相比小时候坐13号线，现在则是坐 8 号线多得多，从北京南站背着大包小包由 14 号线换乘 8 号线，虽然身上还背着外出比赛的物品，听到的报站声音却和平日上下班通勤无异，有种异样的不匹配的感觉。</p>\n<p>上大学以后，乘坐飞机变成了我主要的出行方式。往返比京沪更远的距离时，飞机相比高铁更快也更便宜，在近两年由于 OCD 恢复了一些，更加可以忍受机场的安检以来，更是没有坐几次火车。与之对应的，也在有意无意的尝试忘记这种温柔的孤独的感觉──无论是转变为“北京郊区人”的自我定位，还是无暇顾及的旅行本身。从某种角度而言，我感觉也许这不是我个人的困境，就像如同一个模子印出来的各地高铁站一样，可能谁都逃不了。目的地永远只有几个小时的路程之外，而这几个小时的路程，也就因此变得不再特别。22 年，体育大会又在延庆举办，我坐上 S2 希望能够再次体验之前的那个情景，虽然本身没有抱有很大希望，不过听到广播中传来导游讲解和推销纪念品的声音的时候，还是有如当头一棒。</p>\n<p>但是我依旧感觉乘坐火车或者地铁对我来说是一件很特殊的事情，特别是在一些很偶然的时刻，就像今天在途径芜湖附近的时候，向车窗外的无聊一瞥，看到一对情侣/夫妇（Persumably）穿着一样的衣服，和两只狗狗在乡间小路上慢慢地跑着，这样的场景会提醒我铁路上对我而言富含人性的一面，那种温柔的孤独，无论是半虚假的思乡，还是临时的冒险，又或者是各自有着迥然不同目的地的人们，却一起聚集在了这样一个不大不小的罐头里这样一个奇迹，也许都悄悄藏在车厢的轻轻摇晃之中吧。</p>\n<hr />\n<p>然后我就想起来我有一个包忘在南京南了，当场打高铁回去了一趟，加上一开始的换乘，今天一共三顾南京南。</p>\n<p>Also，写这些糨糊的时候总让我想到《秒五》，我感觉我可能是脑子出问题了（</p>\n","plain":"还记得在 20 年的时候，第一次坐 S2 线到延庆去跑比赛。回来的路上碰巧天气刚好，经过八达岭长城的时候，太阳正好落山，整片天空都染成金色，山的剪影边缘上又是一条金边。可能是因为平时我起床的时候天都黑了，就在这完全随机的一个场景下，意外见到了我所见过最漂亮的一次晚霞。伴随着车厢缓缓地摇动着，逐渐晚霞褪去，路灯一盏盏地亮起，到达南口站的时候，由于这是一个只有两个站台的小站，视线正好可以穿过站厅，路对面的面馆前摆着几长桌子，几个穿着汗衫的男子端着热腾腾的汤面，一边吃一边聊，津津有味。\n我一直无法忘记这个场景。很遗憾，我当时还在用电池爆炸的 1+7，坐上回程列车的时候早就没电了，所以也没有照片。当时在延庆站的候车厅内忐忑不安因为无法查询车次表，生怕记错了发车时间。一对儿背着徒步包的夫妇上来搭话，原来是周末二人在山上搭帐篷住了一晚，刚刚下山，坐 S2 回北京，回到普通的工作日当中。我也一直想关于此写一篇博客，然而正是因为这段记忆过于超常但又日常，我一直甚至不知道从哪里开始写，拖到了现在，甚至怀疑这段记忆是否真实。\n今天刚刚乘坐了一整天的高铁，从北京一路来到黟县，也是来跑比赛。一路上，高铁站都是又大又气派，候车厅至少两层，以及应该是因为高速客运线的调度要求，无论多小的站都至少有四个站台以上。然而在经过两小时站票，踏上黟县东站台的一刻，看向站外黑漆漆的一片深夜，给我的既视感是那种老客运线的真正的小站，几十个座位的站厅，一个钢架天桥通往对面的站台，就像南口站，或者怀柔站那样。这是一种很奇怪但又很熟悉的感觉──一种温暖的孤独。\n之前跟家里人从北京回老家，列车会在早上五点到县城。在春节期间，天是完全黑的，站长会打着手电筒迎接到站的人们，并且把出发的旅客们送上车。一天一个车对两班车，凌晨来，下午回。火车站就是县城中心，走下火车站的台阶，还要坐上拖拉机，从河套平原爬上黄土坡，穿过两个隔壁村子，才能回到自家的院子里。这是我高中之前几乎每个寒假必须经历的行程。之后渐渐的，家人逐渐失去了回村里的动力，而对我本人而言，我生长的更多时间其实是在北京郊区附近的一个小区，上了幼儿园，上了小学，不是坐绿皮而是坐 13 号线，每周末前往中关村上补习班，然后搬到更接近市中心的地方，被卷入新的生活节奏当中。但是即使这个“老家”对我而言更多是一个符号，我还是很怀念那里的许多人，许多时光──即使是现在作为一个局外人。\n跑定向和马拉松导致很多时候需要全国遍地跑，尤其是定向，场地一般都在一些犄角旮旯的地方，普速车和大巴有的时候不可避免。在这些时候，坐火车前往新的目的地是一个很令人期待的事情，透过车窗看着未曾见过的城市的天际线，或者在第一次到达的火车站附近四处寻找吃的。另外，由于拖延症，几乎所有时候都会把打包拖到最后一刻，从而要不是误车改签，要不是最后一两分钟勉勉强强挤进检票口，所以上车的过程本来就是很刺激的一件事情。与之对应，回程的心态则苦涩的多。相比小时候坐13号线，现在则是坐 8 号线多得多，从北京南站背着大包小包由 14 号线换乘 8 号线，虽然身上还背着外出比赛的物品，听到的报站声音却和平日上下班通勤无异，有种异样的不匹配的感觉。\n上大学以后，乘坐飞机变成了我主要的出行方式。往返比京沪更远的距离时，飞机相比高铁更快也更便宜，在近两年由于 OCD 恢复了一些，更加可以忍受机场的安检以来，更是没有坐几次火车。与之对应的，也在有意无意的尝试忘记这种温柔的孤独的感觉──无论是转变为“北京郊区人”的自我定位，还是无暇顾及的旅行本身。从某种角度而言，我感觉也许这不是我个人的困境，就像如同一个模子印出来的各地高铁站一样，可能谁都逃不了。目的地永远只有几个小时的路程之外，而这几个小时的路程，也就因此变得不再特别。22 年，体育大会又在延庆举办，我坐上 S2 希望能够再次体验之前的那个情景，虽然本身没有抱有很大希望，不过听到广播中传来导游讲解和推销纪念品的声音的时候，还是有如当头一棒。\n但是我依旧感觉乘坐火车或者地铁对我来说是一件很特殊的事情，特别是在一些很偶然的时刻，就像今天在途径芜湖附近的时候，向车窗外的无聊一瞥，看到一对情侣/夫妇（Persumably）穿着一样的衣服，和两只狗狗在乡间小路上慢慢地跑着，这样的场景会提醒我铁路上对我而言富含人性的一面，那种温柔的孤独，无论是半虚假的思乡，还是临时的冒险，又或者是各自有着迥然不同目的地的人们，却一起聚集在了这样一个不大不小的罐头里这样一个奇迹，也许都悄悄藏在车厢的轻轻摇晃之中吧。\n---\n然后我就想起来我有一个包忘在南京南了，当场打高铁回去了一趟，加上一开始的换乘，今天一共三顾南京南。\nAlso，写这些糨糊的时候总让我想到《秒五》，我感觉我可能是脑子出问题了（\n"},{"metadata":{"id":"fixing-libvirt-passthrough","lang":"zh-CN","title":"Fixing libvirt GPU passthrough","tags":["灵车"],"publish_time":"2025-04-03T05:23:22+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"Fixing","hadv":3299,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"libvirt","hadv":3290,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"G","components":[["M 441 20C 536 20 607 -0 685 -46L 685 -95C 685 -193 687 -280 689 -367L 521 -367C 523 -275 525 -190 525 -100L 525 -9L 581 -40C 542 -26 503 -18 460 -18C 326 -18 221 -151 221 -374C 221 -614 330 -729 470 -729C 527 -729 567 -713 622 -670L 622 -712L 539 -743L 599 -530L 661 -530L 665 -713C 603 -747 534 -767 448 -767C 207 -767 43 -617 43 -376C 43 -128 204 20 441 20Z",[-0.048,0.116]],["M 416 -333L 555 -316L 624 -316L 750 -333L 750 -367L 416 -367Z",[0.82,0.005]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":750},"hadv":766},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"U","components":[["M 36 -713L 198 -698L 228 -698L 392 -713L 392 -747L 36 -747Z",[-0.815,0.01]],["M 417 20C 595 20 692 -84 695 -314L 699 -747L 647 -747L 651 -316C 653 -135 586 -62 470 -62C 355 -62 295 -129 295 -312L 295 -406C 295 -520 295 -634 297 -747L 121 -747C 125 -633 125 -518 125 -406L 125 -297C 125 -61 245 20 417 20Z",[-0.062,0.22]],["M 533 -713L 657 -697L 689 -697L 802 -713L 802 -747L 533 -747Z",[-0.295,0.048]]],"bbox":{"top":-747,"bottom":20,"left":36,"right":802},"hadv":829}],"text":"GPU","hadv":2285,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"passthrough","hadv":6578,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>最近灵车 Libvirt GPU Passthrough 爆炸了，记录一下踩到的坑。</p>\n<h2>Unknown PCI header type ‘127’</h2>\n<p>According to 有能群友 127 是 PCIe 读取字段超时返回的错误值，在这里是由于显卡没有正确 Reset。</p>\n<p>通常进行 GPU passthrough 的设置时需要使用 vfio-pci 驱动，以防止驱动在显卡上电之后进行设置导致无法正确 Reset。然而对于 NVIDIA 20xx 显卡，<strong>使用 Nouveau 驱动可以正常在直通后 Reset，但是使用 vfio-pci 会出 127</strong>。这个现象和 AMD 显卡是正好相反的。</p>\n<p>一个好处是，这样可以在直通前让 BIOS / GRUB / Host 直接用这个显卡输出，就算只有一个显示器也不用拔拔插插了。</p>\n<h2>启动虚拟机后黑屏没反应</h2>\n<p>没反应指就连 OVMF 的 Logo 都没出现。我一开始以为是直通挂了，但是观察 CPU usage 发现有一个核心狂转。</p>\n<p>最后发现这是近期另一个修改导致的：ArchLinux 在最近把 <code>edk2-ovmf</code> 包中的数个 2M 版本的固件/模板文件删除了，<a href=\"https://bbs.archlinux.org/viewtopic.php?id=300862\">ArchLinux 论坛</a> 给出的解决方法是直接用 4M 版本。<strong>但是在我这里额外需要清空 NVRAM:</strong></p>\n<pre><code>virsh start vm --reset-nvram\n</code></pre>\n<p>之后正常启动。</p>\n","plain":"最近灵车 Libvirt GPU Passthrough 爆炸了，记录一下踩到的坑。\n\nUnknown PCI header type ‘127’\nAccording to 有能群友 127 是 PCIe 读取字段超时返回的错误值，在这里是由于显卡没有正确 Reset。\n通常进行 GPU passthrough 的设置时需要使用 vfio-pci 驱动，以防止驱动在显卡上电之后进行设置导致无法正确 Reset。然而对于 NVIDIA 20xx 显卡，使用 Nouveau 驱动可以正常在直通后 Reset，但是使用 vfio-pci 会出 127。这个现象和 AMD 显卡是正好相反的。\n一个好处是，这样可以在直通前让 BIOS / GRUB / Host 直接用这个显卡输出，就算只有一个显示器也不用拔拔插插了。\n\n启动虚拟机后黑屏没反应\n没反应指就连 OVMF 的 Logo 都没出现。我一开始以为是直通挂了，但是观察 CPU usage 发现有一个核心狂转。\n最后发现这是近期另一个修改导致的：ArchLinux 在最近把 edk2-ovmf 包中的数个 2M 版本的固件/模板文件删除了，ArchLinux 论坛 给出的解决方法是直接用 4M 版本。但是在我这里额外需要清空 NVRAM:\nvirsh start vm --reset-nvram\n\n之后正常启动。\n"},{"metadata":{"id":"tomato","lang":"zh-CN","title":"扔番茄","tags":["开发","TUNA","前端"],"publish_time":"2025-04-03T03:34:07+08:00","update_time":"2025-04-03T05:27:24+08:00","title_outline":{"groups":[{"chars":[{"char":"扔","components":[["M 18 -378L 66 -220C 79 -224 90 -236 95 -249C 249 -340 358 -417 424 -467L 421 -477C 258 -432 83 -390 18 -378Z",[0.627,0.286]],["M 319 -839L 147 -855L 147 -85C 147 -75 143 -70 128 -70C 108 -70 22 -75 22 -75L 22 -61C 67 -52 86 -37 100 -13C 113 10 118 44 121 93C 264 79 282 25 282 -72L 282 -811C 307 -814 317 -824 319 -839Z",[0.032,0.836]],["M 336 -703L 282 -615L 23 -615L 31 -587L 403 -587C 417 -587 427 -592 430 -603C 397 -642 336 -703 336 -703Z",[0.727,0.084]],["M 604 -763L 456 -763C 455 -449 470 -164 277 82L 288 96C 599 -112 599 -412 604 -763Z",[0.163,0.792]],["M 759 -763L 346 -763L 355 -735L 759 -735Z",[-0.827,0.021]],["M 798 -477L 809 -477C 802 -231 789 -96 760 -71C 752 -64 743 -61 727 -61C 704 -61 639 -64 595 -68L 595 -57C 641 -46 676 -30 694 -9C 711 10 716 43 715 85C 785 85 827 72 863 41C 920 -7 937 -129 946 -425C 969 -428 981 -435 989 -444L 870 -547Z",[0.161,0.668]],["M 828 -725L 694 -761C 688 -698 657 -534 635 -462L 672 -499C 649 -492 623 -476 608 -461L 732 -392L 779 -449L 771 -449C 789 -519 818 -667 828 -725Z",[0.154,0.576]],["M 682 -763L 694 -763L 708 -704C 771 -691 846 -687 868 -710L 745 -825Z",[0.192,0.226]],["M 873 -477L 713 -477L 713 -449L 873 -449Z",[-0.39,0.115]]],"bbox":{"top":-855,"bottom":96,"left":18,"right":989},"hadv":1000}],"text":"扔","hadv":1000,"breakAfter":true},{"chars":[{"char":"番","components":[["M 328 -534C 268 -425 156 -308 19 -235L 25 -224C 232 -283 401 -382 490 -518L 490 -534Z",[0.611,0.471]],["M 36 -534L 44 -506L 943 -506C 958 -506 969 -511 972 -522C 924 -562 846 -618 846 -618L 777 -534Z",[0.937,0.027]],["M 746 -857C 598 -808 312 -751 90 -727L 91 -713C 327 -701 613 -711 797 -732C 832 -718 857 -718 869 -728Z",[0.753,0.087]],["M 194 -291L 194 94L 214 94C 270 94 334 65 334 53L 334 -259L 763 -259L 763 -291L 342 -291L 194 -348Z",[0.285,0.243]],["M 215 -703L 207 -698C 229 -662 244 -608 241 -558C 349 -458 496 -663 215 -703Z",[-0.073,0.269]],["M 265 -148L 265 -120L 769 -120L 769 -148Z",[-0.953,0.001]],["M 265 3L 265 31L 769 31L 769 3Z",[0.944,0.0]],["M 433 -748L 433 -307L 459 -307C 530 -307 572 -336 573 -343L 573 -770Z",[0.017,0.679]],["M 437 -291L 437 14L 572 14L 572 -291Z",[-0.002,0.565]],["M 587 -534L 577 -528C 634 -380 743 -292 886 -232C 900 -298 933 -342 984 -357L 985 -368C 838 -387 662 -435 587 -534Z",[-0.569,0.29]],["M 674 -720C 656 -652 633 -578 614 -533L 625 -525C 681 -551 745 -590 799 -632C 821 -630 835 -638 840 -650Z",[0.417,0.258]],["M 683 -291L 683 88L 708 88C 754 88 824 63 825 55L 825 -244C 844 -247 855 -256 860 -263L 735 -357L 673 -291Z",[0.022,0.593]]],"bbox":{"top":-857,"bottom":94,"left":19,"right":985},"hadv":1000}],"text":"番","hadv":1000,"breakAfter":true},{"chars":[{"char":"茄","components":[["M 153 -620C 152 -355 165 -118 13 82L 24 95C 288 -70 287 -315 295 -578C 318 -582 328 -591 330 -605Z",[0.159,0.77]],["M 27 -454L 36 -426L 416 -426L 416 -454Z",[-0.831,0.006]],["M 27 -721L 34 -693L 275 -693L 275 -577L 298 -577C 360 -577 416 -596 416 -608L 416 -693L 575 -693L 575 -583L 598 -583C 662 -583 719 -602 719 -614L 719 -693L 946 -693C 961 -693 972 -698 974 -709C 931 -752 854 -814 854 -814L 785 -721L 719 -721L 719 -813C 745 -817 753 -826 754 -839L 575 -854L 575 -721L 416 -721L 416 -813C 442 -817 450 -826 451 -839L 275 -854L 275 -721Z",[0.634,0.033]],["M 355 -454C 350 -197 343 -86 318 -63C 311 -56 303 -54 289 -54C 271 -54 227 -55 201 -58L 201 -46C 237 -37 258 -23 272 -3C 285 15 287 46 287 88C 344 88 385 75 418 46C 471 2 483 -92 489 -403C 510 -406 523 -413 530 -422L 414 -522L 344 -454Z",[0.124,0.708]],["M 548 -495L 548 89L 569 89C 629 89 685 57 685 42L 685 -467L 841 -467L 841 -495L 689 -495L 548 -552Z",[0.046,0.706]],["M 616 -40L 616 -12L 848 -12L 848 -40Z",[0.879,0.001]],["M 775 -495L 775 73L 798 73C 846 73 914 46 915 37L 915 -445C 935 -449 948 -458 955 -466L 828 -565L 765 -495Z",[0.014,0.732]]],"bbox":{"top":-854,"bottom":95,"left":13,"right":974},"hadv":1000}],"text":"茄","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>TUNA April fools 写了一段小脚本来扔番茄。使用 Tempermonkey 或者类似的脚本注入插件应该可以让任何页面都可以扔番茄。Alternatively, 直接在 Devtools 里面执行，不需要额外加载任何跨域的东西，或者修改 HTML / CSS。</p>\n<script id=\"tomato-script\" type=\"application/text\">\nfunction tomato() {\n  const LIFE = 1;\n  let INIT_VY = -100;\n  let GRAVITY = 400;\n  let VARIANCE = 100;\n  let TOMATO = '🍅';\n  const POV = 0.5;\n\n  const tomatos = new Set()// { div, x, y, spawn, lastUpdate, vy, vx }\n  let cnt = 0;\n\n  function renderTomato(now, tomato) {\n    const zoom = POV / (POV + (now - tomato.spawn) / 1000);\n    tomato.div.style.transform = `translate(${tomato.x}px, ${tomato.y}px) scale(${zoom})`;\n  }\n\n  function updateTomato(now, tomato) {\n    let dt = (now - tomato.lastUpdate) / 1000;\n    let dying = (now - tomato.spawn) / 1000 >= LIFE;\n    if(dying) dt = LIFE - (tomato.lastUpdate - tomato.spawn) / 1000;\n\n    tomato.lastUpdate = now;\n\n    tomato.x += tomato.vx * dt;\n    tomato.y += tomato.vy * dt + 1/2 * GRAVITY * dt * dt;\n    tomato.vy += GRAVITY * dt;\n\n    return dying;\n  }\n\n  function dropTomato(tomato) {\n    tomatos.delete(tomato);\n\n    tomato.div.innerHTML = `<svg id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 39.69563762 38.43225379\"><path d=\"M18.98199913,4.97441789c1.56389432,4.80745789-.46066328,7.62163229-2.44002861,8.29263583-2.53598286.8596961-4.29761578-4.38429468-9.15011136-3.87008242-1.84382446.19538768-3.83614081,1.67551244-3.96504717,3.20253725-.24510055,2.90345579,6.40775611,4.06600515,6.86258216,8.46385293.15587863,1.50723321-.4478001,3.08938046-1.37251658,4.1175483-2.50284238,2.78284525-6.6955892.77141179-8.31134895,3.05003683-1.27961983,1.80458492-.39350903,5.5250663,1.37251586,6.25257408,2.57504129,1.0607807,5.40751027-4.90627186,10.75137913-4.49880362,1.85716764.14160855,3.26719114.99590292,3.88879768,1.37251515,3.72767703,2.25849263,3.34935929,5.41581108,5.9475704,6.6338294,3.32293532,1.55776247,8.75531949-1.3500013,8.76885518-3.4312893.01447686-2.22604518-2.3623387-3.59522382-3.12628675-7.72005619-.08354425-.45108135-.02054675-1.91027265.68625821-2.97378559,2.20132386-3.31228302,5.92067206,2.11272658,9.30260999-1.35380229,1.78983712-1.83460815,1.98686044-5.52309556.53375573-6.93883308-2.24108389-2.18345025-4.10409597,3.31455119-8.4638493.59129322-.49912935-.31177438-2.17815591-2.27556367-2.51628011-4.04129836-.73223358-3.82383719,2.45043615-6.64531075,1.83002176-9.43639977-.73251878-3.29542044-9.33401606-3.47168043-10.67512761-1.00997524-.53308266.97851059-.83545238.49490025.07625032,3.29750287Z\" fill=\"#ed2024\"/><path d=\"M23.72192942,12.5577001c.51093442,2.75402331-1.44313217,4.30434921-3.70591707,5.2953825-1.28405586,4.90638674,1.54601253,7.48536382,3.98242138,11.20577448,1.25273644-6.92586461-2.39798413-6.51376096,6.72470957-5.88299674,3.45361313-4.01403833-5.1613199-2.7864131-7.52321941-3.30795619.38946259-2.19197062,2.66072592-5.89503736,1.06679418-7.83927725\" fill=\"#51b848\"/></svg>`\n\n    tomato.div.classList.add('splash');\n    const vpx = tomato.x - window.visualViewport.pageLeft;\n    const vpy = tomato.y - window.visualViewport.pageTop;\n    const stack = document.elementsFromPoint(vpx, vpy);\n    const field = document.getElementById('field');\n    const ctrl = document.getElementsByClassName('field-ctrl')[0];\n    for(const el of stack) {\n      // Skip tomato\n      if(field && field.contains(el)) continue;\n      if(ctrl && ctrl.contains(el)) continue;\n      try {\n        if(el.computedStyleMap().get('pointer-events').toString() === 'none') continue;\n      } catch(e) {\n        console.log('Firefox?', el);\n      }\n      console.log(el);\n      return el;\n    }\n\n    return null;\n  }\n\n  console.log('🍅 registered');\n\n  document.addEventListener('click', function(event) {\n    const ctrl = document.getElementsByClassName('field-ctrl')[0];\n    if(event.pointerType === 'synthetic') return;\n    if(ctrl && ctrl.contains(event.target)) return;\n    console.log('clicked at ', event.pageX, event.pageY);\n    event.preventDefault();\n    event.stopPropagation();\n    event.stopImmediatePropagation();\n\n    const div = document.createElement('div');\n    const inner = document.createElement('div');\n    inner.innerText = TOMATO;\n    inner.className = 'tomato-inner';\n    div.appendChild(inner);\n    div.className = 'tomato';\n\n    const now = document.timeline.currentTime;\n    const tomato = {\n      div,\n      x: event.pageX,\n      y: event.pageY,\n      spawn: now,\n      lastUpdate: now,\n      vy: INIT_VY + (Math.random() - 1/2) * VARIANCE,\n      vx: (Math.random() - 1/2) * VARIANCE,\n    };\n    renderTomato(now, tomato);\n\n    const field = document.getElementById('field');\n    field.appendChild(div);\n    tomatos.add(tomato);\n    cnt += 1;\n    if(cnt === 10) {\n      const ctrl = document.getElementsByClassName('field-ctrl')[0];\n      // window.localStorage.setItem('tomato-hint', 'true');\n      if(ctrl.classList.contains('tucked')) {\n        ctrl.classList.remove('tucked');\n        ctrl.classList.add('hidden');\n      }\n    }\n\n  }, {\n    capture: true,\n  });\n\n  function loop(ts) {\n    const clickTargets = [];\n    for (const tomato of tomatos) {\n      const dying = updateTomato(ts, tomato);\n      renderTomato(ts, tomato);\n      if(dying) {\n        const target = dropTomato(tomato);\n        if(target) clickTargets.push(target);\n      }\n    }\n\n    if(clickTargets.length > 0) {\n      for (const target of clickTargets) {\n        const event = new PointerEvent('click', {\n          bubbles: true,\n          pointerType: 'synthetic',\n        });\n        target.dispatchEvent(event);\n      }\n    }\n\n    requestAnimationFrame(loop);\n  }\n\n  requestAnimationFrame(loop);\n\n  function setData(key, value) {\n    const input = document.getElementById(`field-${key}`);\n    input.value = value;\n    const ev = new Event('input', {\n      bubbles: true,\n      cancelable: true,\n    });\n    input.dispatchEvent(ev);\n  }\n\n  function lazerSettings() {\n    setData('variance', 0);\n    setData('gravity', 0);\n    setData('init-vy', 0);\n  }\n\n  function defaultSettings() {\n    setData('variance', 100);\n    setData('gravity', 400);\n    setData('init-vy', -100);\n  }\n\n  // HTML\n  const wrapper = document.createElement('div');\n  wrapper.innerHTML = `\n  <div id=\"field\"></div>\n  <div class=\"field-ctrl tucked\">\n      <div class=\"field-ctrl-toggle\">\n          🍅 Got stuck?\n      </div>\n\n      <div class=\"field-ctrl-main\">\n          <div class=\"field-ctrl-info\">\n              <span>\n                  Aim for your target!\n              </span>\n              <button id=\"field-ctrl-lazer\">Turn into lazer</button>\n              <button id=\"field-ctrl-default\">Deafult</button>\n          </div>\n          <div>\n              <input id=\"field-variance\" type=\"range\" min=\"0\" max=\"100\" value=\"100\" >\n              <label for=\"field-variance\">Variance: 100</label>\n          </div>\n          <div>\n              <input id=\"field-gravity\" type=\"range\" min=\"0\" max=\"1000\" value=\"400\" >\n              <label for=\"field-gravity\">Gravity: 400</label>\n          </div>\n          <div>\n              <input id=\"field-init-vy\" type=\"range\" min=\"-200\" max=\"200\" value=\"-100\" >\n              <label for=\"field-init-vy\">Initial Velocity: -100</label>\n          </div>\n      </div>\n  </div>\n  <style>\n  #field {\n    position: absolute;\n    z-index: 100000;\n    pointer-events: none;\n  }\n\n  .tomato {\n    width: 40px;\n    height: 40px;\n    position: absolute;\n    top: -20px;\n    left: -20px;\n    transform-origin: 50% 50%;\n  }\n\n  .tomato-inner {\n    width: 40px;\n    height: 40px;\n\n    animation: tomato-rotate .5s linear infinite;\n\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 40px;\n  }\n\n  @keyframes tomato-rotate {\n    0% {\n      transform: rotate(0deg);\n    }\n    100% {\n      transform: rotate(360deg);\n    }\n  }\n\n  .tomato.splash svg {\n    transform-origin: 50% 50%;\n    transform: scale(3);\n  }\n\n  .field-ctrl {\n    position: fixed;\n    z-index: 100005;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    padding: 0 20px 20px 20px;\n    transition: transform .2s ease;\n  }\n\n  .field-ctrl-toggle {\n    margin-bottom: 20px;\n    padding: 0 20px;\n    height: 40px;\n    line-height: 40px;\n    max-width: 200px;\n    background: var(--color-bg);\n    box-shadow: rgba(0,0,0, .3) 0 4px 6px;\n    font-weight: bold;\n    cursor: pointer;\n    border-radius: 4px;\n  }\n\n  .field-ctrl-main {\n    padding: 10px 20px;\n    background: var(--color-bg);\n    box-shadow: rgba(0,0,0, .3) 0 4px 6px;\n    border-radius: 4px;\n\n    & > div {\n      display: flex;\n      align-items: center;\n\n      & > input {\n        flex: 1;\n      }\n\n      & > label {\n        margin-left: 10px;\n      }\n    }\n  }\n\n\n  .field-ctrl.tucked {\n    transform: translateY(calc(100% + 20px));\n  }\n\n  .field-ctrl.hidden {\n    transform: translateY(calc(100% - 50px));\n  }\n\n  .field-ctrl-info {\n    display: flex;\n    align-items: center;\n    & > span {\n      flex: 1;\n    }\n    & button {\n      margin-left: 10px;\n    }\n  }\n  </style>\n  `;\n\n  function setup() {\n    // Inject HTML\n    document.body.prepend(wrapper);\n\n    const toggle = document.getElementsByClassName('field-ctrl-toggle')[0];\n    toggle.addEventListener('click', function() {\n      const ctrl = document.getElementsByClassName('field-ctrl')[0];\n      ctrl.classList.toggle('hidden');\n    });\n\n    const defaultBtn = document.getElementById('field-ctrl-default');\n    defaultBtn.addEventListener('click', function() {\n      defaultSettings();\n    });\n\n    const lazer = document.getElementById('field-ctrl-lazer');\n    lazer.addEventListener('click', function() {\n      lazerSettings();\n    });\n\n    const variance = document.getElementById('field-variance');\n    variance.addEventListener('input', function() {\n      VARIANCE = parseInt(variance.value);\n      const varianceLabel = document.querySelector('label[for=\"field-variance\"]');\n      varianceLabel.innerText = `Variance: ${VARIANCE}`;\n      // window.localStorage.setItem('tomato-variance', VARIANCE);\n    });\n\n    const gravity = document.getElementById('field-gravity');\n    gravity.addEventListener('input', function() {\n      console.log('Update gravity: ', gravity.value);\n      GRAVITY = parseInt(gravity.value);\n      const gravityLabel = document.querySelector('label[for=\"field-gravity\"]');\n      gravityLabel.innerText = `Gravity: ${GRAVITY}`;\n      // window.localStorage.setItem('tomato-gravity', GRAVITY);\n    });\n\n    const init_vy = document.getElementById('field-init-vy');\n    init_vy.addEventListener('input', function() {\n      INIT_VY = parseInt(init_vy.value);\n      const initVyLabel = document.querySelector('label[for=\"field-init-vy\"]');\n      initVyLabel.innerText = `Initial Velocity: ${INIT_VY}`;\n      // window.localStorage.setItem('tomato-init-vy', INIT_VY);\n    });\n\n    // Recover stored settings\n    // setData('variance', parseInt(window.localStorage.getItem('tomato-variance') ?? 100));\n    // setData('gravity', parseInt(window.localStorage.getItem('tomato-gravity') ?? 400));\n    // setData('init-vy', parseInt(window.localStorage.getItem('tomato-init-vy') ?? -100));\n    // if(window.localStorage.getItem('tomato-hint') === 'true') {\n    //   const ctrl = document.getElementsByClassName('field-ctrl')[0];\n    //   ctrl.classList.remove('tucked');\n    //   ctrl.classList.add('hidden');\n    // }\n  };\n\n  if(document.readyState !== 'loading') setup();\n  else document.addEventListener('DOMContentLoaded', () => setup());\n}\ntomato();\n</script>\n<p><a href=\"javascript:console.log(eval(document.getElementById('tomato-script').innerText))\">点我扔番茄</a></p>\n<p>注：这个实现会 Break 掉部分使用 <code>preventsDefault</code> 的网站，比如这个博客本身，原因不太清楚。使用 <code>dispatchEvent</code> 触发的点击行为一直就不太一致。</p>\n<p>注2：这个实现使用了 <code>stopImmediatePropagation()</code> 来尝试禁用所有其他点击的 event handler，并且添加在 <code>window</code> 的 capture 阶段。不过这还是依赖 handler 的添加顺序，例如 jQuery (in turn, Bootstrap) 没有用 DOM 自己的 event propagation，所以它的事件也是一个挂在 <code>window</code> 的 capture 阶段的 handler 处理的，这样这个脚本必须先于 jQuery 的初始化注册 handler，否则例如 Bootstrap 的下拉框、Modal 之类的点击行为不会被撤销掉。</p>\n<p>注3：实现中控制参数存入 localStorage 的部分被注释掉了，如果有需求可以启用。另一方面，控制参数的 UI 背景是用 CSS Variable <code>--color-bg</code> 控制的，请按需修改。</p>\n<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">LIFE </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">INIT_VY </span><span style=\"color:#657b83;\">= -</span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">GRAVITY </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">400</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">VARIANCE </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">TOMATO </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">🍅</span><span style=\"color:#839496;\">&#39;;\n</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">POV </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">0.5</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">tomatos </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">new Set</span><span style=\"color:#657b83;\">()</span><span style=\"color:#586e75;\">// { div, x, y, spawn, lastUpdate, vy, vx }\n</span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">cnt </span><span style=\"color:#657b83;\">= </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">renderTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">now</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">tomato</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">zoom </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">POV </span><span style=\"color:#657b83;\">/ (</span><span style=\"color:#839496;\">POV </span><span style=\"color:#657b83;\">+ (</span><span style=\"color:#839496;\">now </span><span style=\"color:#657b83;\">- </span><span style=\"color:#839496;\">tomato.spawn</span><span style=\"color:#657b83;\">) / </span><span style=\"color:#6c71c4;\">1000</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  tomato.div.style.transform </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">`</span><span style=\"color:#2aa198;\">translate(</span><span style=\"color:#839496;\">${tomato.x}</span><span style=\"color:#2aa198;\">px, </span><span style=\"color:#839496;\">${tomato.y}</span><span style=\"color:#2aa198;\">px) scale(</span><span style=\"color:#839496;\">${zoom}</span><span style=\"color:#2aa198;\">)</span><span style=\"color:#839496;\">`;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">updateTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">now</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">tomato</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">dt </span><span style=\"color:#657b83;\">= (</span><span style=\"color:#839496;\">now </span><span style=\"color:#657b83;\">- </span><span style=\"color:#839496;\">tomato.lastUpdate</span><span style=\"color:#657b83;\">) / </span><span style=\"color:#6c71c4;\">1000</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">let </span><span style=\"color:#839496;\">dying </span><span style=\"color:#657b83;\">= (</span><span style=\"color:#839496;\">now </span><span style=\"color:#657b83;\">- </span><span style=\"color:#839496;\">tomato.spawn</span><span style=\"color:#657b83;\">) / </span><span style=\"color:#6c71c4;\">1000 </span><span style=\"color:#859900;\">&gt;= </span><span style=\"color:#839496;\">LIFE;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">dying</span><span style=\"color:#657b83;\">) </span><span style=\"color:#839496;\">dt </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">LIFE </span><span style=\"color:#657b83;\">- (</span><span style=\"color:#839496;\">tomato.lastUpdate </span><span style=\"color:#657b83;\">- </span><span style=\"color:#839496;\">tomato.spawn</span><span style=\"color:#657b83;\">) / </span><span style=\"color:#6c71c4;\">1000</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  tomato.lastUpdate </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">now;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  tomato.x </span><span style=\"color:#657b83;\">+= </span><span style=\"color:#839496;\">tomato.vx </span><span style=\"color:#657b83;\">* </span><span style=\"color:#839496;\">dt;\n</span><span style=\"color:#839496;\">  tomato.y </span><span style=\"color:#657b83;\">+= </span><span style=\"color:#839496;\">tomato.vy </span><span style=\"color:#657b83;\">* </span><span style=\"color:#839496;\">dt </span><span style=\"color:#657b83;\">+ </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#657b83;\">/</span><span style=\"color:#6c71c4;\">2 </span><span style=\"color:#657b83;\">* </span><span style=\"color:#839496;\">GRAVITY </span><span style=\"color:#657b83;\">* </span><span style=\"color:#839496;\">dt </span><span style=\"color:#657b83;\">* </span><span style=\"color:#839496;\">dt;\n</span><span style=\"color:#839496;\">  tomato.vy </span><span style=\"color:#657b83;\">+= </span><span style=\"color:#839496;\">GRAVITY </span><span style=\"color:#657b83;\">* </span><span style=\"color:#839496;\">dt;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">return </span><span style=\"color:#839496;\">dying;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">dropTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">tomato</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  tomatos.</span><span style=\"color:#b58900;\">delete</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">tomato</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  tomato.div.innerHTML </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">`</span><span style=\"color:#2aa198;\">&lt;svg id=&quot;Layer_1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 39.69563762 38.43225379&quot;&gt;&lt;path d=&quot;M18.98199913,4.97441789c1.56389432,4.80745789-.46066328,7.62163229-2.44002861,8.29263583-2.53598286.8596961-4.29761578-4.38429468-9.15011136-3.87008242-1.84382446.19538768-3.83614081,1.67551244-3.96504717,3.20253725-.24510055,2.90345579,6.40775611,4.06600515,6.86258216,8.46385293.15587863,1.50723321-.4478001,3.08938046-1.37251658,4.1175483-2.50284238,2.78284525-6.6955892.77141179-8.31134895,3.05003683-1.27961983,1.80458492-.39350903,5.5250663,1.37251586,6.25257408,2.57504129,1.0607807,5.40751027-4.90627186,10.75137913-4.49880362,1.85716764.14160855,3.26719114.99590292,3.88879768,1.37251515,3.72767703,2.25849263,3.34935929,5.41581108,5.9475704,6.6338294,3.32293532,1.55776247,8.75531949-1.3500013,8.76885518-3.4312893.01447686-2.22604518-2.3623387-3.59522382-3.12628675-7.72005619-.08354425-.45108135-.02054675-1.91027265.68625821-2.97378559,2.20132386-3.31228302,5.92067206,2.11272658,9.30260999-1.35380229,1.78983712-1.83460815,1.98686044-5.52309556.53375573-6.93883308-2.24108389-2.18345025-4.10409597,3.31455119-8.4638493.59129322-.49912935-.31177438-2.17815591-2.27556367-2.51628011-4.04129836-.73223358-3.82383719,2.45043615-6.64531075,1.83002176-9.43639977-.73251878-3.29542044-9.33401606-3.47168043-10.67512761-1.00997524-.53308266.97851059-.83545238.49490025.07625032,3.29750287Z&quot; fill=&quot;#ed2024&quot;/&gt;&lt;path d=&quot;M23.72192942,12.5577001c.51093442,2.75402331-1.44313217,4.30434921-3.70591707,5.2953825-1.28405586,4.90638674,1.54601253,7.48536382,3.98242138,11.20577448,1.25273644-6.92586461-2.39798413-6.51376096,6.72470957-5.88299674,3.45361313-4.01403833-5.1613199-2.7864131-7.52321941-3.30795619.38946259-2.19197062,2.66072592-5.89503736,1.06679418-7.83927725&quot; fill=&quot;#51b848&quot;/&gt;&lt;/svg&gt;</span><span style=\"color:#839496;\">`\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  tomato.div.classList.</span><span style=\"color:#859900;\">add</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">splash</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">vpx </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">tomato.x </span><span style=\"color:#657b83;\">- </span><span style=\"color:#859900;\">window</span><span style=\"color:#839496;\">.visualViewport.pageLeft;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">vpy </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">tomato.y </span><span style=\"color:#657b83;\">- </span><span style=\"color:#859900;\">window</span><span style=\"color:#839496;\">.visualViewport.pageTop;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">stack </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">elementsFromPoint</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">vpx, vpy</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">field </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">ctrl </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">getElementsByClassName</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#268bd2;\">[</span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">for</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">el </span><span style=\"color:#859900;\">of </span><span style=\"color:#839496;\">stack</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// Skip tomato\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">field </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#839496;\">field.</span><span style=\"color:#b58900;\">contains</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">el</span><span style=\"color:#657b83;\">)) </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ctrl </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#839496;\">ctrl.</span><span style=\"color:#b58900;\">contains</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">el</span><span style=\"color:#657b83;\">)) </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">try </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">el.</span><span style=\"color:#b58900;\">computedStyleMap</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">get</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">pointer-events</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">toString</span><span style=\"color:#657b83;\">() === </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">none</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">) </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">} </span><span style=\"color:#859900;\">catch</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">e</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">console</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">log</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">Firefox?</span><span style=\"color:#839496;\">&#39;, el</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">console</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">log</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">el</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">return </span><span style=\"color:#839496;\">el;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">return </span><span style=\"color:#b58900;\">null</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">console</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">log</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">🍅 registered</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">click</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">event</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">ctrl </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">getElementsByClassName</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#268bd2;\">[</span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">event.pointerType </span><span style=\"color:#657b83;\">=== </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">synthetic</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">) </span><span style=\"color:#859900;\">return</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ctrl </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#839496;\">ctrl.</span><span style=\"color:#b58900;\">contains</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">event.target</span><span style=\"color:#657b83;\">)) </span><span style=\"color:#859900;\">return</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">console</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">log</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">clicked at </span><span style=\"color:#839496;\">&#39;, event.pageX, event.pageY</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  event.</span><span style=\"color:#b58900;\">preventDefault</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  event.</span><span style=\"color:#b58900;\">stopPropagation</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  event.</span><span style=\"color:#b58900;\">stopImmediatePropagation</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">div </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">createElement</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">div</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">inner </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">createElement</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">div</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  inner.innerText </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">TOMATO;\n</span><span style=\"color:#839496;\">  inner.className </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">tomato-inner</span><span style=\"color:#839496;\">&#39;;\n</span><span style=\"color:#839496;\">  div.</span><span style=\"color:#859900;\">appendChild</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">inner</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  div.className </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">tomato</span><span style=\"color:#839496;\">&#39;;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">now </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.timeline.currentTime;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">tomato </span><span style=\"color:#657b83;\">= {\n</span><span style=\"color:#839496;\">    div,\n</span><span style=\"color:#839496;\">    x: event.pageX,\n</span><span style=\"color:#839496;\">    y: event.pageY,\n</span><span style=\"color:#839496;\">    spawn: now,\n</span><span style=\"color:#839496;\">    lastUpdate: now,\n</span><span style=\"color:#839496;\">    vy: INIT_VY </span><span style=\"color:#657b83;\">+ (</span><span style=\"color:#859900;\">Math</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">random</span><span style=\"color:#657b83;\">() - </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#657b83;\">/</span><span style=\"color:#6c71c4;\">2</span><span style=\"color:#657b83;\">) * </span><span style=\"color:#839496;\">VARIANCE,\n</span><span style=\"color:#839496;\">    vx: </span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">Math</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">random</span><span style=\"color:#657b83;\">() - </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#657b83;\">/</span><span style=\"color:#6c71c4;\">2</span><span style=\"color:#657b83;\">) * </span><span style=\"color:#839496;\">VARIANCE,\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">renderTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">now, tomato</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">field </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  field.</span><span style=\"color:#859900;\">appendChild</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">div</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  tomatos.</span><span style=\"color:#859900;\">add</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">tomato</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  cnt </span><span style=\"color:#657b83;\">+= </span><span style=\"color:#6c71c4;\">1</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">cnt </span><span style=\"color:#657b83;\">=== </span><span style=\"color:#6c71c4;\">10</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">ctrl </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">getElementsByClassName</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#268bd2;\">[</span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// window.localStorage.setItem(&#39;tomato-hint&#39;, &#39;true&#39;);\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ctrl.classList.</span><span style=\"color:#b58900;\">contains</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">tucked</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)) {\n</span><span style=\"color:#839496;\">      ctrl.classList.</span><span style=\"color:#859900;\">remove</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">tucked</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      ctrl.classList.</span><span style=\"color:#859900;\">add</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">hidden</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">, </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  capture: </span><span style=\"color:#b58900;\">true</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">loop</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">ts</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">clickTargets </span><span style=\"color:#657b83;\">= </span><span style=\"color:#268bd2;\">[]</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">for </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">tomato </span><span style=\"color:#859900;\">of </span><span style=\"color:#839496;\">tomatos</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">dying </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">updateTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ts, tomato</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#b58900;\">renderTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ts, tomato</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">dying</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">target </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">dropTomato</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">tomato</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">target</span><span style=\"color:#657b83;\">) </span><span style=\"color:#839496;\">clickTargets.</span><span style=\"color:#859900;\">push</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">target</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">clickTargets.length </span><span style=\"color:#859900;\">&gt; </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">for </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">target </span><span style=\"color:#859900;\">of </span><span style=\"color:#839496;\">clickTargets</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">event </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">new </span><span style=\"color:#268bd2;\">PointerEvent</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">click</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">        bubbles: </span><span style=\"color:#b58900;\">true</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">        pointerType: &#39;</span><span style=\"color:#2aa198;\">synthetic</span><span style=\"color:#839496;\">&#39;,\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      target.</span><span style=\"color:#b58900;\">dispatchEvent</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">event</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">requestAnimationFrame</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">loop</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">requestAnimationFrame</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">loop</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">key</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">value</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">input </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">`</span><span style=\"color:#2aa198;\">field-</span><span style=\"color:#839496;\">${key}`</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  input.value </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">value;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">ev </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">new </span><span style=\"color:#268bd2;\">Event</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">input</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    bubbles: </span><span style=\"color:#b58900;\">true</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">    cancelable: </span><span style=\"color:#b58900;\">true</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  input.</span><span style=\"color:#b58900;\">dispatchEvent</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">ev</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">lazerSettings</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">variance</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">gravity</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">init-vy</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">defaultSettings</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">variance</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">gravity</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#6c71c4;\">400</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">setData</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">init-vy</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#657b83;\">-</span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">// HTML\n</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">wrapper </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">createElement</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">div</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">wrapper.innerHTML </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">`\n</span><span style=\"color:#2aa198;\">&lt;div id=&quot;field&quot;&gt;&lt;/div&gt;\n</span><span style=\"color:#2aa198;\">&lt;div class=&quot;field-ctrl tucked&quot;&gt;\n</span><span style=\"color:#2aa198;\">    &lt;div class=&quot;field-ctrl-toggle&quot;&gt;\n</span><span style=\"color:#2aa198;\">        🍅 Got stuck?\n</span><span style=\"color:#2aa198;\">    &lt;/div&gt;\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">    &lt;div class=&quot;field-ctrl-main&quot;&gt;\n</span><span style=\"color:#2aa198;\">        &lt;div class=&quot;field-ctrl-info&quot;&gt;\n</span><span style=\"color:#2aa198;\">            &lt;span&gt;\n</span><span style=\"color:#2aa198;\">                Aim for your target!\n</span><span style=\"color:#2aa198;\">            &lt;/span&gt;\n</span><span style=\"color:#2aa198;\">            &lt;button id=&quot;field-ctrl-lazer&quot;&gt;Turn into lazer&lt;/button&gt;\n</span><span style=\"color:#2aa198;\">            &lt;button id=&quot;field-ctrl-default&quot;&gt;Deafult&lt;/button&gt;\n</span><span style=\"color:#2aa198;\">        &lt;/div&gt;\n</span><span style=\"color:#2aa198;\">        &lt;div&gt;\n</span><span style=\"color:#2aa198;\">            &lt;input id=&quot;field-variance&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;100&quot; value=&quot;100&quot; &gt;\n</span><span style=\"color:#2aa198;\">            &lt;label for=&quot;field-variance&quot;&gt;Variance: 100&lt;/label&gt;\n</span><span style=\"color:#2aa198;\">        &lt;/div&gt;\n</span><span style=\"color:#2aa198;\">        &lt;div&gt;\n</span><span style=\"color:#2aa198;\">            &lt;input id=&quot;field-gravity&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;1000&quot; value=&quot;400&quot; &gt;\n</span><span style=\"color:#2aa198;\">            &lt;label for=&quot;field-gravity&quot;&gt;Gravity: 400&lt;/label&gt;\n</span><span style=\"color:#2aa198;\">        &lt;/div&gt;\n</span><span style=\"color:#2aa198;\">        &lt;div&gt;\n</span><span style=\"color:#2aa198;\">            &lt;input id=&quot;field-init-vy&quot; type=&quot;range&quot; min=&quot;-200&quot; max=&quot;200&quot; value=&quot;-100&quot; &gt;\n</span><span style=\"color:#2aa198;\">            &lt;label for=&quot;field-init-vy&quot;&gt;Initial Velocity: -100&lt;/label&gt;\n</span><span style=\"color:#2aa198;\">        &lt;/div&gt;\n</span><span style=\"color:#2aa198;\">    &lt;/div&gt;\n</span><span style=\"color:#2aa198;\">&lt;/div&gt;\n</span><span style=\"color:#2aa198;\">&lt;style&gt;\n</span><span style=\"color:#2aa198;\">#field {\n</span><span style=\"color:#2aa198;\">  position: absolute;\n</span><span style=\"color:#2aa198;\">  z-index: 100000;\n</span><span style=\"color:#2aa198;\">  pointer-events: none;\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.tomato {\n</span><span style=\"color:#2aa198;\">  width: 40px;\n</span><span style=\"color:#2aa198;\">  height: 40px;\n</span><span style=\"color:#2aa198;\">  position: absolute;\n</span><span style=\"color:#2aa198;\">  top: -20px;\n</span><span style=\"color:#2aa198;\">  left: -20px;\n</span><span style=\"color:#2aa198;\">  transform-origin: 50% 50%;\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.tomato-inner {\n</span><span style=\"color:#2aa198;\">  width: 40px;\n</span><span style=\"color:#2aa198;\">  height: 40px;\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">  animation: tomato-rotate .5s linear infinite;\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">  display: flex;\n</span><span style=\"color:#2aa198;\">  align-items: center;\n</span><span style=\"color:#2aa198;\">  justify-content: center;\n</span><span style=\"color:#2aa198;\">  font-size: 40px;\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">@keyframes tomato-rotate {\n</span><span style=\"color:#2aa198;\">  0% {\n</span><span style=\"color:#2aa198;\">    transform: rotate(0deg);\n</span><span style=\"color:#2aa198;\">  }\n</span><span style=\"color:#2aa198;\">  100% {\n</span><span style=\"color:#2aa198;\">    transform: rotate(360deg);\n</span><span style=\"color:#2aa198;\">  }\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.tomato.splash svg {\n</span><span style=\"color:#2aa198;\">  transform-origin: 50% 50%;\n</span><span style=\"color:#2aa198;\">  transform: scale(3);\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.field-ctrl {\n</span><span style=\"color:#2aa198;\">  position: fixed;\n</span><span style=\"color:#2aa198;\">  z-index: 100005;\n</span><span style=\"color:#2aa198;\">  bottom: 0;\n</span><span style=\"color:#2aa198;\">  left: 0;\n</span><span style=\"color:#2aa198;\">  right: 0;\n</span><span style=\"color:#2aa198;\">  padding: 0 20px 20px 20px;\n</span><span style=\"color:#2aa198;\">  transition: transform .2s ease;\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.field-ctrl-toggle {\n</span><span style=\"color:#2aa198;\">  margin-bottom: 20px;\n</span><span style=\"color:#2aa198;\">  padding: 0 20px;\n</span><span style=\"color:#2aa198;\">  height: 40px;\n</span><span style=\"color:#2aa198;\">  line-height: 40px;\n</span><span style=\"color:#2aa198;\">  max-width: 200px;\n</span><span style=\"color:#2aa198;\">  background: var(--color-bg);\n</span><span style=\"color:#2aa198;\">  box-shadow: rgba(0,0,0, .3) 0 4px 6px;\n</span><span style=\"color:#2aa198;\">  font-weight: bold;\n</span><span style=\"color:#2aa198;\">  cursor: pointer;\n</span><span style=\"color:#2aa198;\">  border-radius: 4px;\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.field-ctrl-main {\n</span><span style=\"color:#2aa198;\">  padding: 10px 20px;\n</span><span style=\"color:#2aa198;\">  background: var(--color-bg);\n</span><span style=\"color:#2aa198;\">  box-shadow: rgba(0,0,0, .3) 0 4px 6px;\n</span><span style=\"color:#2aa198;\">  border-radius: 4px;\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">  &amp; &gt; div {\n</span><span style=\"color:#2aa198;\">    display: flex;\n</span><span style=\"color:#2aa198;\">    align-items: center;\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">    &amp; &gt; input {\n</span><span style=\"color:#2aa198;\">      flex: 1;\n</span><span style=\"color:#2aa198;\">    }\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">    &amp; &gt; label {\n</span><span style=\"color:#2aa198;\">      margin-left: 10px;\n</span><span style=\"color:#2aa198;\">    }\n</span><span style=\"color:#2aa198;\">  }\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.field-ctrl.tucked {\n</span><span style=\"color:#2aa198;\">  transform: translateY(calc(100% + 20px));\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.field-ctrl.hidden {\n</span><span style=\"color:#2aa198;\">  transform: translateY(calc(100% - 50px));\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">\n</span><span style=\"color:#2aa198;\">.field-ctrl-info {\n</span><span style=\"color:#2aa198;\">  display: flex;\n</span><span style=\"color:#2aa198;\">  align-items: center;\n</span><span style=\"color:#2aa198;\">  &amp; &gt; span {\n</span><span style=\"color:#2aa198;\">    flex: 1;\n</span><span style=\"color:#2aa198;\">  }\n</span><span style=\"color:#2aa198;\">  &amp; button {\n</span><span style=\"color:#2aa198;\">    margin-left: 10px;\n</span><span style=\"color:#2aa198;\">  }\n</span><span style=\"color:#2aa198;\">}\n</span><span style=\"color:#2aa198;\">&lt;/style&gt;\n</span><span style=\"color:#839496;\">`;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">setup</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// Inject HTML\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.body.</span><span style=\"color:#b58900;\">prepend</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">wrapper</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">toggle </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">getElementsByClassName</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl-toggle</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#268bd2;\">[</span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  toggle.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">click</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">ctrl </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">getElementsByClassName</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#268bd2;\">[</span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    ctrl.classList.</span><span style=\"color:#b58900;\">toggle</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">hidden</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">defaultBtn </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl-default</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  defaultBtn.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">click</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#b58900;\">defaultSettings</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">lazer </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-ctrl-lazer</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  lazer.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">click</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#b58900;\">lazerSettings</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">variance </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-variance</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  variance.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">input</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    VARIANCE </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">parseInt</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">variance.value</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">varianceLabel </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">querySelector</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">label[for=&quot;field-variance&quot;]</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    varianceLabel.innerText </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">`</span><span style=\"color:#2aa198;\">Variance: </span><span style=\"color:#839496;\">${VARIANCE}`;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// window.localStorage.setItem(&#39;tomato-variance&#39;, VARIANCE);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">gravity </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-gravity</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  gravity.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">input</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">console</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">log</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">Update gravity: </span><span style=\"color:#839496;\">&#39;, gravity.value</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    GRAVITY </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">parseInt</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">gravity.value</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">gravityLabel </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">querySelector</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">label[for=&quot;field-gravity&quot;]</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    gravityLabel.innerText </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">`</span><span style=\"color:#2aa198;\">Gravity: </span><span style=\"color:#839496;\">${GRAVITY}`;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// window.localStorage.setItem(&#39;tomato-gravity&#39;, GRAVITY);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">init_vy </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">getElementById</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">field-init-vy</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  init_vy.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">input</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#268bd2;\">function</span><span style=\"color:#657b83;\">() {\n</span><span style=\"color:#839496;\">    INIT_VY </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">parseInt</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">init_vy.value</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">initVyLabel </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">querySelector</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">label[for=&quot;field-init-vy&quot;]</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    initVyLabel.innerText </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">`</span><span style=\"color:#2aa198;\">Initial Velocity: </span><span style=\"color:#839496;\">${INIT_VY}`;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">// window.localStorage.setItem(&#39;tomato-init-vy&#39;, INIT_VY);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// Recover stored settings\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// setData(&#39;variance&#39;, parseInt(window.localStorage.getItem(&#39;tomato-variance&#39;) ?? 100));\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// setData(&#39;gravity&#39;, parseInt(window.localStorage.getItem(&#39;tomato-gravity&#39;) ?? 400));\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// setData(&#39;init-vy&#39;, parseInt(window.localStorage.getItem(&#39;tomato-init-vy&#39;) ?? -100));\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// if(window.localStorage.getItem(&#39;tomato-hint&#39;) === &#39;true&#39;) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">//   const ctrl = document.getElementsByClassName(&#39;field-ctrl&#39;)[0];\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">//   ctrl.classList.remove(&#39;tucked&#39;);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">//   ctrl.classList.add(&#39;hidden&#39;);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">// }\n</span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">document</span><span style=\"color:#839496;\">.readyState </span><span style=\"color:#657b83;\">!== </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">loading</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">) </span><span style=\"color:#b58900;\">setup</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#859900;\">else document</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">DOMContentLoaded</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#657b83;\">() </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#b58900;\">setup</span><span style=\"color:#657b83;\">())</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>","plain":"TUNA April fools 写了一段小脚本来扔番茄。使用 Tempermonkey 或者类似的脚本注入插件应该可以让任何页面都可以扔番茄。Alternatively, 直接在 Devtools 里面执行，不需要额外加载任何跨域的东西，或者修改 HTML / CSS。\n点我扔番茄\n注：这个实现会 Break 掉部分使用 preventsDefault 的网站，比如这个博客本身，原因不太清楚。使用 dispatchEvent 触发的点击行为一直就不太一致。\n注2：这个实现使用了 stopImmediatePropagation() 来尝试禁用所有其他点击的 event handler，并且添加在 window 的 capture 阶段。不过这还是依赖 handler 的添加顺序，例如 jQuery (in turn, Bootstrap) 没有用 DOM 自己的 event propagation，所以它的事件也是一个挂在 window 的 capture 阶段的 handler 处理的，这样这个脚本必须先于 jQuery 的初始化注册 handler，否则例如 Bootstrap 的下拉框、Modal 之类的点击行为不会被撤销掉。\n注3：实现中控制参数存入 localStorage 的部分被注释掉了，如果有需求可以启用。另一方面，控制参数的 UI 背景是用 CSS Variable --color-bg 控制的，请按需修改。\nconst LIFE = 1;\nlet INIT_VY = -100;\nlet GRAVITY = 400;\nlet VARIANCE = 100;\nlet TOMATO = '🍅';\nconst POV = 0.5;\n\nconst tomatos = new Set()// { div, x, y, spawn, lastUpdate, vy, vx }\nlet cnt = 0;\n\nfunction renderTomato(now, tomato) {\n  const zoom = POV / (POV + (now - tomato.spawn) / 1000);\n  tomato.div.style.transform = `translate(${tomato.x}px, ${tomato.y}px) scale(${zoom})`;\n}\n\nfunction updateTomato(now, tomato) {\n  let dt = (now - tomato.lastUpdate) / 1000;\n  let dying = (now - tomato.spawn) / 1000 >= LIFE;\n  if(dying) dt = LIFE - (tomato.lastUpdate - tomato.spawn) / 1000;\n\n  tomato.lastUpdate = now;\n\n  tomato.x += tomato.vx * dt;\n  tomato.y += tomato.vy * dt + 1/2 * GRAVITY * dt * dt;\n  tomato.vy += GRAVITY * dt;\n\n  return dying;\n}\n\nfunction dropTomato(tomato) {\n  tomatos.delete(tomato);\n\n  tomato.div.innerHTML = `<svg id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 39.69563762 38.43225379\"><path d=\"M18.98199913,4.97441789c1.56389432,4.80745789-.46066328,7.62163229-2.44002861,8.29263583-2.53598286.8596961-4.29761578-4.38429468-9.15011136-3.87008242-1.84382446.19538768-3.83614081,1.67551244-3.96504717,3.20253725-.24510055,2.90345579,6.40775611,4.06600515,6.86258216,8.46385293.15587863,1.50723321-.4478001,3.08938046-1.37251658,4.1175483-2.50284238,2.78284525-6.6955892.77141179-8.31134895,3.05003683-1.27961983,1.80458492-.39350903,5.5250663,1.37251586,6.25257408,2.57504129,1.0607807,5.40751027-4.90627186,10.75137913-4.49880362,1.85716764.14160855,3.26719114.99590292,3.88879768,1.37251515,3.72767703,2.25849263,3.34935929,5.41581108,5.9475704,6.6338294,3.32293532,1.55776247,8.75531949-1.3500013,8.76885518-3.4312893.01447686-2.22604518-2.3623387-3.59522382-3.12628675-7.72005619-.08354425-.45108135-.02054675-1.91027265.68625821-2.97378559,2.20132386-3.31228302,5.92067206,2.11272658,9.30260999-1.35380229,1.78983712-1.83460815,1.98686044-5.52309556.53375573-6.93883308-2.24108389-2.18345025-4.10409597,3.31455119-8.4638493.59129322-.49912935-.31177438-2.17815591-2.27556367-2.51628011-4.04129836-.73223358-3.82383719,2.45043615-6.64531075,1.83002176-9.43639977-.73251878-3.29542044-9.33401606-3.47168043-10.67512761-1.00997524-.53308266.97851059-.83545238.49490025.07625032,3.29750287Z\" fill=\"#ed2024\"/><path d=\"M23.72192942,12.5577001c.51093442,2.75402331-1.44313217,4.30434921-3.70591707,5.2953825-1.28405586,4.90638674,1.54601253,7.48536382,3.98242138,11.20577448,1.25273644-6.92586461-2.39798413-6.51376096,6.72470957-5.88299674,3.45361313-4.01403833-5.1613199-2.7864131-7.52321941-3.30795619.38946259-2.19197062,2.66072592-5.89503736,1.06679418-7.83927725\" fill=\"#51b848\"/></svg>`\n\n  tomato.div.classList.add('splash');\n  const vpx = tomato.x - window.visualViewport.pageLeft;\n  const vpy = tomato.y - window.visualViewport.pageTop;\n  const stack = document.elementsFromPoint(vpx, vpy);\n  const field = document.getElementById('field');\n  const ctrl = document.getElementsByClassName('field-ctrl')[0];\n  for(const el of stack) {\n    // Skip tomato\n    if(field && field.contains(el)) continue;\n    if(ctrl && ctrl.contains(el)) continue;\n    try {\n      if(el.computedStyleMap().get('pointer-events').toString() === 'none') continue;\n    } catch(e) {\n      console.log('Firefox?', el);\n    }\n    console.log(el);\n    return el;\n  }\n\n  return null;\n}\n\nconsole.log('🍅 registered');\n\ndocument.addEventListener('click', function(event) {\n  const ctrl = document.getElementsByClassName('field-ctrl')[0];\n  if(event.pointerType === 'synthetic') return;\n  if(ctrl && ctrl.contains(event.target)) return;\n  console.log('clicked at ', event.pageX, event.pageY);\n  event.preventDefault();\n  event.stopPropagation();\n  event.stopImmediatePropagation();\n\n  const div = document.createElement('div');\n  const inner = document.createElement('div');\n  inner.innerText = TOMATO;\n  inner.className = 'tomato-inner';\n  div.appendChild(inner);\n  div.className = 'tomato';\n\n  const now = document.timeline.currentTime;\n  const tomato = {\n    div,\n    x: event.pageX,\n    y: event.pageY,\n    spawn: now,\n    lastUpdate: now,\n    vy: INIT_VY + (Math.random() - 1/2) * VARIANCE,\n    vx: (Math.random() - 1/2) * VARIANCE,\n  };\n  renderTomato(now, tomato);\n\n  const field = document.getElementById('field');\n  field.appendChild(div);\n  tomatos.add(tomato);\n  cnt += 1;\n  if(cnt === 10) {\n    const ctrl = document.getElementsByClassName('field-ctrl')[0];\n    // window.localStorage.setItem('tomato-hint', 'true');\n    if(ctrl.classList.contains('tucked')) {\n      ctrl.classList.remove('tucked');\n      ctrl.classList.add('hidden');\n    }\n  }\n\n}, {\n  capture: true,\n});\n\nfunction loop(ts) {\n  const clickTargets = [];\n  for (const tomato of tomatos) {\n    const dying = updateTomato(ts, tomato);\n    renderTomato(ts, tomato);\n    if(dying) {\n      const target = dropTomato(tomato);\n      if(target) clickTargets.push(target);\n    }\n  }\n\n  if(clickTargets.length > 0) {\n    for (const target of clickTargets) {\n      const event = new PointerEvent('click', {\n        bubbles: true,\n        pointerType: 'synthetic',\n      });\n      target.dispatchEvent(event);\n    }\n  }\n\n  requestAnimationFrame(loop);\n}\n\nrequestAnimationFrame(loop);\n\nfunction setData(key, value) {\n  const input = document.getElementById(`field-${key}`);\n  input.value = value;\n  const ev = new Event('input', {\n    bubbles: true,\n    cancelable: true,\n  });\n  input.dispatchEvent(ev);\n}\n\nfunction lazerSettings() {\n  setData('variance', 0);\n  setData('gravity', 0);\n  setData('init-vy', 0);\n}\n\nfunction defaultSettings() {\n  setData('variance', 100);\n  setData('gravity', 400);\n  setData('init-vy', -100);\n}\n\n// HTML\nconst wrapper = document.createElement('div');\nwrapper.innerHTML = `\n<div id=\"field\"></div>\n<div class=\"field-ctrl tucked\">\n    <div class=\"field-ctrl-toggle\">\n        🍅 Got stuck?\n    </div>\n\n    <div class=\"field-ctrl-main\">\n        <div class=\"field-ctrl-info\">\n            <span>\n                Aim for your target!\n            </span>\n            <button id=\"field-ctrl-lazer\">Turn into lazer</button>\n            <button id=\"field-ctrl-default\">Deafult</button>\n        </div>\n        <div>\n            <input id=\"field-variance\" type=\"range\" min=\"0\" max=\"100\" value=\"100\" >\n            <label for=\"field-variance\">Variance: 100</label>\n        </div>\n        <div>\n            <input id=\"field-gravity\" type=\"range\" min=\"0\" max=\"1000\" value=\"400\" >\n            <label for=\"field-gravity\">Gravity: 400</label>\n        </div>\n        <div>\n            <input id=\"field-init-vy\" type=\"range\" min=\"-200\" max=\"200\" value=\"-100\" >\n            <label for=\"field-init-vy\">Initial Velocity: -100</label>\n        </div>\n    </div>\n</div>\n<style>\n#field {\n  position: absolute;\n  z-index: 100000;\n  pointer-events: none;\n}\n\n.tomato {\n  width: 40px;\n  height: 40px;\n  position: absolute;\n  top: -20px;\n  left: -20px;\n  transform-origin: 50% 50%;\n}\n\n.tomato-inner {\n  width: 40px;\n  height: 40px;\n\n  animation: tomato-rotate .5s linear infinite;\n\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 40px;\n}\n\n@keyframes tomato-rotate {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n.tomato.splash svg {\n  transform-origin: 50% 50%;\n  transform: scale(3);\n}\n\n.field-ctrl {\n  position: fixed;\n  z-index: 100005;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  padding: 0 20px 20px 20px;\n  transition: transform .2s ease;\n}\n\n.field-ctrl-toggle {\n  margin-bottom: 20px;\n  padding: 0 20px;\n  height: 40px;\n  line-height: 40px;\n  max-width: 200px;\n  background: var(--color-bg);\n  box-shadow: rgba(0,0,0, .3) 0 4px 6px;\n  font-weight: bold;\n  cursor: pointer;\n  border-radius: 4px;\n}\n\n.field-ctrl-main {\n  padding: 10px 20px;\n  background: var(--color-bg);\n  box-shadow: rgba(0,0,0, .3) 0 4px 6px;\n  border-radius: 4px;\n\n  & > div {\n    display: flex;\n    align-items: center;\n\n    & > input {\n      flex: 1;\n    }\n\n    & > label {\n      margin-left: 10px;\n    }\n  }\n}\n\n\n.field-ctrl.tucked {\n  transform: translateY(calc(100% + 20px));\n}\n\n.field-ctrl.hidden {\n  transform: translateY(calc(100% - 50px));\n}\n\n.field-ctrl-info {\n  display: flex;\n  align-items: center;\n  & > span {\n    flex: 1;\n  }\n  & button {\n    margin-left: 10px;\n  }\n}\n</style>\n`;\n\nfunction setup() {\n  // Inject HTML\n  document.body.prepend(wrapper);\n\n  const toggle = document.getElementsByClassName('field-ctrl-toggle')[0];\n  toggle.addEventListener('click', function() {\n    const ctrl = document.getElementsByClassName('field-ctrl')[0];\n    ctrl.classList.toggle('hidden');\n  });\n\n  const defaultBtn = document.getElementById('field-ctrl-default');\n  defaultBtn.addEventListener('click', function() {\n    defaultSettings();\n  });\n\n  const lazer = document.getElementById('field-ctrl-lazer');\n  lazer.addEventListener('click', function() {\n    lazerSettings();\n  });\n\n  const variance = document.getElementById('field-variance');\n  variance.addEventListener('input', function() {\n    VARIANCE = parseInt(variance.value);\n    const varianceLabel = document.querySelector('label[for=\"field-variance\"]');\n    varianceLabel.innerText = `Variance: ${VARIANCE}`;\n    // window.localStorage.setItem('tomato-variance', VARIANCE);\n  });\n\n  const gravity = document.getElementById('field-gravity');\n  gravity.addEventListener('input', function() {\n    console.log('Update gravity: ', gravity.value);\n    GRAVITY = parseInt(gravity.value);\n    const gravityLabel = document.querySelector('label[for=\"field-gravity\"]');\n    gravityLabel.innerText = `Gravity: ${GRAVITY}`;\n    // window.localStorage.setItem('tomato-gravity', GRAVITY);\n  });\n\n  const init_vy = document.getElementById('field-init-vy');\n  init_vy.addEventListener('input', function() {\n    INIT_VY = parseInt(init_vy.value);\n    const initVyLabel = document.querySelector('label[for=\"field-init-vy\"]');\n    initVyLabel.innerText = `Initial Velocity: ${INIT_VY}`;\n    // window.localStorage.setItem('tomato-init-vy', INIT_VY);\n  });\n\n  // Recover stored settings\n  // setData('variance', parseInt(window.localStorage.getItem('tomato-variance') ?? 100));\n  // setData('gravity', parseInt(window.localStorage.getItem('tomato-gravity') ?? 400));\n  // setData('init-vy', parseInt(window.localStorage.getItem('tomato-init-vy') ?? -100));\n  // if(window.localStorage.getItem('tomato-hint') === 'true') {\n  //   const ctrl = document.getElementsByClassName('field-ctrl')[0];\n  //   ctrl.classList.remove('tucked');\n  //   ctrl.classList.add('hidden');\n  // }\n};\n\nif(document.readyState !== 'loading') setup();\nelse document.addEventListener('DOMContentLoaded', () => setup());\n\n"},{"metadata":{"id":"hurkens-pt1","lang":"zh-CN","title":"学习 Hurkens' Paradox (Pt.1)","tags":["胡说八道","TT"],"publish_time":"2025-03-22T00:20:00+08:00","update_time":"2025-03-22T03:40:52+08:00","title_outline":{"groups":[{"chars":[{"char":"学","components":[["M 138 -716C 148 -651 114 -593 78 -571C 42 -554 17 -522 30 -480C 45 -437 94 -423 134 -446C 191 -477 224 -578 150 -717Z",[0.203,0.455]],["M 38 -262L 46 -234L 944 -234C 959 -234 971 -239 974 -250C 923 -296 836 -363 836 -363L 760 -262Z",[0.924,0.038]],["M 160 -630L 160 -602L 860 -602L 860 -630Z",[-0.765,0.012]],["M 185 -844L 177 -839C 212 -792 245 -723 251 -659C 374 -564 497 -803 185 -844Z",[-0.143,0.332]],["M 207 -494L 216 -466L 668 -466L 668 -494Z",[-0.81,0.01]],["M 422 -366L 422 -79C 422 -66 417 -61 401 -61C 374 -61 216 -71 216 -71L 216 -59C 287 -46 313 -30 337 -8C 361 15 368 48 373 96C 550 81 576 27 576 -72L 576 -325C 597 -329 607 -336 609 -351Z",[0.13,0.508]],["M 415 -856L 407 -852C 429 -803 448 -738 447 -675C 562 -566 714 -788 415 -856Z",[-0.107,0.321]],["M 621 -494C 595 -451 544 -380 507 -337L 512 -331C 591 -355 707 -399 778 -432C 800 -434 810 -437 818 -446L 689 -569L 609 -494Z",[0.424,0.255]],["M 689 -856C 669 -787 632 -687 598 -620L 622 -620C 697 -664 776 -728 828 -773C 851 -770 863 -778 868 -789Z",[0.418,0.314]],["M 786 -630C 778 -591 761 -527 746 -486L 751 -481C 812 -501 895 -539 944 -569C 966 -570 976 -573 984 -583L 852 -707L 775 -630Z",[0.251,0.218]]],"bbox":{"top":-856,"bottom":96,"left":17,"right":984},"hadv":1000}],"text":"学","hadv":1000,"breakAfter":true},{"chars":[{"char":"习","components":[["M 85 -228L 181 -61C 194 -66 203 -76 209 -89C 522 -230 715 -337 834 -422L 831 -434C 525 -340 212 -257 85 -228Z",[0.751,0.286]],["M 796 -745L 101 -745L 110 -717L 796 -717Z",[0.648,0.026]],["M 169 -623L 164 -613C 269 -571 410 -482 492 -410C 660 -397 641 -698 169 -623Z",[-0.603,0.27]],["M 751 -745L 764 -745C 751 -346 730 -125 683 -84C 670 -74 658 -69 640 -69C 611 -69 542 -73 492 -77L 492 -66C 545 -54 582 -34 601 -10C 618 10 625 45 625 96C 705 96 755 78 800 33C 871 -36 895 -222 910 -689C 935 -693 950 -701 958 -711L 832 -827Z",[0.148,0.764]]],"bbox":{"top":-827,"bottom":96,"left":85,"right":958},"hadv":1000}],"text":"习","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"H","components":[["M 41 -0L 387 -0L 387 -34L 227 -50L 196 -50L 41 -34Z",[-0.865,0.0]],["M 41 -713L 196 -698L 227 -698L 387 -713L 387 -747L 41 -747Z",[-0.504,0.014]],["M 128 -0L 305 -0C 301 -117 301 -235 301 -365L 301 -395C 301 -514 301 -632 305 -747L 128 -747C 131 -630 131 -513 131 -395L 131 -351C 131 -232 131 -114 128 -0Z",[0.0,0.771]],["M 216 -361L 654 -361L 654 -399L 216 -399Z",[-0.931,0.006]],["M 482 -0L 829 -0L 829 -34L 671 -50L 641 -50L 482 -34Z",[-0.863,0.002]],["M 482 -713L 641 -698L 671 -698L 829 -713L 829 -747L 482 -747Z",[-0.608,0.05]],["M 565 -0L 742 -0C 739 -117 739 -235 739 -351L 739 -395C 739 -514 739 -632 742 -747L 565 -747C 569 -630 569 -513 569 -395L 569 -365C 569 -232 569 -114 565 -0Z",[-0.001,0.77]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":829},"hadv":870},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Hurkens","hadv":4549,"breakAfter":false},{"chars":[{"char":"'","components":[["M 127 -829C 78 -829 49 -801 49 -744C 49 -698 70 -628 79 -586L 111 -459L 144 -459L 177 -586C 185 -628 205 -696 205 -744C 205 -801 176 -829 127 -829Z",[-0.001,0.613]]],"bbox":{"top":-829,"bottom":-459,"left":49,"right":205},"hadv":255}],"text":"'","hadv":255,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617}],"text":"Paradox","hadv":4335,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"(","components":[["M 206 -315C 206 -504 242 -638 376 -803L 352 -825C 180 -684 86 -529 86 -315C 86 -101 180 53 352 195L 376 173C 249 12 206 -126 206 -315Z",[-0.002,0.755]]],"bbox":{"top":-825,"bottom":195,"left":86,"right":376},"hadv":418}],"text":"(","hadv":418,"breakAfter":false},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Pt","hadv":1096,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463}],"text":"1","hadv":463,"breakAfter":false},{"chars":[{"char":")","components":[["M 212 -315C 212 -126 176 8 42 173L 66 195C 238 54 332 -101 332 -315C 332 -529 238 -683 66 -825L 42 -803C 169 -642 212 -504 212 -315Z",[-0.001,0.755]]],"bbox":{"top":-825,"bottom":195,"left":42,"right":332},"hadv":418}],"text":")","hadv":418,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>前几天和群友一起学习了一下 Type-in-type 可能导致的问题。作为一个能够勉强背诵 ZFC 公理的工科🐖，感觉 Girard’s paradox 的构造十分神奇，遂做学习笔记，尝试在 Lean 上实现。事实上，接下来讨论的主要都是 Hurkens 的 Girard’s paradox 简化版本。 Girard’s paradox 是 Burali-Forti paradox 在类型论中的编码，本文先主要处理较为朴素的编码（Hurkens95 的第五节），后续如果我还能写的出来的话，会继续跟进这一个编码的简化，以及如何应用到 Type-in-type 的系统内，例如如果 Coq 或者 Lean 加入一些非直谓宇宙公理之后导出的矛盾。</p>\n<h2>Burali-Forti Paradox</h2>\n<p>Burali-Forti paradox 简单来说就是“全体序数不构成集合”：</p>\n<blockquote>\n<p>如果全体序数构成一个集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mi>r</mi><mi>d</mi><mo>=</mo><mo stretchy=\"false\">{</mo><mi>x</mi><mi mathvariant=\"normal\">∣</mi><mi>x</mi><mtext> well-ordered and transitive</mtext><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">Ord = \\{ x | x \\text{ well-ordered and transitive} \\}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">d</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord mathnormal\">x</span><span class=\"mord\">∣</span><span class=\"mord mathnormal\">x</span><span class=\"mord text\"><span class=\"mord\"> well-ordered and transitive</span></span><span class=\"mclose\">}</span></span></span></span>，那么可以检查 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mi>r</mi><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">Ord</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">d</span></span></span></span> 本身 WO &amp; transitive, s.t. <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mi>r</mi><mi>d</mi><mo>∈</mo><mi>O</mi><mi>r</mi><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">Ord \\in Ord</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7335em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">d</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">d</span></span></span></span>，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">{</mo><mi>O</mi><mi>r</mi><mi>d</mi><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">\\{ Ord \\}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">d</span><span class=\"mclose\">}</span></span></span></span> 是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mi>r</mi><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">Ord</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">d</span></span></span></span> 无最小元的子集，矛盾。</p>\n</blockquote>\n<p>如果把传统 von Neumann 序数直接翻译到 Lean 里，那么如果想不遍地用排中律，定义其实非常麻烦，有很多小细节需要考虑。尤其是“全序”，传统的定义方式是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>a</mi><mo>&lt;</mo><mi>b</mi><mo>∨</mo><mi>b</mi><mo>&lt;</mo><mi>a</mi><mo>∨</mo><mi>a</mi><mo>=</mo><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">a &lt; b \\lor b &lt; a \\lor a = b</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∨</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7335em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5556em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∨</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span></span></span></span>，不排中的话非常倒闭。</p>\n<h2>Hurkens’ paradoxical universe</h2>\n<p>Hurkens 用了一个比较聪明的方法刻画了序数的概念，或者说序数里我们比较关心的属性：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>-well-foundedness</p>\n<blockquote>\n<p><strong>定义</strong>: 如果存在一个集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> 满足 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∀</mi><mi>y</mi><mo separator=\"true\">,</mo><mo stretchy=\"false\">(</mo><mi mathvariant=\"normal\">∀</mi><mi>z</mi><mo>∈</mo><mi>y</mi><mo separator=\"true\">,</mo><mi>z</mi><mo>∈</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>→</mo><mi>z</mi><mo>∈</mo><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">\\forall y, (\\forall z \\in y, z \\in x) \\to z \\in x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∀</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord\">∀</span><span class=\"mord mathnormal\" style=\"margin-right:0.04398em;\">z</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7335em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.04398em;\">z</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.04398em;\">z</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span>，称 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> 为 Inductive set</p>\n</blockquote>\n<p>可以把 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> 理解为描述了一个 “<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>-超穷归纳可证的性质”。那么一个 Well-founded set 就是满足所有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>-归纳可证属性的集合。</p>\n<blockquote>\n<p><strong>定义</strong>: 如果存在一个集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> 满足 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∀</mi><mi>y</mi><mo separator=\"true\">,</mo><mo stretchy=\"false\">(</mo><mi>y</mi><mtext> inductive</mtext><mo stretchy=\"false\">)</mo><mo>→</mo><mi>x</mi><mo>∈</mo><mi>y</mi></mrow><annotation encoding=\"application/x-tex\">\\forall y, (y \\text{ inductive}) \\to x \\in y</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∀</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mord text\"><span class=\"mord\"> inductive</span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span></span></span></span>，称 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> 为 Well-founded set</p>\n</blockquote>\n<p>注意这里某个特定的 Inductive set <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> 里面可能有一些妙妙不 Well-founded 的元素：毕竟我们没有加入正则性公理对 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span> 关系加入限制。不过如果定义 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">Ω</mi><mo>=</mo><mo stretchy=\"false\">{</mo><mi>x</mi><mi mathvariant=\"normal\">∣</mi><mi>x</mi><mtext> well-founded</mtext><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">\\Omega = \\{ x | x \\text{ well-founded} \\}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord\">Ω</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord mathnormal\">x</span><span class=\"mord\">∣</span><span class=\"mord mathnormal\">x</span><span class=\"mord text\"><span class=\"mord\"> well-founded</span></span><span class=\"mclose\">}</span></span></span></span>，那么它一定是最小的 Inductive set。这个很像从无穷公理得到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ω</mi></mrow><annotation encoding=\"application/x-tex\">\\omega</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">ω</span></span></span></span> 集合的过程：Informally，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ω</mi></mrow><annotation encoding=\"application/x-tex\">\\omega</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">ω</span></span></span></span> 是所有验证无穷公理的集合的交 = 最小的验证无穷公理的集合 = 由 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>S</mi></mrow><annotation encoding=\"application/x-tex\">S</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">S</span></span></span></span> 自由生成出来的集合。</p>\n<p>Hurkens 随后在类型论中将以下两个常量解读为序数上的操作：如果有 Universe <code>U</code>，解读 <code>τ : (U -&gt; Prop) -&gt; Prop</code> 和 <code>σ : U -&gt; (U -&gt; Prop)</code>。</p>\n<ul>\n<li>对于前者，将 <code>T : U</code> 全部解读为序数，那么 <code>P : U -&gt; Prop</code> 可以被解读为一个序数 subclass。如果它变成了一个集合的话，我们可以考虑 <code>P</code> 上的 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>-序型 <super>[1]</super>，得到序型的过程是一个 <code>(U -&gt; Prop) -&gt; U</code> 的映射。</li>\n<li>对应地，后者解读为“前驱”，即 <code>σ x</code> 是所有小于 <code>x</code> 的序数构成的子集。</li>\n</ul>\n<p>根据这个解读，存在以下性质：</p>\n<div class=\"highlighted highlighted-lean\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-lean\"><span style=\"color:#859900;\">axiom </span><span style=\"color:#b58900;\">paradoxical </span><span style=\"color:#839496;\">: forall (p : U -&gt; </span><span style=\"color:#268bd2;\">Prop</span><span style=\"color:#839496;\">) (x : U), σ (τ p) x &lt;-&gt; exists y, p y ∧ τ (σ y) = x\n</span></code></pre>\n</div>\n<p>如果上述两个常量和性质存在，据此可以后续推出矛盾。</p>\n<h2>喵喵的解读</h2>\n<p>不过我个人其实没太看懂这个解读。这里有两个不太 Make sense 的地方：</p>\n<ul>\n<li>首先根据最终构造的矛盾，不是所有东西都是序数，否则其实只有一个 Inductive set。甚至因为不存在正则性，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span> 关系其实都不太 Well-founded，对任意集合谈论序型其实就比较怪。</li>\n<li>论文中提了一嘴，但是确实对于一个序数 <code>x</code>，有 <code>τ (σ x) = x</code>：因为在 von Neumann 序数的序型是自身，然后前驱关系就是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>。据此，上述 <code>paradoxical</code> 性质就变成了 <code>σ (τ p) = p</code>（考虑外延性）。这说明 <code>p</code> 不能只是任意序数子集，而只能也就是一个序数。</li>\n</ul>\n<p>所以感觉符合上述那个解读的模型估计论域里真的就只有序数。我个人的解读如下：</p>\n<ul>\n<li>Universe <code>U</code> 里面都是集合。</li>\n<li>把 σ 直接当成 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>。</li>\n<li>τ 其实说的是 Unrestricted comprehension，读作“把满足特定属性的集合收集成一个集合”。</li>\n</ul>\n<p>这种解读下恢复出来了上述 <code>σ (τ p) = p</code> 以及 <code>τ (σ x) = x</code> 的性质。In some sense，集合本身刻画的就是属于关系，所以 <code>U</code> 和 <code>U -&gt; Prop</code> 除了大小问题以外在集合论内确实就是同样的概念。在下面的构造中先使用 <code>σ (τ p) = p</code> 得到矛盾，后续文章中再放松至论文原先的条件。</p>\n<p>在这种解读下哪里出了问题就比较明显了：Unrestricted comprehension。对应地，在这种脱离了序数的解读下，Hurkens 的构造变得更像传统的 Burali-Forti paradox 的陈述。</p>\n<h2>构造</h2>\n<p>重点是考虑 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>P</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>x</mi><mo>∉</mo><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">P(x) = x \\not \\in x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">P</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\"><span class=\"mord vbox\"><span class=\"thinbox\"><span class=\"rlap\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"inner\"><span class=\"mord\"><span class=\"mrel\"></span></span></span><span class=\"fix\"></span></span></span></span></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span>，这一性质是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding=\"application/x-tex\">\\epsilon</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">ϵ</span></span></span></span>-归纳可证的，因此对所有具有正则性的集合都满足，特别是 Well-founded 的集合。然而如果通过 Unrestricted comprehension 收集所有 Well-founded 集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">Ω</mi></mrow><annotation encoding=\"application/x-tex\">\\Omega</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord\">Ω</span></span></span></span>，那么 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">Ω</mi></mrow><annotation encoding=\"application/x-tex\">\\Omega</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord\">Ω</span></span></span></span> 本身也 Well-founded，因此 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">Ω</mi><mo>∈</mo><mi mathvariant=\"normal\">Ω</mi></mrow><annotation encoding=\"application/x-tex\">\\Omega \\in \\Omega</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7224em;vertical-align:-0.0391em;\"></span><span class=\"mord\">Ω</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord\">Ω</span></span></span></span>，因此矛盾。</p>\n<div class=\"highlighted highlighted-lean\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-lean\"><span style=\"color:#859900;\">class </span><span style=\"color:#b58900;\">Paradoxical.</span><span style=\"color:#839496;\">{u} (U : </span><span style=\"color:#268bd2;\">Type</span><span style=\"color:#839496;\"> u) </span><span style=\"color:#859900;\">where\n</span><span style=\"color:#839496;\">  σ : U -&gt; (U -&gt; </span><span style=\"color:#268bd2;\">Prop</span><span style=\"color:#839496;\">)\n</span><span style=\"color:#839496;\">  τ : (U -&gt; </span><span style=\"color:#268bd2;\">Prop</span><span style=\"color:#839496;\">) -&gt; U\n</span><span style=\"color:#839496;\">  paradoxical {u} {pu : U -&gt; </span><span style=\"color:#268bd2;\">Prop</span><span style=\"color:#839496;\">} : (σ (τ pu)) u ↔ pu u\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">notation</span><span style=\"color:#839496;\"> a &quot;</span><span style=\"color:#2aa198;\">ε</span><span style=\"color:#839496;\">&quot; b =&gt; Paradoxical.σ b a\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">def </span><span style=\"color:#b58900;\">Paradoxical.bad </span><span style=\"color:#839496;\">{U} [Paradoxical U] : False := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">let</span><span style=\"color:#839496;\"> Inductive (x : U) := forall y, (forall z, (z ε y) -&gt; (z ε x)) -&gt; (y ε x)\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">let</span><span style=\"color:#839496;\"> WellFounded (x : U) := forall y, Inductive y -&gt; x ε y\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">let</span><span style=\"color:#839496;\"> Ω : U := Paradoxical.τ (</span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> x =&gt; WellFounded x)\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> Ω_wf : WellFounded Ω := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> {\n</span><span style=\"color:#839496;\">    intros x h\n</span><span style=\"color:#839496;\">    apply h\n</span><span style=\"color:#839496;\">    intros z hz\n</span><span style=\"color:#839496;\">    rw [Paradoxical.paradoxical] at hz\n</span><span style=\"color:#839496;\">    exact hz x h\n</span><span style=\"color:#839496;\">  }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> Ω_in_self: Ω ε Ω := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> {\n</span><span style=\"color:#839496;\">    rw [Paradoxical.paradoxical]\n</span><span style=\"color:#839496;\">    exact Ω_wf\n</span><span style=\"color:#839496;\">  }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">have lemma </span><span style=\"color:#839496;\">: Inductive (Paradoxical.τ (</span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> x =&gt; ¬ (x ε x))) := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> {\n</span><span style=\"color:#839496;\">    intros y h\n</span><span style=\"color:#839496;\">    rw [Paradoxical.paradoxical]\n</span><span style=\"color:#839496;\">    intros hyiny\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> h&#39; := h y hyiny\n</span><span style=\"color:#839496;\">    rw [Paradoxical.paradoxical] at h&#39;\n</span><span style=\"color:#839496;\">    exact h&#39; hyiny\n</span><span style=\"color:#839496;\">  }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> Ω_not_in_self : ¬ (Ω ε Ω) := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> h := Ω_wf _ </span><span style=\"color:#859900;\">lemma\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#b58900;\">rw </span><span style=\"color:#839496;\">[Paradoxical.paradoxical] at h\n</span><span style=\"color:#839496;\">    assumption\n</span><span style=\"color:#839496;\">  }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  exact Ω_not_in_self Ω_in_self\n</span><span style=\"color:#839496;\">}\n</span></code></pre>\n</div>\n<h2>那么在原先的解读下问题在哪里呢？</h2>\n<p>在原先的解读下，τ 的含义是序数 Subclass 到序型。这里最大的问题就是不是所有序数 Subclass 都能得到一个序数作为序型，典型例子就是 Ord class 本身。</p>\n<p>[1] 其实不是集合的话也可以，见 Mostowski collapse，结果如果是 proper class 那么一定是 Ord 本身。</p>\n","plain":"前几天和群友一起学习了一下 Type-in-type 可能导致的问题。作为一个能够勉强背诵 ZFC 公理的工科🐖，感觉 Girard’s paradox 的构造十分神奇，遂做学习笔记，尝试在 Lean 上实现。事实上，接下来讨论的主要都是 Hurkens 的 Girard’s paradox 简化版本。 Girard’s paradox 是 Burali-Forti paradox 在类型论中的编码，本文先主要处理较为朴素的编码（Hurkens95 的第五节），后续如果我还能写的出来的话，会继续跟进这一个编码的简化，以及如何应用到 Type-in-type 的系统内，例如如果 Coq 或者 Lean 加入一些非直谓宇宙公理之后导出的矛盾。\n\nBurali-Forti Paradox\nBurali-Forti paradox 简单来说就是“全体序数不构成集合”：\n如果全体序数构成一个集合 Ord = \\{ x | x \\text{ well-ordered and transitive} \\}，那么可以检查 Ord 本身 WO & transitive, s.t. Ord \\in Ord，那么 \\{ Ord \\} 是 Ord 无最小元的子集，矛盾。\n\n如果把传统 von Neumann 序数直接翻译到 Lean 里，那么如果想不遍地用排中律，定义其实非常麻烦，有很多小细节需要考虑。尤其是“全序”，传统的定义方式是 a < b \\lor b < a \\lor a = b，不排中的话非常倒闭。\n\nHurkens’ paradoxical universe\nHurkens 用了一个比较聪明的方法刻画了序数的概念，或者说序数里我们比较关心的属性：\\epsilon-well-foundedness\n定义: 如果存在一个集合 x 满足 \\forall y, (\\forall z \\in y, z \\in x) \\to z \\in x，称 x 为 Inductive set\n\n可以把 x 理解为描述了一个 “\\epsilon-超穷归纳可证的性质”。那么一个 Well-founded set 就是满足所有 \\epsilon-归纳可证属性的集合。\n定义: 如果存在一个集合 x 满足 \\forall y, (y \\text{ inductive}) \\to x \\in y，称 x 为 Well-founded set\n\n注意这里某个特定的 Inductive set x 里面可能有一些妙妙不 Well-founded 的元素：毕竟我们没有加入正则性公理对 \\epsilon 关系加入限制。不过如果定义 \\Omega = \\{ x | x \\text{ well-founded} \\}，那么它一定是最小的 Inductive set。这个很像从无穷公理得到 \\omega 集合的过程：Informally，\\omega 是所有验证无穷公理的集合的交 = 最小的验证无穷公理的集合 = 由 0 和 S 自由生成出来的集合。\nHurkens 随后在类型论中将以下两个常量解读为序数上的操作：如果有 Universe U，解读 τ : (U -> Prop) -> Prop 和 σ : U -> (U -> Prop)。\n- 对于前者，将 T : U 全部解读为序数，那么 P : U -> Prop 可以被解读为一个序数 subclass。如果它变成了一个集合的话，我们可以考虑 P 上的 \\epsilon-序型 [1]，得到序型的过程是一个 (U -> Prop) -> U 的映射。\n- 对应地，后者解读为“前驱”，即 σ x 是所有小于 x 的序数构成的子集。\n根据这个解读，存在以下性质：\naxiom paradoxical : forall (p : U -> Prop) (x : U), σ (τ p) x <-> exists y, p y ∧ τ (σ y) = x\n\n如果上述两个常量和性质存在，据此可以后续推出矛盾。\n\n喵喵的解读\n不过我个人其实没太看懂这个解读。这里有两个不太 Make sense 的地方：\n- 首先根据最终构造的矛盾，不是所有东西都是序数，否则其实只有一个 Inductive set。甚至因为不存在正则性，\\epsilon 关系其实都不太 Well-founded，对任意集合谈论序型其实就比较怪。\n- 论文中提了一嘴，但是确实对于一个序数 x，有 τ (σ x) = x：因为在 von Neumann 序数的序型是自身，然后前驱关系就是 \\epsilon。据此，上述 paradoxical 性质就变成了 σ (τ p) = p（考虑外延性）。这说明 p 不能只是任意序数子集，而只能也就是一个序数。\n所以感觉符合上述那个解读的模型估计论域里真的就只有序数。我个人的解读如下：\n- Universe U 里面都是集合。\n- 把 σ 直接当成 \\epsilon。\n- τ 其实说的是 Unrestricted comprehension，读作“把满足特定属性的集合收集成一个集合”。\n这种解读下恢复出来了上述 σ (τ p) = p 以及 τ (σ x) = x 的性质。In some sense，集合本身刻画的就是属于关系，所以 U 和 U -> Prop 除了大小问题以外在集合论内确实就是同样的概念。在下面的构造中先使用 σ (τ p) = p 得到矛盾，后续文章中再放松至论文原先的条件。\n在这种解读下哪里出了问题就比较明显了：Unrestricted comprehension。对应地，在这种脱离了序数的解读下，Hurkens 的构造变得更像传统的 Burali-Forti paradox 的陈述。\n\n构造\n重点是考虑 P(x) = x \\not \\in x，这一性质是 \\epsilon-归纳可证的，因此对所有具有正则性的集合都满足，特别是 Well-founded 的集合。然而如果通过 Unrestricted comprehension 收集所有 Well-founded 集合 \\Omega，那么 \\Omega 本身也 Well-founded，因此 \\Omega \\in \\Omega，因此矛盾。\nclass Paradoxical.{u} (U : Type u) where\n  σ : U -> (U -> Prop)\n  τ : (U -> Prop) -> U\n  paradoxical {u} {pu : U -> Prop} : (σ (τ pu)) u ↔ pu u\n\nnotation a \"ε\" b => Paradoxical.σ b a\n\ndef Paradoxical.bad {U} [Paradoxical U] : False := by {\n  let Inductive (x : U) := forall y, (forall z, (z ε y) -> (z ε x)) -> (y ε x)\n  let WellFounded (x : U) := forall y, Inductive y -> x ε y\n  let Ω : U := Paradoxical.τ (fun x => WellFounded x)\n\n  have Ω_wf : WellFounded Ω := by {\n    intros x h\n    apply h\n    intros z hz\n    rw [Paradoxical.paradoxical] at hz\n    exact hz x h\n  }\n\n  have Ω_in_self: Ω ε Ω := by {\n    rw [Paradoxical.paradoxical]\n    exact Ω_wf\n  }\n\n  have lemma : Inductive (Paradoxical.τ (fun x => ¬ (x ε x))) := by {\n    intros y h\n    rw [Paradoxical.paradoxical]\n    intros hyiny\n    have h' := h y hyiny\n    rw [Paradoxical.paradoxical] at h'\n    exact h' hyiny\n  }\n\n  have Ω_not_in_self : ¬ (Ω ε Ω) := by {\n    have h := Ω_wf _ lemma\n    rw [Paradoxical.paradoxical] at h\n    assumption\n  }\n\n  exact Ω_not_in_self Ω_in_self\n}\n\n\n那么在原先的解读下问题在哪里呢？\n在原先的解读下，τ 的含义是序数 Subclass 到序型。这里最大的问题就是不是所有序数 Subclass 都能得到一个序数作为序型，典型例子就是 Ord class 本身。\n[1] 其实不是集合的话也可以，见 Mostowski collapse，结果如果是 proper class 那么一定是 Ord 本身。\n"},{"metadata":{"id":"sticker-outline","lang":"zh-CN","title":"Adobe Illustrator 添加白边","tags":["TUNA"],"publish_time":"2025-03-19T23:00:38+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"Adobe","hadv":3346,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Illustrator","hadv":5460,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"添","components":[["M 28 -622L 20 -617C 49 -577 76 -517 79 -461C 190 -374 309 -587 28 -622Z",[-0.182,0.311]],["M 79 -229C 68 -229 34 -229 34 -229L 34 -211C 55 -209 72 -204 87 -194C 110 -178 114 -76 93 29C 103 69 133 82 158 82C 213 82 253 45 255 -9C 258 -101 211 -132 208 -191C 208 -217 214 -254 221 -287C 232 -342 285 -553 317 -667L 302 -671C 134 -287 134 -287 111 -249C 99 -229 95 -229 79 -229Z",[0.113,0.761]],["M 99 -841L 92 -836C 124 -795 162 -733 175 -676C 297 -598 399 -826 99 -841Z",[-0.22,0.284]],["M 512 -763C 496 -574 414 -395 228 -275L 233 -265C 504 -355 635 -537 677 -763Z",[0.409,0.635]],["M 421 -308C 407 -225 353 -181 300 -162C 190 -30 526 28 434 -307Z",[0.296,0.42]],["M 302 -572L 310 -544L 945 -544C 960 -544 971 -549 974 -560C 927 -604 847 -670 847 -670L 777 -572Z",[0.853,0.066]],["M 338 -763L 346 -735L 879 -735C 893 -735 904 -740 907 -751C 863 -793 786 -856 786 -856L 719 -763Z",[0.793,0.044]],["M 504 -413L 504 -62C 504 -52 500 -47 486 -47C 467 -47 372 -53 372 -53L 372 -40C 420 -31 439 -17 453 2C 468 22 472 52 475 94C 615 82 634 34 634 -55L 634 -373C 656 -376 666 -384 668 -399Z",[0.082,0.667]],["M 663 -282L 652 -278C 676 -219 695 -138 689 -68C 780 27 900 -165 663 -282Z",[-0.148,0.454]],["M 676 -572L 667 -567C 709 -431 774 -337 888 -278C 903 -347 939 -391 988 -405L 990 -417C 869 -436 736 -491 676 -572Z",[-0.425,0.29]],["M 769 -309L 759 -303C 810 -242 856 -149 862 -69C 972 22 1074 -215 769 -309Z",[-0.246,0.383]]],"bbox":{"top":-856,"bottom":94,"left":20,"right":1074},"hadv":1000}],"text":"添","hadv":1000,"breakAfter":true},{"chars":[{"char":"加","components":[["M 155 -845C 155 -523 172 -198 10 83L 23 96C 303 -140 293 -480 298 -801C 323 -805 332 -814 335 -829Z",[0.13,0.822]],["M 36 -631L 45 -603L 411 -603L 411 -631Z",[-0.718,0.012]],["M 363 -631C 357 -268 348 -116 314 -85C 305 -77 296 -73 281 -73C 261 -73 218 -75 191 -78L 190 -66C 229 -55 250 -41 265 -19C 277 -1 280 31 280 79C 339 79 386 63 423 27C 482 -30 493 -147 501 -578C 524 -582 537 -589 545 -599L 425 -705L 351 -631Z",[0.109,0.768]],["M 556 -685L 556 76L 579 76C 641 76 696 43 696 26L 696 -657L 861 -657L 861 -685L 700 -685L 556 -744Z",[0.034,0.779]],["M 620 -82L 620 -54L 856 -54L 856 -82Z",[0.881,0.002]],["M 785 -685L 785 55L 809 55C 864 55 930 17 932 5L 932 -634C 952 -639 964 -647 971 -656L 842 -759L 775 -685Z",[0.008,0.787]]],"bbox":{"top":-845,"bottom":96,"left":10,"right":971},"hadv":1000}],"text":"加","hadv":1000,"breakAfter":true},{"chars":[{"char":"白","components":[["M 125 -639L 125 90L 150 90C 216 90 280 53 280 35L 280 -611L 800 -611L 800 -639L 291 -639L 125 -703Z",[0.137,0.505]],["M 192 -37L 192 -9L 806 -9L 806 -37Z",[-0.954,0.0]],["M 192 -341L 192 -313L 806 -313L 806 -341Z",[-0.907,0.005]],["M 404 -861C 399 -796 386 -698 373 -633L 401 -633C 466 -681 529 -747 574 -791C 597 -791 608 -799 612 -812Z",[0.332,0.247]],["M 722 -639L 722 84L 747 84C 806 84 877 45 878 33L 878 -582C 903 -587 916 -598 924 -607L 783 -720L 710 -639Z",[0.017,0.758]]],"bbox":{"top":-861,"bottom":90,"left":125,"right":924},"hadv":1000}],"text":"白","hadv":1000,"breakAfter":true},{"chars":[{"char":"边","components":[["M 249 -161C 223 -161 97 -94 13 -59L 107 97C 117 92 123 83 121 72C 159 9 216 -70 236 -104C 250 -124 262 -127 275 -104C 350 20 430 78 638 78C 711 78 830 78 882 78C 888 16 921 -39 977 -53L 977 -64C 875 -57 788 -56 686 -56C 468 -55 362 -77 290 -145C 277 -157 270 -161 249 -161Z",[-0.815,0.071]],["M 296 -137L 296 -448C 325 -453 340 -461 349 -471L 209 -583L 142 -495L 26 -495L 32 -466L 159 -466L 159 -102Z",[-0.031,0.591]],["M 99 -832L 91 -827C 134 -768 178 -685 194 -608C 329 -511 444 -773 99 -832Z",[-0.258,0.379]],["M 686 -836L 511 -853L 511 -731C 511 -538 503 -282 321 -112L 329 -104C 617 -233 649 -520 651 -730L 651 -809C 677 -813 684 -823 686 -836Z",[0.184,0.766]],["M 809 -625L 343 -625L 352 -597L 809 -597Z",[0.685,0.029]],["M 766 -625L 777 -625C 771 -399 761 -284 735 -262C 728 -255 719 -252 704 -252C 684 -252 626 -255 589 -258L 588 -247C 632 -237 661 -221 678 -200C 694 -180 698 -148 698 -104C 764 -104 806 -117 841 -146C 896 -190 911 -294 919 -572C 941 -576 953 -583 961 -592L 839 -695Z",[0.158,0.649]]],"bbox":{"top":-853,"bottom":97,"left":13,"right":977},"hadv":1000}],"text":"边","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>最近给 TUNA 画了新的贴纸和 TUNAive。</p>\n<p><img src=\"https://github.com/tuna/artwork/blob/master/clothing/TUNA-tunaive-2025-art-light.png?raw=true\" alt=\"TUNAive 正面图案.jpg\" /></p>\n<p>经常会遇到的一个操作是需要给贴纸添加一个白边。TUNA 贴纸使用的操作如下：</p>\n<blockquote>\n<ul>\n<li>选中对象，复制一份，打开 Path finder，Union</li>\n<li>删除掉所有 Clip group 内部的背景</li>\n<li>Object -&gt; Path -&gt; Offset Path\n<ul>\n<li>我们选择的是圆角，所以这里选 Round joint</li>\n</ul>\n</li>\n<li>把可能出现的洞填起来，再 Union 一次。删除掉 Offset Path 之前的路径。</li>\n<li>填充白色，放置在最底层</li>\n</ul>\n</blockquote>\n<p>对于常见的矢量图，以上操作是够用的。</p>\n<h2>文字</h2>\n<p>对于文字，需要在一开始额外进行一个操作，将文字转换为路径：</p>\n<blockquote>\n<p>右键选中文字，Create outlines</p>\n</blockquote>\n<h2>Stroke</h2>\n<p>这次画的贴纸第一次部分直接使用 Stroke 作为展示元素，例如本文最开始图片中的网线。直接使用 Path finder 进行 Union 是不工作的，因为这个路径不是使用其内部填充进行绘制的。</p>\n<p>因此也需要在一开始将路径的 Stroke 填充本身转换为一个轮廓路径。</p>\n<blockquote>\n<p>选中路径，Object -&gt; Path -&gt; Outline Stroke</p>\n</blockquote>\n<h2>位图</h2>\n<p>本次准备印制的贴纸也是第一次使用了来源第三方的位图。位图同样因为缺乏轮廓路径所以无法通过 Offset Path 直接得到想要的结果。</p>\n<p>为了获得一个有透明度的图片的不透明部分轮廓路径，可以采用以下方式：</p>\n<blockquote>\n<ul>\n<li>将这一位图复制一份</li>\n<li>Effect -&gt; Path -&gt; Outline Object。Effect 的执行结果是一个边缘路径，但是这个路径暂时没办法被直接操作。</li>\n<li>Object -&gt; Expand Appearance，这时会得到可以直接操作的路径，但是这个路径现在被套在很多层 Group / Clip group 背后。\n<ul>\n<li>在实践中，很多时候 Trace 出来的边界有锯齿，需要进行一次 Object -&gt; Path -&gt; Smooth。选大约 3-5% 即可。</li>\n</ul>\n</li>\n<li>如果愿意一层一层把所有的 Group 打开，可以根据矢量路径的方法继续操作。我因为比较懒，直接设置了个白色的 Stroke color，宽度是白边宽度 x2，然后丢到最底层了，其实也能达成这个效果。</li>\n</ul>\n</blockquote>\n","plain":"最近给 TUNA 画了新的贴纸和 TUNAive。\nTUNAive 正面图案.jpg\n经常会遇到的一个操作是需要给贴纸添加一个白边。TUNA 贴纸使用的操作如下：\n- 选中对象，复制一份，打开 Path finder，Union\n- 删除掉所有 Clip group 内部的背景\n- Object -> Path -> Offset Path- 我们选择的是圆角，所以这里选 Round joint\n\n- 把可能出现的洞填起来，再 Union 一次。删除掉 Offset Path 之前的路径。\n- 填充白色，放置在最底层\n\n对于常见的矢量图，以上操作是够用的。\n\n文字\n对于文字，需要在一开始额外进行一个操作，将文字转换为路径：\n右键选中文字，Create outlines\n\n\nStroke\n这次画的贴纸第一次部分直接使用 Stroke 作为展示元素，例如本文最开始图片中的网线。直接使用 Path finder 进行 Union 是不工作的，因为这个路径不是使用其内部填充进行绘制的。\n因此也需要在一开始将路径的 Stroke 填充本身转换为一个轮廓路径。\n选中路径，Object -> Path -> Outline Stroke\n\n\n位图\n本次准备印制的贴纸也是第一次使用了来源第三方的位图。位图同样因为缺乏轮廓路径所以无法通过 Offset Path 直接得到想要的结果。\n为了获得一个有透明度的图片的不透明部分轮廓路径，可以采用以下方式：\n- 将这一位图复制一份\n- Effect -> Path -> Outline Object。Effect 的执行结果是一个边缘路径，但是这个路径暂时没办法被直接操作。\n- Object -> Expand Appearance，这时会得到可以直接操作的路径，但是这个路径现在被套在很多层 Group / Clip group 背后。- 在实践中，很多时候 Trace 出来的边界有锯齿，需要进行一次 Object -> Path -> Smooth。选大约 3-5% 即可。\n\n- 如果愿意一层一层把所有的 Group 打开，可以根据矢量路径的方法继续操作。我因为比较懒，直接设置了个白色的 Stroke color，宽度是白边宽度 x2，然后丢到最底层了，其实也能达成这个效果。\n\n"},{"metadata":{"id":"jsx-dom","lang":"zh-CN","title":"使用 JSX 直接创建 DOM 元素","tags":["meta","开发"],"publish_time":"2025-03-18T04:29:23+08:00","update_time":null,"title_outline":{"groups":[{"chars":[{"char":"使","components":[["M 198 -856C 163 -661 84 -460 5 -332L 16 -325C 159 -426 270 -572 349 -778C 372 -777 385 -786 390 -799Z",[0.328,0.655]],["M 127 -524L 127 95L 153 95C 208 95 265 65 266 55L 266 -528C 286 -532 294 -538 298 -548L 178 -592Z",[0.011,0.79]],["M 559 -852L 559 -326C 559 -123 471 -1 261 85L 266 95C 578 38 698 -94 701 -326L 701 -807C 727 -811 735 -821 737 -835Z",[0.134,0.765]],["M 324 -697L 332 -669L 948 -669C 962 -669 974 -674 977 -685C 925 -731 838 -798 838 -798L 761 -697Z",[0.901,0.068]],["M 335 -568L 335 -256L 354 -256C 411 -256 472 -285 472 -297L 472 -540L 799 -540L 799 -568L 478 -568L 335 -623Z",[0.248,0.231]],["M 431 -259L 421 -254C 490 -42 627 51 880 92C 890 19 935 -34 990 -52L 991 -64C 751 -61 519 -115 431 -259Z",[-0.643,0.24]],["M 437 -348L 437 -320L 821 -320L 821 -348Z",[-0.929,0.009]],["M 787 -568L 787 -269L 811 -269C 858 -269 927 -296 927 -304L 927 -517C 948 -522 961 -531 967 -539L 839 -636L 777 -568Z",[0.001,0.585]]],"bbox":{"top":-856,"bottom":95,"left":5,"right":991},"hadv":1000}],"text":"使","hadv":1000,"breakAfter":true},{"chars":[{"char":"用","components":[["M 136 -773L 136 -461C 136 -273 129 -77 25 76L 34 83C 266 -58 278 -276 278 -462L 278 -773L 299 -773L 136 -828L 136 -783Z",[0.078,0.811]],["M 217 -540L 217 -512L 792 -512L 792 -540Z",[-0.834,0.008]],["M 217 -773L 217 -745L 792 -745L 792 -773Z",[-0.626,0.018]],["M 217 -297L 217 -269L 792 -269L 792 -297Z",[-0.951,0.003]],["M 427 -763L 427 80L 453 80C 527 80 569 51 569 42L 569 -763Z",[0.004,0.824]],["M 740 -773L 740 -90C 740 -78 736 -70 720 -70C 700 -70 607 -76 607 -76L 607 -63C 657 -54 675 -39 690 -18C 704 2 709 35 712 80C 864 67 885 17 885 -76L 885 -719C 908 -724 921 -734 929 -743L 795 -849L 729 -773Z",[0.041,0.817]]],"bbox":{"top":-849,"bottom":83,"left":25,"right":929},"hadv":1000}],"text":"用","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"J","components":[["M 74 162C 131 162 194 140 248 75C 295 18 317 -49 317 -201L 317 -404C 317 -520 317 -636 321 -747L 151 -747C 154 -423 155 -298 155 -208C 155 -60 159 43 142 134L 142 142L 157 142L 157 136L 111 79C 76 40 58 33 23 33C -14 33 -42 49 -51 93C -44 142 -1 162 74 162Z",[0.111,0.745]],["M 43 -713L 204 -698L 246 -698L 409 -713L 409 -747L 43 -747Z",[-0.888,0.008]]],"bbox":{"top":-747,"bottom":162,"left":-51,"right":409},"hadv":442},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"X","components":[["M 10 -0L 253 -0L 253 -34L 147 -50L 121 -50L 10 -34Z",[0.806,0.001]],["M 19 -713L 167 -698L 220 -698L 368 -713L 368 -747L 19 -747Z",[-0.791,0.001]],["M 493 -0L 680 -0L 246 -747L 59 -747Z",[-0.426,0.698]],["M 67 -0L 127 -0L 340 -347L 360 -382L 366 -382L 337 -401Z",[0.49,0.755]],["M 370 -0L 727 -0L 727 -34L 579 -50L 530 -50L 370 -34Z",[0.867,0.001]],["M 402 -395L 634 -747L 579 -747L 395 -444L 376 -410L 370 -410Z",[0.484,0.763]],["M 457 -713L 559 -699L 586 -699L 695 -713L 695 -747L 457 -747Z",[-0.19,0.031]]],"bbox":{"top":-747,"bottom":0,"left":10,"right":727},"hadv":739}],"text":"JSX","hadv":1793,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"直","components":[["M 855 -67L 787 21L 37 21L 45 49L 948 49C 963 49 974 44 976 33C 931 -8 855 -67 855 -67Z",[0.929,0.033]],["M 821 -781L 749 -695L 55 -695L 63 -667L 923 -667C 938 -667 949 -672 952 -683C 902 -723 821 -781 821 -781Z",[0.83,0.039]],["M 192 -616L 192 39L 337 39L 337 -531L 650 -531L 650 39L 802 39L 802 -517C 828 -522 840 -528 847 -538L 702 -637L 641 -559L 345 -559ZM 723 -129L 272 -129L 272 -101L 723 -101ZM 724 -274L 273 -274L 273 -246L 724 -246ZM 724 -419L 273 -419L 273 -391L 724 -391Z",[0.177,0.011]],["M 607 -834L 407 -857C 404 -758 398 -622 392 -545L 485 -545C 508 -611 545 -729 566 -803C 590 -806 604 -816 607 -834Z",[0.133,0.535]]],"bbox":{"top":-857,"bottom":49,"left":37,"right":976},"hadv":1000}],"text":"直","hadv":1000,"breakAfter":true},{"chars":[{"char":"接","components":[["M 301 -839L 129 -855L 129 -85C 129 -75 125 -70 110 -70C 90 -70 4 -75 4 -75L 4 -61C 49 -52 68 -37 82 -13C 95 10 100 44 103 93C 246 79 264 25 264 -72L 264 -811C 289 -814 299 -824 301 -839Z",[0.033,0.836]],["M 15 -378L 72 -224C 85 -229 95 -241 99 -255C 234 -351 329 -432 386 -484L 384 -493C 234 -442 75 -393 15 -378Z",[0.577,0.324]],["M 310 -703L 256 -615L 20 -615L 28 -587L 377 -587C 391 -587 401 -592 403 -603C 371 -642 310 -703 310 -703Z",[0.763,0.089]],["M 863 -289L 863 -305L 713 -305C 669 -103 554 5 292 83L 298 96C 674 47 793 -62 863 -289Z",[0.559,0.494]],["M 858 -406L 789 -316L 314 -316L 322 -288L 955 -288C 969 -288 981 -293 983 -304C 936 -345 858 -406 858 -406Z",[0.868,0.057]],["M 838 -556L 771 -472L 367 -472L 375 -444L 931 -444C 946 -444 956 -449 959 -460C 914 -500 838 -556 838 -556Z",[0.866,0.057]],["M 406 -150L 380 -135C 567 -78 709 7 781 73C 916 148 1145 -102 406 -150Z",[-0.698,0.274]],["M 380 -135L 517 -124C 561 -200 620 -332 647 -394L 620 -378C 670 -375 680 -387 684 -401L 511 -440C 492 -374 422 -208 380 -135Z",[0.284,0.514]],["M 826 -795L 761 -709L 380 -709L 388 -681L 916 -681C 931 -681 941 -686 944 -697C 900 -737 826 -795 826 -795Z",[0.688,0.083]],["M 462 -674L 453 -670C 472 -626 491 -565 491 -508C 589 -415 721 -604 462 -674Z",[-0.081,0.355]],["M 548 -853L 542 -848C 564 -820 584 -772 583 -728C 699 -637 834 -853 548 -853Z",[0.083,0.296]],["M 889 -638L 722 -679C 712 -615 691 -522 669 -460L 681 -460C 744 -506 812 -570 852 -617C 874 -617 886 -625 889 -638Z",[0.412,0.493]]],"bbox":{"top":-855,"bottom":148,"left":4,"right":1145},"hadv":1000}],"text":"接","hadv":1000,"breakAfter":true},{"chars":[{"char":"创","components":[["M 409 -790L 236 -862C 204 -724 124 -529 9 -403L 17 -394C 188 -486 303 -642 371 -773C 396 -771 405 -779 409 -790Z",[0.392,0.613]],["M 131 -549L 131 -70C 131 21 160 44 272 44L 371 44C 541 44 593 22 593 -33C 593 -57 583 -71 547 -87L 544 -215L 534 -215C 513 -156 494 -109 482 -91C 474 -81 465 -79 452 -78C 439 -77 413 -77 386 -77L 302 -77C 272 -77 265 -82 265 -100L 265 -526L 279 -526L 156 -572Z",[-0.239,0.43]],["M 445 -526L 228 -526L 228 -498L 445 -498Z",[-0.629,0.035]],["M 378 -526L 388 -526C 388 -367 389 -306 377 -294C 373 -289 368 -287 355 -287C 341 -287 307 -288 288 -290L 288 -278C 317 -270 333 -259 345 -243C 357 -226 359 -202 359 -166C 413 -166 446 -173 474 -194C 514 -225 518 -278 518 -477C 537 -481 548 -487 555 -495L 443 -587Z",[0.1,0.603]],["M 333 -778L 326 -772C 379 -717 434 -633 455 -555C 593 -468 693 -739 333 -778Z",[-0.272,0.345]],["M 765 -725L 604 -740L 604 -140L 628 -140C 676 -140 733 -165 733 -175L 733 -700C 757 -704 764 -713 765 -725Z",[0.015,0.772]],["M 968 -837L 796 -853L 796 -67C 796 -55 791 -49 774 -49C 750 -49 636 -56 636 -56L 636 -43C 692 -33 714 -18 732 3C 750 24 755 55 759 99C 910 85 931 35 931 -57L 931 -808C 956 -812 966 -822 968 -837Z",[0.033,0.854]]],"bbox":{"top":-862,"bottom":99,"left":9,"right":968},"hadv":1000}],"text":"创","hadv":1000,"breakAfter":true},{"chars":[{"char":"建","components":[["M 231 -447L 242 -447C 229 -240 183 -39 19 84L 26 95C 268 -8 343 -196 372 -400C 394 -403 403 -407 409 -418L 294 -514Z",[0.286,0.711]],["M 269 -747L 28 -747L 37 -719L 269 -719Z",[-0.938,0.008]],["M 332 -704L 206 -747C 184 -679 114 -518 73 -447L 114 -480C 92 -475 65 -460 50 -447L 168 -377L 207 -419L 201 -419C 236 -489 305 -641 332 -704Z",[0.275,0.575]],["M 71 -376L 62 -372C 152 -5 335 64 736 64C 772 64 854 64 890 64C 893 8 919 -44 973 -56L 973 -67C 912 -66 795 -66 746 -66C 362 -66 173 -107 71 -376Z",[-0.754,0.173]],["M 302 -447L 136 -447L 122 -419L 302 -419Z",[-0.982,0.0]],["M 193 -747L 206 -747L 219 -690C 274 -681 342 -680 362 -702L 250 -804Z",[-0.559,0.207]],["M 902 -701L 851 -614L 316 -614L 324 -586L 964 -586C 978 -586 988 -591 991 -602C 961 -640 902 -701 902 -701Z",[0.818,0.054]],["M 818 -314L 747 -223L 333 -223L 341 -195L 920 -195C 934 -195 946 -200 949 -211C 900 -253 818 -314 818 -314Z",[0.857,0.062]],["M 777 -741L 369 -741L 378 -713L 777 -713Z",[-0.832,0.02]],["M 796 -440L 733 -355L 375 -355L 383 -327L 883 -327C 898 -327 908 -332 911 -343C 869 -382 796 -440 796 -440Z",[0.853,0.063]],["M 773 -485L 384 -485L 393 -457L 773 -457Z",[-0.829,0.008]],["M 697 -838L 523 -854L 523 -75L 550 -75C 603 -75 660 -99 660 -109L 660 -809C 688 -813 695 -823 697 -838Z",[0.009,0.815]],["M 709 -741L 719 -741L 719 -421L 741 -421C 784 -421 849 -443 850 -451L 850 -693C 869 -697 882 -706 888 -713L 767 -804Z",[0.055,0.578]]],"bbox":{"top":-854,"bottom":95,"left":19,"right":991},"hadv":1000}],"text":"建","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014}],"text":"DOM","hadv":2608,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"元","components":[["M 278 -487C 278 -257 238 -54 18 86L 22 95C 350 -0 429 -217 443 -487Z",[0.305,0.661]],["M 33 -501L 41 -473L 941 -473C 956 -473 968 -478 971 -489C 918 -535 829 -603 829 -603L 751 -501Z",[0.949,0.042]],["M 135 -753L 143 -725L 859 -725C 874 -725 885 -730 888 -741C 837 -785 751 -849 751 -849L 675 -753Z",[0.844,0.033]],["M 547 -487L 547 -58C 547 40 574 65 687 65L 775 65C 939 65 987 36 987 -22C 987 -51 979 -68 942 -84L 939 -244L 929 -244C 905 -172 885 -115 871 -93C 864 -80 858 -77 845 -77C 832 -76 813 -76 793 -76L 725 -76C 701 -76 695 -81 695 -97L 695 -448C 695 -458 695 -475 695 -487Z",[-0.223,0.376]]],"bbox":{"top":-849,"bottom":95,"left":18,"right":987},"hadv":1000}],"text":"元","hadv":1000,"breakAfter":true},{"chars":[{"char":"素","components":[["M 397 -64L 256 -155C 212 -85 117 6 20 61L 27 72C 156 51 281 2 359 -54C 382 -50 391 -55 397 -64Z",[0.578,0.32]],["M 847 -612L 780 -523L 34 -523L 42 -495L 942 -495C 956 -495 967 -500 970 -511C 924 -552 847 -612 847 -612Z",[0.958,0.031]],["M 796 -838L 728 -757L 85 -757L 93 -729L 893 -729C 908 -729 919 -734 922 -745C 873 -784 796 -838 796 -838Z",[0.812,0.039]],["M 797 -382L 650 -471C 563 -402 318 -283 149 -253C 132 -249 102 -246 102 -246L 155 -118C 179 -128 200 -160 206 -230L 161 -230L 161 -221C 368 -250 649 -322 767 -379L 732 -376C 768 -361 790 -370 797 -382Z",[0.798,0.293]],["M 774 -715L 709 -640L 127 -640L 135 -612L 864 -612C 879 -612 890 -617 892 -628C 847 -665 774 -715 774 -715Z",[0.861,0.04]],["M 565 -436L 447 -524C 399 -486 268 -412 170 -395C 158 -392 142 -389 142 -389L 184 -292C 201 -300 219 -321 223 -375L 184 -375L 184 -365C 309 -376 471 -411 541 -438L 507 -438C 538 -420 558 -426 565 -436Z",[0.697,0.254]],["M 143 -238L 171 -141C 444 -173 666 -204 806 -228L 806 -245C 524 -239 256 -235 143 -238Z",[0.881,0.059]],["M 162 -389L 189 -303C 361 -329 511 -358 598 -375L 598 -392C 415 -388 238 -387 162 -389Z",[0.906,0.068]],["M 567 -44L 567 -211L 425 -211L 425 -46C 425 -37 421 -31 408 -31C 389 -31 310 -36 310 -36L 310 -24C 356 -16 372 -1 384 16C 397 34 400 63 402 103C 547 92 567 43 567 -44Z",[0.106,0.421]],["M 603 -841L 424 -855L 424 -508L 567 -508L 567 -812C 595 -817 602 -827 603 -841Z",[0.029,0.589]],["M 586 -132L 579 -124C 652 -78 751 3 802 70C 942 108 967 -147 586 -132Z",[-0.505,0.308]],["M 668 -333L 661 -326C 720 -281 790 -204 821 -135C 956 -72 1019 -332 668 -333Z",[-0.388,0.313]]],"bbox":{"top":-855,"bottom":108,"left":20,"right":1019},"hadv":1000}],"text":"素","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>JSX 语法实在是太香了。不过常见的方式要用上的话，必须得有一个 MVVM 框架，或者至少得有一个 VDOM 库（e.g. <a href=\"https://github.com/snabbdom/snabbdom\"><code>snabbdom</code></a>）。如果不想用这些库的话，Vanilla JS 对应的 <code>document.createElement</code> 相比起来实在是过于繁琐。正常人这个时候应该都去用 <a href=\"https://github.com/choojs/nanohtml\"><code>choojs/html</code></a> 这类 HTML template literal 库了。</p>\n<p>不过我们可以搞点灵的。</p>\n<h2>JSX-style DOM invocation</h2>\n<p>回忆 JSX 会被 tsc / 其他 build tools 翻译成 React/Preact style <code>h</code> calls，或者 <code>React.createElement</code> style calls。如果只要能弄出来一个语义一样的函数，在内部调用 DOM，那就可以用 JSX 直接创建 DOM 元素了。</p>\n<p>事实上，我们可以搞出来带 namespace 的版本，这样我们还可以用 JSX 来写 SVG：</p>\n<div class=\"highlighted highlighted-typescript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-typescript\"><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">jsxFactory</span><span style=\"color:#657b83;\">(\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">ns</span><span style=\"color:#859900;\">?: string</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#657b83;\">)</span><span style=\"color:#859900;\">: </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">tag</span><span style=\"color:#859900;\">: string</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">data</span><span style=\"color:#859900;\">: </span><span style=\"color:#b58900;\">JSXData</span><span style=\"color:#839496;\">, </span><span style=\"color:#859900;\">...</span><span style=\"color:#268bd2;\">children</span><span style=\"color:#859900;\">: </span><span style=\"color:#b58900;\">RecursiveElement</span><span style=\"color:#268bd2;\">[]</span><span style=\"color:#657b83;\">) </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#b58900;\">Element </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">return </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">tag</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">, </span><span style=\"color:#859900;\">...</span><span style=\"color:#268bd2;\">children</span><span style=\"color:#657b83;\">) </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#268bd2;\">const el </span><span style=\"color:#657b83;\">=\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#268bd2;\">ns </span><span style=\"color:#657b83;\">!== </span><span style=\"color:#b58900;\">undefined\n</span><span style=\"color:#839496;\">        </span><span style=\"color:#859900;\">? document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">createElementNS</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">ns</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">tag</span><span style=\"color:#657b83;\">)\n</span><span style=\"color:#839496;\">        </span><span style=\"color:#859900;\">: document</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">createElement</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">tag</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">?.</span><span style=\"color:#268bd2;\">class </span><span style=\"color:#657b83;\">!== </span><span style=\"color:#b58900;\">undefined</span><span style=\"color:#657b83;\">)\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#268bd2;\">el</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">setAttribute</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">class</span><span style=\"color:#839496;\">&quot;, </span><span style=\"color:#b58900;\">evalClassDef</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">.</span><span style=\"color:#268bd2;\">class</span><span style=\"color:#657b83;\">))</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">?.</span><span style=\"color:#859900;\">style </span><span style=\"color:#657b83;\">!== </span><span style=\"color:#b58900;\">undefined</span><span style=\"color:#657b83;\">)\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#268bd2;\">el</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">setAttribute</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">style</span><span style=\"color:#839496;\">&quot;, </span><span style=\"color:#b58900;\">evalStyleDef</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">style</span><span style=\"color:#657b83;\">))</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">data </span><span style=\"color:#657b83;\">!== </span><span style=\"color:#b58900;\">null</span><span style=\"color:#657b83;\">)\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#859900;\">for </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">const key </span><span style=\"color:#859900;\">in </span><span style=\"color:#268bd2;\">data</span><span style=\"color:#657b83;\">) </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">        </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">key </span><span style=\"color:#657b83;\">=== </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">class</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#859900;\">|| </span><span style=\"color:#268bd2;\">key </span><span style=\"color:#657b83;\">=== </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">style</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#859900;\">|| </span><span style=\"color:#268bd2;\">key </span><span style=\"color:#657b83;\">=== </span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">__html</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#657b83;\">) </span><span style=\"color:#859900;\">continue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">        </span><span style=\"color:#268bd2;\">el</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">setAttribute</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">key</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">data[key]</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">      }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">if </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">?.</span><span style=\"color:#268bd2;\">__html </span><span style=\"color:#657b83;\">!== </span><span style=\"color:#b58900;\">undefined</span><span style=\"color:#657b83;\">) </span><span style=\"color:#268bd2;\">el</span><span style=\"color:#839496;\">.</span><span style=\"color:#268bd2;\">innerHTML </span><span style=\"color:#657b83;\">= </span><span style=\"color:#268bd2;\">data</span><span style=\"color:#839496;\">.</span><span style=\"color:#268bd2;\">__html</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">else </span><span style=\"color:#268bd2;\">el</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">append</span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">...</span><span style=\"color:#b58900;\">flatten</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">children</span><span style=\"color:#657b83;\">))</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">return </span><span style=\"color:#268bd2;\">el</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  };\n</span><span style=\"color:#839496;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">const jsx </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">factory</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">const jsxSVG </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">factory</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">http://www.w3.org/2000/svg</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>其中，JSXData 的定义为：</p>\n<div class=\"highlighted highlighted-typescript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-typescript\"><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">type </span><span style=\"color:#b58900;\">JSXData </span><span style=\"color:#657b83;\">= </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">class</span><span style=\"color:#859900;\">?: </span><span style=\"color:#b58900;\">classDef</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">style</span><span style=\"color:#859900;\">?: </span><span style=\"color:#b58900;\">styleDef</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">__html</span><span style=\"color:#859900;\">?: string</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">[other</span><span style=\"color:#859900;\">: string</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#859900;\">: any</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">} </span><span style=\"color:#859900;\">| null</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>如果在 <code>tsconfig.json</code> 中添加如下配置：</p>\n<div class=\"highlighted highlighted-json\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-json\"><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  &quot;</span><span style=\"color:#2aa198;\">compilerOptions</span><span style=\"color:#839496;\">&quot;: </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    &quot;</span><span style=\"color:#2aa198;\">jsx</span><span style=\"color:#839496;\">&quot;: &quot;</span><span style=\"color:#2aa198;\">react</span><span style=\"color:#839496;\">&quot;,\n</span><span style=\"color:#839496;\">    &quot;</span><span style=\"color:#2aa198;\">jsxFactory</span><span style=\"color:#839496;\">&quot;: &quot;</span><span style=\"color:#2aa198;\">jsx</span><span style=\"color:#839496;\">&quot;,\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>那么只要在用到 JSX 的文件内引入 <code>jsx</code> 即可：</p>\n<div class=\"highlighted highlighted-typescript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-typescript\"><span style=\"color:#cb4b16;\">import </span><span style=\"color:#839496;\">{ </span><span style=\"color:#268bd2;\">jsx </span><span style=\"color:#839496;\">} </span><span style=\"color:#cb4b16;\">from </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">./jsx.ts</span><span style=\"color:#839496;\">&#39;\n</span><span style=\"color:#586e75;\">// Or: \n</span><span style=\"color:#cb4b16;\">import </span><span style=\"color:#839496;\">{ </span><span style=\"color:#268bd2;\">jsxSVG </span><span style=\"color:#cb4b16;\">as </span><span style=\"color:#268bd2;\">jsx </span><span style=\"color:#839496;\">} </span><span style=\"color:#cb4b16;\">from </span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">./jsx.ts</span><span style=\"color:#839496;\">&#39;\n</span></code></pre>\n</div>\n<h2>类型炸了！</h2>\n<p>然而，直接这么搞的话，tsc 会非常不开心：</p>\n<blockquote>\n<p>JSX element implicitly has type ‘any’ because no interface ‘JSX.IntrinsicElements’ exists.</p>\n</blockquote>\n<p>学习了一下 tsc 提供这个 interface 的方法，居然是通过在 <code>jsx</code> 定义的文件内放一个同名的 <code>namespace</code> 来实现：</p>\n<div class=\"highlighted highlighted-typescript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-typescript\"><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">namespace </span><span style=\"color:#b58900;\">jsx </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">namespace </span><span style=\"color:#b58900;\">JSX </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">type </span><span style=\"color:#b58900;\">Element </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">HTMLElement</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">export </span><span style=\"color:#268bd2;\">interface </span><span style=\"color:#b58900;\">IntrinsicElements </span><span style=\"color:#839496;\">{\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#586e75;\">// TODO: restrict to HTML elements\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#268bd2;\">[elemName</span><span style=\"color:#859900;\">: string</span><span style=\"color:#268bd2;\">]</span><span style=\"color:#859900;\">: </span><span style=\"color:#b58900;\">JSXData</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    }\n</span><span style=\"color:#839496;\">  }\n</span><span style=\"color:#839496;\">}\n</span></code></pre>\n</div>\n<p><code>jsx.JSX.Element</code> 指定了 JSX 吐出来的东西的类型。这里的实现略微偷懒了，其实可以给每一种元素名搞出来不同的参数类型。</p>\n<p>最有趣/灵车的地方是，如果在 <code>namespace jsxSVG</code> 中给出另一个不同的定义，在 <code>import { jsxSVG as jsx }</code> 的时候会用 <code>jsxSVG</code> 中的定义。感觉 <code>namespace xxx</code> 有点像 Scala 的 companion object 的对偶，可以强行往一个值上加一些类型信息。</p>\n<h2>SSR?</h2>\n<p>那么 SSR 呢？</p>\n<p>简单的方法是我们可以搞一个输出字符串版本的 Factory，然后动态通过运行时检查是否是 SSR 环境内，决定使用哪个 <code>jsx</code> 实现：</p>\n<div class=\"highlighted highlighted-typescript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-typescript\"><span style=\"color:#268bd2;\">const jsx </span><span style=\"color:#657b83;\">= </span><span style=\"color:#268bd2;\">context</span><span style=\"color:#839496;\">.</span><span style=\"color:#268bd2;\">SSR </span><span style=\"color:#859900;\">? </span><span style=\"color:#268bd2;\">jsxDom </span><span style=\"color:#859900;\">: </span><span style=\"color:#268bd2;\">jsxStr</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>然而这个时候上述 <code>namespace jsx</code> 的解析就不工作了。正常人这个时候就去用 <a href=\"https://github.com/jsdom/jsdom\"><code>jsdom</code></a> 给 JS Runtime 加上 DOM API 了。</p>\n<p>不过我们可以再搞点灵的。</p>\n<p>上述问题出现的主要原因是 tsc 的类型检查无法携带运行时信息。如果我们有依值类型，可以把我们想要编译器看到的东西表达地更清楚一点:</p>\n<div class=\"highlighted highlighted-typescript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-typescript\"><span style=\"color:#268bd2;\">const </span><span style=\"color:#b58900;\">JSXElementType</span><span style=\"color:#859900;\">: </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">ssr</span><span style=\"color:#859900;\">: boolean</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\"> -&gt; </span><span style=\"color:#b58900;\">type </span><span style=\"color:#657b83;\">= (</span><span style=\"color:#268bd2;\">ssr</span><span style=\"color:#657b83;\">) </span><span style=\"color:#268bd2;\">=&gt; ssr </span><span style=\"color:#859900;\">? </span><span style=\"color:#268bd2;\">string </span><span style=\"color:#859900;\">: HTMLElement</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#268bd2;\">type </span><span style=\"color:#b58900;\">Element </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">JSXElementType</span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">context</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">SSR</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>很遗憾我们显然没有这种东西。不过 TypeScript 的类型检查和运行时不一定完全对应，所以我们可以搞一些 Type hack:</p>\n<ul>\n<li>定义一个 <code>jsxStr</code> 是 SSR 版本的字符串拼接，返回的是字符串。</li>\n<li>依旧 <code>const jsx = context.SSR ? jsx : jsxStr</code>，但是 <code>jsx.JSX.Element</code> 永远是 <code>HTMLElement</code></li>\n<li>在使用这个元素的时候，区分一下是不是在 SSR 环境\n<ul>\n<li>如果不在，那么 <code>document.querySelector('balabala')!.appendChild(elem)</code>.</li>\n<li>如果在，那么 <code>template.replace('placeholder', elem.toString())</code>.</li>\n</ul>\n</li>\n</ul>\n<p>Perfectly type-checks!</p>\n<p>什么？问为啥 tsc 没有检查 <code>jsx</code> 返回值是不是和 <code>jsx.JSX.Element</code> 声称的一致？或者说我们为什么甚至需要一个 <code>jsx.JSX.Element</code> 来标记返回值？</p>\n<p>如果真的是这么搞的，那上述 hack 就不工作了。还是灵一点好，有前端开发那味儿。</p>\n<hr />\n<p>完整代码：<a href=\"https://gist.github.com/CircuitCoder/4d36f706ddd84e93eb3a999257fe239b\">https://gist.github.com/CircuitCoder/4d36f706ddd84e93eb3a999257fe239b</a></p>\n","plain":"JSX 语法实在是太香了。不过常见的方式要用上的话，必须得有一个 MVVM 框架，或者至少得有一个 VDOM 库（e.g. snabbdom）。如果不想用这些库的话，Vanilla JS 对应的 document.createElement 相比起来实在是过于繁琐。正常人这个时候应该都去用 choojs/html 这类 HTML template literal 库了。\n不过我们可以搞点灵的。\n\nJSX-style DOM invocation\n回忆 JSX 会被 tsc / 其他 build tools 翻译成 React/Preact style h calls，或者 React.createElement style calls。如果只要能弄出来一个语义一样的函数，在内部调用 DOM，那就可以用 JSX 直接创建 DOM 元素了。\n事实上，我们可以搞出来带 namespace 的版本，这样我们还可以用 JSX 来写 SVG：\nexport function jsxFactory(\n  ns?: string,\n): (tag: string, data: JSXData, ...children: RecursiveElement[]) => Element {\n  return (tag, data, ...children) => {\n    const el =\n      ns !== undefined\n        ? document.createElementNS(ns, tag)\n        : document.createElement(tag);\n    if (data?.class !== undefined)\n      el.setAttribute(\"class\", evalClassDef(data.class));\n    if (data?.style !== undefined)\n      el.setAttribute(\"style\", evalStyleDef(data.style));\n    if (data !== null)\n      for (const key in data) {\n        if (key === \"class\" || key === \"style\" || key === \"__html\") continue;\n        el.setAttribute(key, data[key]);\n      }\n\n    if (data?.__html !== undefined) el.innerHTML = data.__html;\n    else el.append(...flatten(children));\n    return el;\n  };\n}\n\nexport const jsx = factory();\nexport const jsxSVG = factory(\"http://www.w3.org/2000/svg\");\n\n其中，JSXData 的定义为：\nexport type JSXData = {\n  class?: classDef;\n  style?: styleDef;\n  __html?: string;\n  [other: string]: any;\n} | null;\n\n如果在 tsconfig.json 中添加如下配置：\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"jsx\",\n  }\n}\n\n那么只要在用到 JSX 的文件内引入 jsx 即可：\nimport { jsx } from './jsx.ts'\n// Or: \nimport { jsxSVG as jsx } from './jsx.ts'\n\n\n类型炸了！\n然而，直接这么搞的话，tsc 会非常不开心：\nJSX element implicitly has type ‘any’ because no interface ‘JSX.IntrinsicElements’ exists.\n\n学习了一下 tsc 提供这个 interface 的方法，居然是通过在 jsx 定义的文件内放一个同名的 namespace 来实现：\nexport namespace jsx {\n  export namespace JSX {\n    export type Element = HTMLElement;\n    export interface IntrinsicElements {\n      // TODO: restrict to HTML elements\n      [elemName: string]: JSXData;\n    }\n  }\n}\n\njsx.JSX.Element 指定了 JSX 吐出来的东西的类型。这里的实现略微偷懒了，其实可以给每一种元素名搞出来不同的参数类型。\n最有趣/灵车的地方是，如果在 namespace jsxSVG 中给出另一个不同的定义，在 import { jsxSVG as jsx } 的时候会用 jsxSVG 中的定义。感觉 namespace xxx 有点像 Scala 的 companion object 的对偶，可以强行往一个值上加一些类型信息。\n\nSSR?\n那么 SSR 呢？\n简单的方法是我们可以搞一个输出字符串版本的 Factory，然后动态通过运行时检查是否是 SSR 环境内，决定使用哪个 jsx 实现：\nconst jsx = context.SSR ? jsxDom : jsxStr;\n\n然而这个时候上述 namespace jsx 的解析就不工作了。正常人这个时候就去用 jsdom 给 JS Runtime 加上 DOM API 了。\n不过我们可以再搞点灵的。\n上述问题出现的主要原因是 tsc 的类型检查无法携带运行时信息。如果我们有依值类型，可以把我们想要编译器看到的东西表达地更清楚一点:\nconst JSXElementType: (ssr: boolean) -> type = (ssr) => ssr ? string : HTMLElement;\ntype Element = JSXElementType(context.SSR);\n\n很遗憾我们显然没有这种东西。不过 TypeScript 的类型检查和运行时不一定完全对应，所以我们可以搞一些 Type hack:\n- 定义一个 jsxStr 是 SSR 版本的字符串拼接，返回的是字符串。\n- 依旧 const jsx = context.SSR ? jsx : jsxStr，但是 jsx.JSX.Element 永远是 HTMLElement\n- 在使用这个元素的时候，区分一下是不是在 SSR 环境- 如果不在，那么 document.querySelector('balabala')!.appendChild(elem).\n- 如果在，那么 template.replace('placeholder', elem.toString()).\n\nPerfectly type-checks!\n什么？问为啥 tsc 没有检查 jsx 返回值是不是和 jsx.JSX.Element 声称的一致？或者说我们为什么甚至需要一个 jsx.JSX.Element 来标记返回值？\n如果真的是这么搞的，那上述 hack 就不工作了。还是灵一点好，有前端开发那味儿。\n---\n完整代码：https://gist.github.com/CircuitCoder/4d36f706ddd84e93eb3a999257fe239b\n"},{"metadata":{"id":"new-blog","lang":"zh-CN","title":"新博客前端","tags":["meta"],"publish_time":"2025-03-15T23:54:00+08:00","update_time":"2025-03-16T00:40:52+08:00","title_outline":{"groups":[{"chars":[{"char":"新","components":[["M 256 -234L 99 -303C 92 -217 67 -82 23 7L 32 17C 117 -46 179 -140 218 -218C 243 -217 252 -224 256 -234Z",[0.258,0.549]],["M 445 -566L 386 -483L 24 -483L 32 -455L 524 -455C 538 -455 548 -460 551 -471C 512 -509 445 -566 445 -566Z",[0.782,0.067]],["M 427 -417L 371 -338L 37 -338L 45 -310L 500 -310C 514 -310 524 -315 527 -326C 490 -363 427 -417 427 -417Z",[0.823,0.065]],["M 427 -778L 370 -699L 40 -699L 48 -671L 503 -671C 517 -671 527 -676 530 -687C 492 -724 427 -778 427 -778Z",[0.748,0.066]],["M 120 -675L 110 -671C 126 -625 142 -562 139 -506C 226 -415 353 -587 120 -675Z",[-0.193,0.394]],["M 347 -47L 347 -475L 210 -475L 210 -50C 210 -40 207 -33 194 -33C 177 -33 117 -37 117 -37L 117 -25C 156 -18 170 -4 180 12C 190 29 192 56 193 93C 328 83 347 36 347 -47Z",[0.042,0.732]],["M 190 -854L 183 -849C 206 -815 227 -762 227 -712C 338 -621 471 -830 190 -854Z",[-0.093,0.251]],["M 498 -631L 341 -679C 333 -616 316 -525 298 -464L 311 -464C 367 -509 425 -569 461 -613C 483 -611 494 -619 498 -631Z",[0.29,0.429]],["M 355 -284L 345 -279C 369 -232 388 -164 384 -104C 478 -11 605 -202 355 -284Z",[-0.174,0.39]],["M 702 -721L 534 -773L 534 -433C 534 -252 524 -64 412 84L 421 94C 658 -38 673 -251 673 -429L 673 -706C 688 -708 699 -713 702 -721Z",[0.094,0.799]],["M 855 -597L 783 -496L 598 -496L 598 -468L 956 -468C 970 -468 982 -473 984 -484C 937 -529 855 -597 855 -597Z",[0.63,0.138]],["M 969 -741L 824 -856C 781 -809 693 -738 619 -698L 622 -687C 723 -695 834 -715 902 -737C 936 -727 957 -730 969 -741Z",[0.439,0.284]],["M 882 56L 882 -496L 740 -496L 740 94L 766 94C 839 94 881 64 882 56Z",[-0.003,0.84]]],"bbox":{"top":-856,"bottom":94,"left":23,"right":984},"hadv":1000}],"text":"新","hadv":1000,"breakAfter":true},{"chars":[{"char":"博","components":[["M 21 -562L 29 -534L 386 -534C 400 -534 410 -539 412 -550C 379 -590 317 -652 317 -652L 262 -562Z",[0.729,0.052]],["M 122 -854L 122 95L 149 95C 201 95 262 61 262 47L 262 -808C 290 -812 297 -823 299 -837Z",[0.006,0.849]],["M 291 -233L 299 -205L 959 -205C 973 -205 984 -210 986 -221C 945 -257 877 -308 877 -308L 817 -233Z",[0.919,0.037]],["M 315 -721L 323 -693L 955 -693C 968 -693 978 -698 980 -709C 950 -741 897 -789 897 -789L 850 -721Z",[0.818,0.012]],["M 367 -631L 367 -270L 386 -270C 440 -270 497 -299 497 -311L 497 -603L 818 -603L 818 -631L 503 -631L 367 -684Z",[0.199,0.304]],["M 399 -200L 392 -195C 422 -161 447 -104 448 -53C 561 34 680 -183 399 -200Z",[-0.215,0.244]],["M 441 -521L 441 -493L 835 -493L 835 -521Z",[-0.806,0.021]],["M 441 -407L 441 -379L 835 -379L 835 -407Z",[-0.927,0.008]],["M 673 -317L 673 -59C 673 -49 669 -45 657 -45C 639 -45 551 -50 551 -50L 551 -37C 596 -29 613 -15 627 3C 641 22 645 50 647 90C 784 78 803 33 803 -54L 803 -278C 824 -281 834 -289 836 -304Z",[0.096,0.565]],["M 564 -853L 564 -281L 587 -281C 640 -281 701 -309 701 -322L 701 -809C 729 -814 736 -824 738 -838Z",[0.01,0.759]],["M 731 -842L 723 -836C 743 -818 761 -782 761 -749C 856 -682 955 -857 731 -842Z",[0.323,0.583]],["M 779 -631L 779 -298L 803 -298C 849 -298 913 -327 914 -336L 914 -587C 931 -590 941 -598 946 -604L 828 -692L 770 -631Z",[0.048,0.565]]],"bbox":{"top":-857,"bottom":95,"left":21,"right":986},"hadv":1000}],"text":"博","hadv":1000,"breakAfter":true},{"chars":[{"char":"客","components":[["M 588 -578L 602 -578C 520 -418 299 -255 28 -169L 33 -160C 339 -208 620 -340 762 -512C 789 -515 801 -519 811 -529L 678 -657Z",[0.65,0.457]],["M 178 -776L 166 -776C 167 -727 126 -680 93 -663C 58 -646 33 -614 46 -572C 61 -528 115 -516 151 -538C 201 -570 228 -656 178 -776Z",[0.216,0.401]],["M 518 -623L 338 -699C 280 -552 176 -420 80 -345L 88 -335C 230 -383 368 -461 475 -605C 499 -602 513 -611 518 -623Z",[0.486,0.486]],["M 846 -715L 156 -715L 156 -687L 846 -687Z",[0.741,0.015]],["M 373 54L 373 -210L 387 -210L 251 -259L 232 -236L 232 96L 258 96C 330 96 373 64 373 54Z",[-0.003,0.574]],["M 713 -11L 290 -11L 290 17L 713 17Z",[0.934,0.0]],["M 724 -210L 292 -210L 292 -182L 724 -182Z",[-0.953,0.005]],["M 331 -561L 320 -553C 415 -319 610 -216 862 -162C 876 -231 912 -279 973 -295L 974 -308C 718 -324 442 -384 331 -561Z",[-0.673,0.274]],["M 675 -578L 377 -578L 360 -550L 675 -550Z",[0.58,0.056]],["M 390 -850L 384 -845C 417 -818 445 -769 449 -721C 580 -639 692 -887 390 -850Z",[-0.002,0.153]],["M 623 -210L 632 -210L 632 85L 658 85C 704 85 776 60 777 53L 777 -165C 794 -169 803 -176 808 -182L 684 -274Z",[0.007,0.548]],["M 784 -715L 795 -715C 793 -677 785 -613 777 -572L 784 -566C 833 -588 895 -628 932 -659C 953 -660 963 -663 971 -672L 852 -784Z",[0.182,0.209]]],"bbox":{"top":-887,"bottom":96,"left":28,"right":974},"hadv":1000}],"text":"客","hadv":1000,"breakAfter":true},{"chars":[{"char":"前","components":[["M 25 -653L 33 -625L 949 -625C 964 -625 975 -630 978 -641C 926 -686 838 -753 838 -753L 761 -653Z",[0.917,0.039]],["M 95 -519L 95 93L 116 93C 175 93 230 61 230 47L 230 -491L 405 -491L 405 -519L 234 -519L 95 -575Z",[0.047,0.723]],["M 156 -371L 156 -343L 416 -343L 416 -371Z",[-0.902,0.003]],["M 156 -208L 156 -180L 416 -180L 416 -208Z",[-0.89,0.001]],["M 214 -847L 207 -842C 245 -798 282 -732 292 -668C 428 -576 546 -834 214 -847Z",[-0.209,0.269]],["M 332 -519L 332 -60C 332 -49 329 -43 316 -43C 298 -43 246 -47 246 -47L 246 -34C 281 -27 294 -12 303 7C 313 26 316 56 317 98C 449 86 467 39 467 -47L 467 -469C 488 -473 501 -482 507 -490L 382 -587L 322 -519Z",[0.037,0.77]],["M 614 -856C 600 -793 573 -699 548 -637L 557 -637C 631 -680 721 -744 772 -788C 796 -788 807 -796 810 -809Z",[0.525,0.243]],["M 551 -547L 551 -104L 574 -104C 624 -104 681 -125 681 -134L 681 -504C 709 -508 716 -519 718 -532Z",[0.023,0.675]],["M 756 -581L 756 -64C 756 -52 751 -48 736 -48C 714 -48 602 -54 602 -54L 602 -42C 657 -32 678 -17 695 2C 712 23 718 53 721 95C 872 83 893 34 893 -57L 893 -539C 916 -542 926 -551 928 -566Z",[0.067,0.723]]],"bbox":{"top":-856,"bottom":98,"left":25,"right":978},"hadv":1000}],"text":"前","hadv":1000,"breakAfter":true},{"chars":[{"char":"端","components":[["M 18 -140L 87 20C 99 16 110 4 114 -10C 242 -95 326 -167 384 -221L 382 -229C 245 -187 91 -151 18 -140Z",[0.56,0.275]],["M 307 -709L 248 -621L 26 -621L 34 -593L 384 -593C 398 -593 409 -598 412 -609C 374 -649 307 -709 307 -709Z",[0.701,0.086]],["M 72 -558L 58 -553C 90 -459 87 -332 78 -261C 135 -146 316 -338 72 -558Z",[-0.094,0.635]],["M 112 -841L 104 -837C 123 -790 141 -727 139 -667C 246 -564 393 -769 112 -841Z",[-0.102,0.369]],["M 407 -525L 246 -568C 239 -438 222 -250 205 -117L 218 -117C 279 -241 336 -401 368 -503C 392 -503 403 -512 407 -525Z",[0.175,0.719]],["M 872 -558L 814 -482L 372 -482L 380 -454L 951 -454C 965 -454 976 -459 979 -470C 939 -506 872 -558 872 -558Z",[0.822,0.059]],["M 503 -723L 410 -723L 410 -576L 431 -613C 414 -607 391 -586 378 -570L 504 -498L 541 -560L 533 -560L 533 -705Z",[0.035,0.377]],["M 513 49L 513 -321L 880 -321L 880 -349L 520 -349L 389 -401L 389 89L 407 89C 459 89 513 61 513 49Z",[0.186,0.365]],["M 570 -775L 410 -790L 410 -670C 511 -670 529 -670 533 -670L 533 -751C 559 -755 568 -763 570 -775Z",[-0.421,0.027]],["M 831 -588L 480 -588L 480 -560L 831 -560Z",[0.748,0.05]],["M 741 -482L 564 -482C 563 -445 556 -377 550 -333L 583 -333C 634 -371 701 -438 741 -482Z",[0.346,0.303]],["M 643 14L 643 -349L 553 -349L 553 36L 569 36C 615 36 643 19 643 14Z",[0.002,0.771]],["M 759 -840L 603 -853L 603 -572L 726 -572L 726 -814C 750 -818 757 -827 759 -840Z",[0.09,0.56]],["M 772 -12L 772 -349L 682 -349L 682 9L 698 9C 744 9 772 -8 772 -12Z",[0.007,0.749]],["M 801 -349L 811 -349L 811 -68C 811 -58 809 -52 798 -52C 787 -52 761 -54 761 -54L 761 -41C 785 -34 794 -22 799 -3C 805 16 806 47 806 88C 923 77 938 32 938 -54L 938 -301C 958 -306 970 -314 976 -322L 856 -411Z",[0.036,0.671]],["M 958 -776L 796 -790L 796 -535L 817 -535C 867 -535 921 -552 921 -560L 921 -748C 949 -753 956 -763 958 -776Z",[0.086,0.486]]],"bbox":{"top":-853,"bottom":89,"left":18,"right":979},"hadv":1000}],"text":"端","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":false,"img":null},"html":"<p>正经写博客的人会每天都在写文章，不正经写博客的人每天都把表达欲用在“搞博客”上——修改主题，更新框架，等等。这一慢性病的终极症状就是完全重写。很遗憾，喵喵病得挺深的，这个从之前的博客站点迭代上就可以看出来。Well，之前的站点从今天开始正式变成前博客了。</p>\n<p>本来这篇“公告”本身想起名叫什么结构表达展示云云，以体现一些视觉设计的 Idea，后来一想还是直接点，因为其实我可能自己也不知道我想表达什么。现在来看，自己喜欢的设计风格确实变化了很多。当认识到自己其实本质上不懂设计以后，其实写前端反而变得更自由了一些，可以围绕少量想达成的视觉效果而进行非常繁杂的周边设计和很糟糕的取舍。这一个前端基本上就是将在 <a href=\"/post/hello-2023\">2023 展望</a> 中提及的视觉设计，再加上这两年给 TUNA 镜像站写愚人节前端的经验，给完成了。这是我自认为这一站点最大的特点。</p>\n<p>技术栈角度而言，现在这一博客以静态站生成方式工作，但是前端本身并未使用框架，是直接在 DOM API 上实现的。这可能是一种 NIH 综合征的具体表现，但我更愿意骗自己这是视觉设计所导致的。我们意识到很多时候动画是本质上是带状态的渲染过程，抽象为无状态的 MVVM 是一种过度简化，导致很多时候动画只能使用 Transition + transitionend event 实现，其实还是挺脏并且挺受限制的。现在本站的整体结构比较接近一个状态机，切换过程可以使用 Promise 去控制，这样用 WAAPI 会更自由一些。具体实现这一网站中遇到的技术问题，后续会继续写一些博文，放在 meta tag 内。</p>\n<p>重制网站的另一个很大的目标是让我自己写博文的体验更简单一些。目前所有博客内容直接集成进了同一个仓库内存储，更新时间是使用 Git 跟踪的，也可以直接使用其他编辑器编辑，发布和更新的体验好了很多。希望使用这些新的工具可以记录更多的想法，以及部分技术相关的博客也许可以使用英文写，也许可以达到更多的受众。加上了评论系统也是很久之前就像做的事情。</p>\n<p>目前这个新站点还有一些没有完全搞定的地方，比如在 FF 和 Safari 上的 SVG 渲染有一些问题，Tag 列表还没有完成，中英文切换还没有实现，之后也许会补充上之前博文的翻译（人工或者 LLM），然而目前点上去是一个 No-op。网站的源码位于 <a href=\"https://github.com/CircuitCoder/layered\">GitHub CircuitCoder/layered</a>，起这个名字的原因具体见 <a href=\"/about\">关于页面</a>：相比于 22 年写的那个关于页面，有很多相似之处，但是心境发生了一些变化，这也体现在了 Brand name 的变化上。</p>\n<p>我自己感觉这些变化还是挺好的。</p>\n<hr />\n<p>怀旧服： <a href=\"https://legacy.meow.c-3.moe\">https://legacy.meow.c-3.moe</a></p>\n","plain":"正经写博客的人会每天都在写文章，不正经写博客的人每天都把表达欲用在“搞博客”上——修改主题，更新框架，等等。这一慢性病的终极症状就是完全重写。很遗憾，喵喵病得挺深的，这个从之前的博客站点迭代上就可以看出来。Well，之前的站点从今天开始正式变成前博客了。\n本来这篇“公告”本身想起名叫什么结构表达展示云云，以体现一些视觉设计的 Idea，后来一想还是直接点，因为其实我可能自己也不知道我想表达什么。现在来看，自己喜欢的设计风格确实变化了很多。当认识到自己其实本质上不懂设计以后，其实写前端反而变得更自由了一些，可以围绕少量想达成的视觉效果而进行非常繁杂的周边设计和很糟糕的取舍。这一个前端基本上就是将在 2023 展望 中提及的视觉设计，再加上这两年给 TUNA 镜像站写愚人节前端的经验，给完成了。这是我自认为这一站点最大的特点。\n技术栈角度而言，现在这一博客以静态站生成方式工作，但是前端本身并未使用框架，是直接在 DOM API 上实现的。这可能是一种 NIH 综合征的具体表现，但我更愿意骗自己这是视觉设计所导致的。我们意识到很多时候动画是本质上是带状态的渲染过程，抽象为无状态的 MVVM 是一种过度简化，导致很多时候动画只能使用 Transition + transitionend event 实现，其实还是挺脏并且挺受限制的。现在本站的整体结构比较接近一个状态机，切换过程可以使用 Promise 去控制，这样用 WAAPI 会更自由一些。具体实现这一网站中遇到的技术问题，后续会继续写一些博文，放在 meta tag 内。\n重制网站的另一个很大的目标是让我自己写博文的体验更简单一些。目前所有博客内容直接集成进了同一个仓库内存储，更新时间是使用 Git 跟踪的，也可以直接使用其他编辑器编辑，发布和更新的体验好了很多。希望使用这些新的工具可以记录更多的想法，以及部分技术相关的博客也许可以使用英文写，也许可以达到更多的受众。加上了评论系统也是很久之前就像做的事情。\n目前这个新站点还有一些没有完全搞定的地方，比如在 FF 和 Safari 上的 SVG 渲染有一些问题，Tag 列表还没有完成，中英文切换还没有实现，之后也许会补充上之前博文的翻译（人工或者 LLM），然而目前点上去是一个 No-op。网站的源码位于 GitHub CircuitCoder/layered，起这个名字的原因具体见 关于页面：相比于 22 年写的那个关于页面，有很多相似之处，但是心境发生了一些变化，这也体现在了 Brand name 的变化上。\n我自己感觉这些变化还是挺好的。\n---\n怀旧服： https://legacy.meow.c-3.moe\n"},{"metadata":{"id":"about-ac-mirage","lang":"zh-CN","title":"关于《刺客信条-幻景》","tags":["游戏屋"],"publish_time":"2025-01-31T02:00:27.313Z","update_time":"2025-01-31T03:12:48.614Z","title_outline":{"groups":[{"chars":[{"char":"关","components":[["M 556 -431L 556 -600L 396 -600L 396 -430C 396 -249 345 -64 22 85L 25 93C 509 -11 555 -251 556 -431Z",[0.303,0.635]],["M 825 -459L 745 -359L 32 -359L 40 -331L 941 -331C 956 -331 968 -336 971 -347C 916 -392 825 -459 825 -459Z",[0.894,0.043]],["M 774 -702L 697 -607L 96 -607L 104 -579L 884 -579C 899 -579 911 -584 914 -595C 861 -639 774 -702 774 -702Z",[0.88,0.047]],["M 221 -848L 214 -843C 252 -790 287 -716 296 -645C 428 -545 555 -802 221 -848Z",[-0.216,0.333]],["M 551 -356L 541 -352C 590 -121 680 12 857 92C 874 17 918 -34 975 -50L 977 -62C 796 -95 622 -193 551 -356Z",[-0.481,0.403]],["M 807 -798L 614 -855C 602 -778 575 -665 547 -589L 557 -589C 637 -645 720 -723 769 -779C 792 -778 803 -786 807 -798Z",[0.283,0.406]]],"bbox":{"top":-855,"bottom":93,"left":22,"right":977},"hadv":1000}],"text":"关","hadv":1000,"breakAfter":true},{"chars":[{"char":"于","components":[["M 26 -449L 34 -421L 946 -421C 961 -421 973 -426 975 -437C 920 -483 829 -550 829 -550L 748 -449Z",[0.913,0.041]],["M 109 -745L 117 -717L 875 -717C 890 -717 901 -722 904 -733C 850 -778 761 -844 761 -844L 682 -745Z",[0.9,0.042]],["M 426 -745L 426 -90C 426 -78 420 -70 404 -70C 375 -70 237 -78 237 -78L 237 -66C 305 -55 330 -38 350 -16C 372 7 380 43 382 93C 552 82 579 13 579 -85L 579 -745Z",[0.058,0.773]]],"bbox":{"top":-844,"bottom":93,"left":26,"right":975},"hadv":1000}],"text":"于","hadv":1000,"breakAfter":true},{"chars":[{"char":"《","components":[["M 832 80L 569 -380L 832 -840L 803 -858L 529 -380L 803 98Z",[0.001,0.709]],["M 974 80L 711 -380L 974 -840L 945 -858L 671 -380L 945 98Z",[0.002,0.707]]],"bbox":{"top":-858,"bottom":98,"left":529,"right":974},"hadv":1000}],"text":"《","hadv":1000,"breakAfter":false},{"chars":[{"char":"刺","components":[["M 254 -372C 213 -223 118 -58 12 27L 20 38C 153 -21 271 -123 338 -216Z",[0.414,0.571]],["M 31 -691L 39 -663L 586 -663C 600 -663 611 -668 614 -679C 568 -721 490 -784 490 -784L 421 -691Z",[0.811,0.048]],["M 69 -570L 69 -256L 93 -256C 159 -256 198 -284 198 -292L 198 -570L 211 -570L 69 -623Z",[-0.007,0.62]],["M 124 -570L 124 -542L 475 -542L 475 -570Z",[-0.865,0.009]],["M 253 -847L 253 93L 278 93C 328 93 385 61 385 47L 385 -802C 413 -806 420 -816 422 -831Z",[0.006,0.857]],["M 375 -278L 366 -272C 409 -219 449 -139 457 -66C 577 26 688 -214 375 -278Z",[-0.273,0.407]],["M 450 -570L 450 -408C 450 -398 447 -392 436 -392C 423 -392 391 -395 391 -395L 391 -381C 418 -376 427 -364 434 -349C 441 -334 442 -309 443 -276C 555 -286 569 -325 569 -397L 569 -522C 590 -525 604 -535 610 -543L 492 -630L 440 -570Z",[0.085,0.587]],["M 615 -774L 615 -133L 639 -133C 688 -133 745 -158 745 -168L 745 -731C 772 -735 779 -745 781 -759Z",[0.012,0.776]],["M 800 -846L 800 -77C 800 -66 795 -61 780 -61C 758 -61 657 -67 657 -67L 657 -54C 708 -44 728 -29 744 -8C 760 13 765 44 768 89C 917 76 937 26 937 -68L 937 -801C 962 -805 972 -815 973 -830Z",[0.036,0.834]]],"bbox":{"top":-847,"bottom":93,"left":12,"right":973},"hadv":1000}],"text":"刺","hadv":1000,"breakAfter":true},{"chars":[{"char":"客","components":[["M 588 -578L 602 -578C 520 -418 299 -255 28 -169L 33 -160C 339 -208 620 -340 762 -512C 789 -515 801 -519 811 -529L 678 -657Z",[0.65,0.457]],["M 178 -776L 166 -776C 167 -727 126 -680 93 -663C 58 -646 33 -614 46 -572C 61 -528 115 -516 151 -538C 201 -570 228 -656 178 -776Z",[0.216,0.401]],["M 518 -623L 338 -699C 280 -552 176 -420 80 -345L 88 -335C 230 -383 368 -461 475 -605C 499 -602 513 -611 518 -623Z",[0.486,0.486]],["M 846 -715L 156 -715L 156 -687L 846 -687Z",[0.741,0.015]],["M 373 54L 373 -210L 387 -210L 251 -259L 232 -236L 232 96L 258 96C 330 96 373 64 373 54Z",[-0.003,0.574]],["M 713 -11L 290 -11L 290 17L 713 17Z",[0.934,0.0]],["M 724 -210L 292 -210L 292 -182L 724 -182Z",[-0.953,0.005]],["M 331 -561L 320 -553C 415 -319 610 -216 862 -162C 876 -231 912 -279 973 -295L 974 -308C 718 -324 442 -384 331 -561Z",[-0.673,0.274]],["M 675 -578L 377 -578L 360 -550L 675 -550Z",[0.58,0.056]],["M 390 -850L 384 -845C 417 -818 445 -769 449 -721C 580 -639 692 -887 390 -850Z",[-0.002,0.153]],["M 623 -210L 632 -210L 632 85L 658 85C 704 85 776 60 777 53L 777 -165C 794 -169 803 -176 808 -182L 684 -274Z",[0.007,0.548]],["M 784 -715L 795 -715C 793 -677 785 -613 777 -572L 784 -566C 833 -588 895 -628 932 -659C 953 -660 963 -663 971 -672L 852 -784Z",[0.182,0.209]]],"bbox":{"top":-887,"bottom":96,"left":28,"right":974},"hadv":1000}],"text":"客","hadv":1000,"breakAfter":true},{"chars":[{"char":"信","components":[["M 392 -803L 193 -859C 162 -659 89 -447 16 -312L 27 -305C 169 -413 276 -567 351 -781C 375 -781 388 -790 392 -803Z",[0.303,0.665]],["M 309 -554L 188 -598L 135 -528L 135 95L 162 95C 218 95 276 65 278 54L 278 -534C 298 -538 306 -544 309 -554Z",[0.012,0.786]],["M 863 -759L 793 -663L 314 -663L 322 -635L 960 -635C 974 -635 985 -640 988 -651C 942 -694 863 -759 863 -759Z",[0.771,0.07]],["M 810 -611L 746 -523L 374 -523L 382 -495L 896 -495C 911 -495 922 -500 924 -511C 882 -551 810 -611 810 -611Z",[0.764,0.079]],["M 808 -464L 744 -376L 382 -376L 390 -348L 895 -348C 909 -348 920 -353 923 -364C 881 -404 808 -464 808 -464Z",[0.819,0.074]],["M 528 50L 528 -219L 825 -219L 825 -247L 535 -247L 386 -304L 386 94L 406 94C 465 94 528 63 528 50Z",[0.179,0.286]],["M 830 -23L 469 -23L 469 5L 830 5Z",[0.924,0.001]],["M 520 -860L 514 -855C 550 -815 583 -752 590 -692C 722 -600 843 -853 520 -860Z",[-0.09,0.194]],["M 739 -247L 749 -247L 749 81L 774 81C 823 81 893 53 894 44L 894 -196C 915 -200 927 -210 933 -218L 803 -316Z",[0.022,0.556]]],"bbox":{"top":-860,"bottom":95,"left":16,"right":988},"hadv":1000}],"text":"信","hadv":1000,"breakAfter":true},{"chars":[{"char":"条","components":[["M 601 -733L 616 -733C 521 -552 294 -423 28 -355L 32 -344C 365 -366 630 -471 781 -670C 808 -672 818 -675 826 -687L 693 -813Z",[0.654,0.426]],["M 417 -166L 253 -254C 217 -157 134 -25 33 58L 40 68C 185 22 305 -66 379 -152C 403 -149 412 -156 417 -166Z",[0.476,0.451]],["M 537 -804L 338 -858C 289 -726 177 -585 62 -510L 67 -503C 240 -552 400 -665 495 -790C 524 -788 532 -793 537 -804Z",[0.504,0.478]],["M 768 -378L 695 -283L 85 -283L 93 -255L 870 -255C 885 -255 896 -260 899 -271C 850 -314 768 -378 768 -378Z",[0.894,0.046]],["M 613 -398L 430 -413L 430 -54C 430 -42 425 -38 411 -38C 389 -38 267 -46 267 -46L 267 -34C 326 -24 347 -9 365 8C 385 27 389 57 393 97C 555 86 580 39 580 -53L 580 -372C 601 -375 611 -383 613 -398Z",[0.093,0.619]],["M 700 -733L 322 -733L 297 -705L 700 -705Z",[0.518,0.044]],["M 309 -702L 299 -694C 398 -470 599 -388 862 -348C 875 -421 909 -472 972 -491L 972 -504C 707 -504 425 -542 309 -702Z",[-0.727,0.23]],["M 629 -212L 621 -206C 681 -143 748 -49 775 36C 916 123 1009 -155 629 -212Z",[-0.36,0.395]]],"bbox":{"top":-858,"bottom":123,"left":28,"right":1009},"hadv":1000}],"text":"条","hadv":1000,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"幻","components":[["M 573 -567L 391 -658C 344 -497 175 -221 78 -139C 63 -126 28 -117 28 -117L 101 43C 131 29 151 -16 157 -95L 85 -95L 85 -82C 242 -188 455 -416 538 -565L 507 -554C 544 -542 566 -553 573 -567Z",[0.48,0.672]],["M 416 -793L 227 -848C 208 -744 129 -558 77 -504C 66 -495 40 -487 40 -487L 109 -337C 138 -351 157 -396 161 -469L 91 -469L 92 -457C 190 -525 325 -674 389 -784L 356 -773C 393 -766 411 -778 416 -793Z",[0.369,0.648]],["M 58 -113L 108 27C 278 -33 411 -92 482 -128L 481 -139C 305 -125 130 -115 58 -113Z",[0.688,0.144]],["M 77 -485L 118 -350C 241 -397 345 -446 397 -474L 397 -485C 265 -483 133 -483 77 -485Z",[0.586,0.105]],["M 368 -285L 358 -280C 395 -200 417 -97 407 -2C 532 128 679 -143 368 -285Z",[-0.16,0.502]],["M 845 -736L 422 -736L 431 -708L 845 -708Z",[0.67,0.01]],["M 776 -736L 789 -736C 779 -298 765 -117 722 -78C 711 -69 700 -65 685 -65C 664 -65 623 -66 596 -68L 595 -57C 634 -46 655 -30 669 -6C 680 12 683 44 683 95C 743 95 794 79 835 36C 902 -30 918 -164 930 -682C 954 -686 969 -693 977 -703L 854 -815Z",[0.119,0.786]]],"bbox":{"top":-848,"bottom":128,"left":28,"right":977},"hadv":1000}],"text":"幻","hadv":1000,"breakAfter":true},{"chars":[{"char":"景","components":[["M 857 -538L 791 -452L 31 -452L 39 -424L 948 -424C 963 -424 974 -429 976 -440C 932 -480 857 -538 857 -538Z",[0.913,0.032]],["M 399 -97L 234 -170C 201 -96 128 3 45 62L 51 73C 175 48 296 -14 362 -81C 386 -80 395 -87 399 -97Z",[0.506,0.353]],["M 328 -522L 328 -763L 733 -763L 733 -791L 336 -791L 186 -848L 186 -479L 206 -479C 264 -479 328 -509 328 -522Z",[0.365,0.195]],["M 354 -187L 354 -332L 716 -332L 716 -360L 361 -360L 209 -417L 209 -145L 229 -145C 287 -145 354 -175 354 -187Z",[0.509,0.137]],["M 717 -221L 261 -221L 261 -193L 717 -193Z",[-0.935,0.001]],["M 737 -576L 262 -576L 262 -548L 737 -548Z",[0.747,0.014]],["M 737 -684L 262 -684L 262 -656L 737 -656Z",[0.665,0.024]],["M 575 -57L 575 -215L 430 -215L 430 -59C 430 -50 426 -44 413 -44C 393 -44 310 -49 310 -49L 310 -37C 358 -29 375 -13 387 4C 401 23 404 53 406 95C 553 84 575 32 575 -57Z",[0.11,0.397]],["M 408 -540L 402 -534C 423 -517 449 -482 456 -449C 566 -394 644 -594 408 -540Z",[0.108,0.017]],["M 613 -138L 609 -127C 701 -66 762 17 781 65C 915 141 1034 -144 613 -138Z",[-0.417,0.303]],["M 637 -360L 647 -360L 647 -158L 673 -158C 718 -158 793 -179 794 -186L 794 -309C 815 -313 827 -323 833 -330L 700 -429Z",[-0.006,0.39]],["M 666 -791L 676 -791L 676 -505L 701 -505C 747 -505 820 -527 821 -534L 821 -740C 842 -744 854 -754 860 -762L 729 -860Z",[0.051,0.524]]],"bbox":{"top":-860,"bottom":141,"left":31,"right":1034},"hadv":1000}],"text":"景","hadv":1000,"breakAfter":false},{"chars":[{"char":"》","components":[["M 26 80L 55 98L 329 -380L 55 -858L 26 -840L 289 -380Z",[0.001,0.711]],["M 168 80L 197 98L 471 -380L 197 -858L 168 -840L 431 -380Z",[0.001,0.71]]],"bbox":{"top":-858,"bottom":98,"left":26,"right":471},"hadv":1000}],"text":"》","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>春节几天狂玩阿育罐头，和 AC Mirage 跨年了。以下是一些感想。</p>\n<p>Some Context:</p>\n<ul>\n<li>Steam 24 冬促不到 100 买的，原价这罐头是真不值</li>\n<li>最高难度，没开 perma-death</li>\n<li>飞雷神实在是太 Imba 了，所以全程没用过</li>\n</ul>\n<p>因为我是二代忠实粉丝（其实玩的第一部是启示录），听说要“回归系列传统”就买了，结果真回归了系列传统，就连地图大小都跟启示录差不多大（笑）。总共流程我玩了 20h，把所有支线都打完大概 25h 吧。首先夸一夸：流程不长，但是剧情和叙事还是挺完整的。由于我没玩过 Vahalla，可能缺失一些上下文，不过作为一个独立的故事还算有趣。此外，加上怀念滤镜之后这个罐头也不算难吃，潜行要素在幻景中被极大强调了，几乎所有任务都是在管制区域内进行的，每个任务当成一个小的箱亭解密，比较对付解谜玩家的胃口。主线剧情有一些非线性性，让玩家跑图稍微有点自由，这是比最早几代还在做 ACT 的时候略有进步的地方。数据库还是有很多很有趣的内容，虽然游戏里的巴格达没有什么如实构建的历史建筑，不过氛围还是做到位了。</p>\n<p>能看出这一代游戏机制是对着 AC2 做的。不过很明显能看出 AC2 的游戏设计已经落后时代了，毕竟是 15 年+ 之前的游戏了（我好老）。我个人最大的问题是这个开放世界的搞法。八年前 BotW 抄了再八年前 AC 的爬塔，加上了 Paraglider 和匹配的地图设计，算是把这一套开放世界的探索机制搞得非常完善了。然后现在幻景把倒车又倒回去了，甚至现在开大地图也不需要爬塔，地图设计在视觉上有太多的 Visual clutter 了，很难一眼找到 PoI，结果就是想找个任务目标全靠抬头显示那个罗盘。所以爬塔现在也就只能作为一个快速移动点，但是又没有 Paraglider 这类从高处向下的横向移动手段，所以搞个塔有什么意义呢？真的是为了回归传统而回归传统了。不过在塔上面同步的动画还是依旧很好看。</p>\n<p>细节说说移动的问题，宏观上来说，问题主要是快速移动点太少，缺乏在高空横向移动的能力，所以只能走巷子或者爬房子。这里其实看地图大小是不准确的，AC 这种城市地图导致横向移动其实非常困难，很多的时候和 PoI 距离就是 100m，然后爬墙爬一分钟，是很坐牢的体验。考虑到可视性也不是很好，导致的结果是地图的实际观感其实比实际地图尺寸大很多，里面的内容也被稀释了。结果就是主游戏循环就变成了冲着主线任务直线爬墙，然后如果附近有什么 PoI 显示在抬头显示罗盘上了就去弄一下，其实完全没有什么探索。微观上来说，这个爬墙既不是二代那种只有少部分位置可以爬的设计，也不是 BotW 那种哪里都可以爬的设计，也不是 Unity 有很复杂的移动系统，结果就是很多的时候难以区分哪里可以移动，然后有意外 Snap 到墙面或者墙顶的情况，尤其是会意外从潜行的草丛的离开，让人想砸手柄。我甚至遇到了在墙顶按住向前结果主角向后走的情况。这应该是由于复用了 Vahalla 的引擎，但是没有针对潜行/城市环境做特殊优化。</p>\n<p>最后说一说战斗和任务设计，我感觉这两者其实是相关的。由于砍了 RPG 要素，所以主角的生命值、防御和攻击力其实没有什么 Scaling，即使敌人也没有，这依旧导致即使在游戏后期，只要被三个敌人围起来，是非常难打的。阿育的解决方法是引入了飞雷神，然后决定既然已经有飞雷神了那么 F__k it 然后就不管敌人的布置了。前面说了其实每个任务可以当成一个箱亭解谜，这直接导致整个解谜都不存在了…还不如把之前的无敌袖箭/防反/连击弄回来呢。因此总体来说，幻景的任务/解谜设计远不如二代 Self-consistent，比如鹰眼视觉看不到敌人巡逻轨迹，在被发现以后的战斗基本不存在，吹口哨保证只有一个敌人能听到大大降低了寻找解决方案的难度，就墩草丛里吹口哨就行了，然后在草丛里暗杀还是有概率被发现所以实质抽奖。因为我决定不用飞雷神，然后选的还是最高难度，所以真的是蹲了 20h 草丛，战斗打成了 Sifu。最后就是门闩。我个人对门闩的意见不是很大，不过看得出来很多人在 Vahalla 打了几十个小时门闩以后已经受够了。总结就是客观而言我觉得阿育在幻景里基本没有在任务设计上下什么功夫，这也算是罐头不得不品味的一点吧。</p>\n<p>此外，游戏有很多地方非常未经打磨。在集市里有个地方 100% 卡 OoB，然后又由于爬墙会 Snap，所以我至少卡出去三次…退出到主菜单再进去居然还卡在原地，看来幻景的存档是真的存了主角的座标…然后加载了五分钟前的自动存档，花了五分钟跑回去，然后一爬墙又卡进去了，非常幽默。所有的预渲染 CG 帧率都很低，显示是 30 FPS 播放但我觉得可能只有 15，这就是阿育为了降低游戏体积作出的努力吗，我哭了。以及有一些中文翻译非常神秘，I mean，武器的“防御攻击”是什么？？最后发现其实是指架势伤害。一句语音 “I wait for no man” 字幕翻译成了我不等待任何男人，最关键这还是个女角色说的，让人十分难绷。</p>\n<p>总体而言，虽然为了重温小时候在寒假玩二代的体验还是玩的挺开心的，不过客观而言以现在的标准来看，幻景的问题还是很多的，所以很难说这个开心有多少成分是看了游戏乐子…虽然不知道阿育下次做这种刺客信条是什么时候，不过乐见他们还是有这个动力去做这样一个游戏，也有很多进步空间，还是期待一下吧。<small>虽然我感觉影卖不出去然后这系列就要倒闭了…</small></p>\n","plain":"春节几天狂玩阿育罐头，和 AC Mirage 跨年了。以下是一些感想。\nSome Context:\n- Steam 24 冬促不到 100 买的，原价这罐头是真不值\n- 最高难度，没开 perma-death\n- 飞雷神实在是太 Imba 了，所以全程没用过\n因为我是二代忠实粉丝（其实玩的第一部是启示录），听说要“回归系列传统”就买了，结果真回归了系列传统，就连地图大小都跟启示录差不多大（笑）。总共流程我玩了 20h，把所有支线都打完大概 25h 吧。首先夸一夸：流程不长，但是剧情和叙事还是挺完整的。由于我没玩过 Vahalla，可能缺失一些上下文，不过作为一个独立的故事还算有趣。此外，加上怀念滤镜之后这个罐头也不算难吃，潜行要素在幻景中被极大强调了，几乎所有任务都是在管制区域内进行的，每个任务当成一个小的箱亭解密，比较对付解谜玩家的胃口。主线剧情有一些非线性性，让玩家跑图稍微有点自由，这是比最早几代还在做 ACT 的时候略有进步的地方。数据库还是有很多很有趣的内容，虽然游戏里的巴格达没有什么如实构建的历史建筑，不过氛围还是做到位了。\n能看出这一代游戏机制是对着 AC2 做的。不过很明显能看出 AC2 的游戏设计已经落后时代了，毕竟是 15 年+ 之前的游戏了（我好老）。我个人最大的问题是这个开放世界的搞法。八年前 BotW 抄了再八年前 AC 的爬塔，加上了 Paraglider 和匹配的地图设计，算是把这一套开放世界的探索机制搞得非常完善了。然后现在幻景把倒车又倒回去了，甚至现在开大地图也不需要爬塔，地图设计在视觉上有太多的 Visual clutter 了，很难一眼找到 PoI，结果就是想找个任务目标全靠抬头显示那个罗盘。所以爬塔现在也就只能作为一个快速移动点，但是又没有 Paraglider 这类从高处向下的横向移动手段，所以搞个塔有什么意义呢？真的是为了回归传统而回归传统了。不过在塔上面同步的动画还是依旧很好看。\n细节说说移动的问题，宏观上来说，问题主要是快速移动点太少，缺乏在高空横向移动的能力，所以只能走巷子或者爬房子。这里其实看地图大小是不准确的，AC 这种城市地图导致横向移动其实非常困难，很多的时候和 PoI 距离就是 100m，然后爬墙爬一分钟，是很坐牢的体验。考虑到可视性也不是很好，导致的结果是地图的实际观感其实比实际地图尺寸大很多，里面的内容也被稀释了。结果就是主游戏循环就变成了冲着主线任务直线爬墙，然后如果附近有什么 PoI 显示在抬头显示罗盘上了就去弄一下，其实完全没有什么探索。微观上来说，这个爬墙既不是二代那种只有少部分位置可以爬的设计，也不是 BotW 那种哪里都可以爬的设计，也不是 Unity 有很复杂的移动系统，结果就是很多的时候难以区分哪里可以移动，然后有意外 Snap 到墙面或者墙顶的情况，尤其是会意外从潜行的草丛的离开，让人想砸手柄。我甚至遇到了在墙顶按住向前结果主角向后走的情况。这应该是由于复用了 Vahalla 的引擎，但是没有针对潜行/城市环境做特殊优化。\n最后说一说战斗和任务设计，我感觉这两者其实是相关的。由于砍了 RPG 要素，所以主角的生命值、防御和攻击力其实没有什么 Scaling，即使敌人也没有，这依旧导致即使在游戏后期，只要被三个敌人围起来，是非常难打的。阿育的解决方法是引入了飞雷神，然后决定既然已经有飞雷神了那么 F__k it 然后就不管敌人的布置了。前面说了其实每个任务可以当成一个箱亭解谜，这直接导致整个解谜都不存在了…还不如把之前的无敌袖箭/防反/连击弄回来呢。因此总体来说，幻景的任务/解谜设计远不如二代 Self-consistent，比如鹰眼视觉看不到敌人巡逻轨迹，在被发现以后的战斗基本不存在，吹口哨保证只有一个敌人能听到大大降低了寻找解决方案的难度，就墩草丛里吹口哨就行了，然后在草丛里暗杀还是有概率被发现所以实质抽奖。因为我决定不用飞雷神，然后选的还是最高难度，所以真的是蹲了 20h 草丛，战斗打成了 Sifu。最后就是门闩。我个人对门闩的意见不是很大，不过看得出来很多人在 Vahalla 打了几十个小时门闩以后已经受够了。总结就是客观而言我觉得阿育在幻景里基本没有在任务设计上下什么功夫，这也算是罐头不得不品味的一点吧。\n此外，游戏有很多地方非常未经打磨。在集市里有个地方 100% 卡 OoB，然后又由于爬墙会 Snap，所以我至少卡出去三次…退出到主菜单再进去居然还卡在原地，看来幻景的存档是真的存了主角的座标…然后加载了五分钟前的自动存档，花了五分钟跑回去，然后一爬墙又卡进去了，非常幽默。所有的预渲染 CG 帧率都很低，显示是 30 FPS 播放但我觉得可能只有 15，这就是阿育为了降低游戏体积作出的努力吗，我哭了。以及有一些中文翻译非常神秘，I mean，武器的“防御攻击”是什么？？最后发现其实是指架势伤害。一句语音 “I wait for no man” 字幕翻译成了我不等待任何男人，最关键这还是个女角色说的，让人十分难绷。\n总体而言，虽然为了重温小时候在寒假玩二代的体验还是玩的挺开心的，不过客观而言以现在的标准来看，幻景的问题还是很多的，所以很难说这个开心有多少成分是看了游戏乐子…虽然不知道阿育下次做这种刺客信条是什么时候，不过乐见他们还是有这个动力去做这样一个游戏，也有很多进步空间，还是期待一下吧。虽然我感觉影卖不出去然后这系列就要倒闭了…\n"},{"metadata":{"id":"cyber-cleanup","lang":"zh-CN","title":"赛博春节扫除","tags":["灵车"],"publish_time":"2025-01-27T15:59:28.420Z","update_time":"2025-01-27T15:59:28.420Z","title_outline":{"groups":[{"chars":[{"char":"赛","components":[["M 456 -418L 265 -418C 231 -325 131 -223 22 -159L 27 -149C 199 -195 373 -284 456 -418Z",[0.587,0.435]],["M 141 -786L 128 -786C 133 -746 104 -706 77 -690C 44 -675 21 -647 31 -608C 44 -568 92 -557 124 -575C 169 -601 191 -680 141 -786Z",[0.191,0.397]],["M 822 -487L 763 -418L 59 -418L 67 -390L 904 -390C 918 -390 928 -395 931 -406C 889 -440 822 -487 822 -487Z",[0.947,0.025]],["M 600 -218L 426 -251C 419 -99 396 -3 77 78L 82 94C 499 42 536 -58 562 -196C 586 -196 597 -206 600 -218Z",[0.534,0.445]],["M 852 -737L 133 -737L 133 -709L 852 -709Z",[0.683,0.024]],["M 749 -684L 697 -623L 171 -623L 179 -595L 819 -595C 833 -595 843 -600 846 -611C 808 -642 749 -684 749 -684Z",[0.903,0.026]],["M 739 -579L 690 -521L 187 -521L 195 -493L 803 -493C 816 -493 826 -498 829 -509C 794 -539 739 -579 739 -579Z",[0.854,0.037]],["M 360 -75L 360 -278L 691 -278L 691 -306L 367 -306L 267 -344L 224 -316L 224 -34L 243 -34C 299 -34 360 -63 360 -75Z",[0.351,0.207]],["M 462 -692L 297 -706L 297 -402L 434 -402L 434 -669C 455 -673 460 -681 462 -692Z",[0.014,0.537]],["M 401 -857L 395 -852C 414 -828 438 -785 442 -744C 562 -667 680 -881 401 -857Z",[0.036,0.194]],["M 464 -79L 461 -67C 605 -29 700 33 750 75C 876 167 1111 -81 464 -79Z",[-0.681,0.234]],["M 710 -684L 543 -698L 543 -403L 682 -403L 682 -661C 703 -665 709 -673 710 -684Z",[0.021,0.507]],["M 626 -411L 616 -405C 668 -287 768 -210 892 -158C 905 -221 934 -264 982 -279L 982 -290C 856 -302 697 -338 626 -411Z",[-0.581,0.27]],["M 617 -306L 627 -306L 627 -74L 650 -74C 692 -74 759 -95 760 -101L 760 -256C 781 -260 794 -270 800 -278L 675 -370Z",[0.029,0.465]],["M 810 -737L 821 -737C 822 -705 821 -650 818 -615L 826 -609C 867 -626 918 -658 949 -683C 969 -685 979 -687 987 -696L 874 -802Z",[0.315,-0.226]]],"bbox":{"top":-881,"bottom":167,"left":21,"right":1111},"hadv":1000}],"text":"赛","hadv":1000,"breakAfter":true},{"chars":[{"char":"博","components":[["M 21 -562L 29 -534L 386 -534C 400 -534 410 -539 412 -550C 379 -590 317 -652 317 -652L 262 -562Z",[0.729,0.052]],["M 122 -854L 122 95L 149 95C 201 95 262 61 262 47L 262 -808C 290 -812 297 -823 299 -837Z",[0.006,0.849]],["M 291 -233L 299 -205L 959 -205C 973 -205 984 -210 986 -221C 945 -257 877 -308 877 -308L 817 -233Z",[0.919,0.037]],["M 315 -721L 323 -693L 955 -693C 968 -693 978 -698 980 -709C 950 -741 897 -789 897 -789L 850 -721Z",[0.818,0.012]],["M 367 -631L 367 -270L 386 -270C 440 -270 497 -299 497 -311L 497 -603L 818 -603L 818 -631L 503 -631L 367 -684Z",[0.199,0.304]],["M 399 -200L 392 -195C 422 -161 447 -104 448 -53C 561 34 680 -183 399 -200Z",[-0.215,0.244]],["M 441 -521L 441 -493L 835 -493L 835 -521Z",[-0.806,0.021]],["M 441 -407L 441 -379L 835 -379L 835 -407Z",[-0.927,0.008]],["M 673 -317L 673 -59C 673 -49 669 -45 657 -45C 639 -45 551 -50 551 -50L 551 -37C 596 -29 613 -15 627 3C 641 22 645 50 647 90C 784 78 803 33 803 -54L 803 -278C 824 -281 834 -289 836 -304Z",[0.096,0.565]],["M 564 -853L 564 -281L 587 -281C 640 -281 701 -309 701 -322L 701 -809C 729 -814 736 -824 738 -838Z",[0.01,0.759]],["M 731 -842L 723 -836C 743 -818 761 -782 761 -749C 856 -682 955 -857 731 -842Z",[0.323,0.583]],["M 779 -631L 779 -298L 803 -298C 849 -298 913 -327 914 -336L 914 -587C 931 -590 941 -598 946 -604L 828 -692L 770 -631Z",[0.048,0.565]]],"bbox":{"top":-857,"bottom":95,"left":21,"right":986},"hadv":1000}],"text":"博","hadv":1000,"breakAfter":true},{"chars":[{"char":"春","components":[["M 579 -823L 376 -857C 358 -622 287 -344 16 -158L 23 -150C 377 -279 493 -528 540 -797C 565 -798 576 -808 579 -823Z",[0.363,0.681]],["M 833 -550L 758 -456L 36 -456L 44 -428L 941 -428C 956 -428 968 -433 970 -444C 919 -487 833 -550 833 -550Z",[0.888,0.039]],["M 799 -808L 727 -717L 75 -717L 83 -689L 901 -689C 916 -689 927 -694 930 -705C 881 -747 799 -808 799 -808Z",[0.797,0.045]],["M 740 -672L 673 -588L 114 -588L 122 -560L 834 -560C 848 -560 859 -565 862 -576C 816 -615 740 -672 740 -672Z",[0.849,0.046]],["M 391 52L 391 -318L 405 -318L 268 -367L 241 -332L 241 94L 269 94C 346 94 391 62 391 52Z",[0.0,0.656]],["M 699 -4L 305 -4L 305 24L 699 24Z",[0.929,0.001]],["M 699 -318L 305 -318L 305 -290L 699 -290Z",[-0.949,0.014]],["M 699 -167L 305 -167L 305 -139L 699 -139Z",[-0.964,0.009]],["M 591 -318L 599 -318L 599 90L 627 90C 679 90 754 61 755 52L 755 -276C 769 -279 777 -285 781 -290L 655 -385Z",[0.009,0.629]],["M 668 -453L 654 -441C 701 -319 780 -216 889 -165C 894 -220 929 -265 986 -304L 988 -319C 871 -325 729 -359 668 -453Z",[-0.421,0.237]]],"bbox":{"top":-857,"bottom":94,"left":16,"right":988},"hadv":1000}],"text":"春","hadv":1000,"breakAfter":true},{"chars":[{"char":"节","components":[["M 270 -709L 27 -709L 34 -681L 270 -681L 270 -527L 293 -527C 351 -527 411 -548 411 -562L 411 -681L 588 -681L 588 -533L 611 -533C 672 -533 732 -555 732 -569L 732 -681L 954 -681C 969 -681 980 -686 982 -697C 938 -743 855 -811 855 -811L 783 -709L 732 -709L 732 -825C 757 -829 765 -839 766 -852L 588 -867L 588 -709L 411 -709L 411 -825C 437 -829 445 -839 446 -852L 270 -867Z",[0.573,0.029]],["M 797 -497L 97 -497L 106 -469L 797 -469Z",[0.83,0.01]],["M 523 60L 523 -490L 364 -490L 364 95L 394 95C 476 95 523 68 523 60Z",[0.003,0.735]],["M 711 -497L 722 -497C 717 -311 710 -221 690 -203C 683 -197 676 -195 662 -195C 643 -195 591 -197 560 -200L 559 -190C 600 -179 625 -164 641 -143C 656 -123 659 -89 659 -45C 724 -44 765 -57 798 -82C 851 -122 864 -205 871 -444C 892 -447 904 -454 911 -463L 786 -567Z",[0.146,0.604]]],"bbox":{"top":-867,"bottom":95,"left":27,"right":982},"hadv":1000}],"text":"节","hadv":1000,"breakAfter":true},{"chars":[{"char":"扫","components":[["M 17 -360L 70 -201C 83 -205 94 -217 98 -230C 279 -330 404 -413 480 -469L 477 -479C 291 -426 91 -375 17 -360Z",[0.657,0.289]],["M 371 -717L 308 -615L 30 -615L 38 -587L 453 -587C 468 -587 478 -592 481 -603C 443 -647 371 -717 371 -717Z",[0.777,0.083]],["M 347 -839L 173 -855L 173 -91C 173 -80 168 -74 154 -74C 132 -74 38 -80 38 -80L 38 -66C 86 -56 106 -41 121 -17C 136 7 141 42 144 92C 291 77 310 22 310 -76L 310 -810C 335 -814 345 -824 347 -839Z",[0.036,0.831]],["M 854 -40L 393 -40L 402 -12L 854 -12Z",[-0.939,0.001]],["M 849 -381L 431 -381L 440 -353L 849 -353Z",[-0.922,0.007]],["M 863 -720L 431 -720L 440 -692L 863 -692Z",[0.666,0.025]],["M 775 -720L 784 -720L 784 91L 809 91C 863 91 932 58 933 48L 933 -676C 948 -679 957 -686 962 -692L 841 -790Z",[0.008,0.791]]],"bbox":{"top":-855,"bottom":92,"left":17,"right":962},"hadv":1000}],"text":"扫","hadv":1000,"breakAfter":true},{"chars":[{"char":"除","components":[["M 69 -777L 69 96L 94 96C 163 96 204 63 204 53L 204 -777L 218 -777L 69 -832Z",[-0.001,0.85]],["M 126 -777L 126 -749L 334 -749L 334 -777Z",[0.409,0.022]],["M 271 -777C 265 -700 242 -560 224 -485C 261 -424 274 -346 274 -280C 274 -253 267 -237 256 -230C 250 -226 244 -225 235 -225C 228 -225 205 -225 192 -225L 192 -213C 213 -207 226 -196 233 -184C 241 -166 246 -114 246 -75C 362 -76 399 -142 399 -240C 399 -323 350 -427 250 -488C 306 -550 373 -650 410 -711C 434 -712 447 -716 455 -726L 327 -843L 259 -777Z",[0.027,0.809]],["M 451 -296C 434 -209 382 -82 315 -5L 322 6C 429 -44 530 -138 574 -219C 593 -217 602 -220 606 -230Z",[0.379,0.502]],["M 694 -777C 725 -649 801 -550 895 -487C 902 -545 936 -604 993 -623L 993 -636C 898 -658 763 -697 705 -787C 736 -790 746 -797 749 -809L 560 -852C 540 -737 435 -562 326 -461L 332 -453C 477 -520 627 -642 694 -777Z",[-0.454,0.018]],["M 383 -372L 391 -344L 938 -344C 952 -344 963 -349 966 -360C 924 -400 851 -460 851 -460L 787 -372Z",[0.879,0.063]],["M 466 -526L 474 -498L 840 -498C 854 -498 865 -503 868 -514C 824 -552 752 -605 752 -605L 688 -526Z",[0.93,0.066]],["M 593 -526L 593 -64C 593 -54 589 -47 575 -47C 557 -47 482 -52 482 -52L 482 -39C 526 -31 543 -16 554 2C 566 21 569 52 571 94C 708 84 728 26 728 -61L 728 -526Z",[0.049,0.739]],["M 757 -284L 748 -279C 788 -209 832 -117 845 -33C 971 69 1086 -182 757 -284Z",[-0.257,0.41]]],"bbox":{"top":-852,"bottom":96,"left":69,"right":1086},"hadv":1000}],"text":"除","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>自从去年十一月从美国回来以后，一直没有什么时间收拾东西，甚至旅行箱还原样摆在地上。今天花了半天时间打扫屋子，拆了两包马拉松的物资包，竟然发现了好多小零嘴，很开心。最大的成就是把吃灰的扫地机器人插上电了，这样过年期间我可以躺平然后看他四处乱跑，也算是有小宠物陪着过春节了。</p>\n<p>然而赛博空间的各个东西也需要收拾，每年总是都忘记一些东西然后发生巨大倒闭事件（例如邮箱挂了大半年），因此今年做一个记录，用作以后参考。</p>\n<h2>域名和服务器续费</h2>\n<p>有两个服务器是年付的没有开自动续费，需要手动续一下，看银行卡余额很疼。主要是把主域名从新网挪到腾讯云了，原因是腾讯云现在加了 plus 的注册，而新网一直不支持 plus 域的 DNSSEC。本来还想多写写新网有多糟糕，后来仔细看了一看，只是系统太老旧了。工作人员大过年半夜还在回工单，十分辛苦。</p>\n<p>好消息是 Transfer 以后有了 DNSSEC，就可以把 SSH server fingerprints 放到 DNS 里了，Trust anchor 现在落到了根域的 DNSSEC 上面，<del>把底裤都交出去了</del>。之后也许研究一些灵车 DNS as PKI，有了 DNSSEC 会更心里有底一点。</p>\n<h2>DNSSEC 更新 DSK</h2>\n<p>去年就让域名的 DNSSEC 过期了半年，但是竟然什么事情都没有发生！这也反应了 DNSSEC 的部署现状把…</p>\n<h2>PGP Key 修改过期时间</h2>\n<p>其实根本没有人一起用 PGP 通信，我的 PGP enc key 在 Yubikey 里面，还在上述的行李箱里呢。不过无论如何，Password store 的 key 是每天都要用的，所以一起更新了。</p>\n<h2>把 Beancount 整理了一下</h2>\n<p>去年电脑大爆炸，一修修了一个半月，因此 Beancount 暂停了半年没有维护。考虑到每次不记账就快速逼近破产，这两天重新把去年所有的账单都导入进去了。今年有机会写一下我的 Beancount 配置把…</p>\n<p>Also，我给 FANBOX 打了快两万块钱了…Subscription 害人</p>\n<h2>检查邮箱还是工作的</h2>\n<p>之前邮箱整天挂的主要原因是 Dovecot 用的 LE 的证书，但是 LE renew 之后默认是 root:root 640 的，所以 Dovecot 就读不出来了。现在写了个 inotify -&gt; setfacl 给 dovecot 权限读证书，目前暂时工作。感觉之后需要设置一个定时发送邮件的功能，这样邮箱挂了可以第一时间知道。现在我都不敢用我的这个邮箱去注册邮件列表。</p>\n<hr />\n<p>以上是所有这两天完成的赛博灵车扫除工作，新年新气象，但灵车运行状态还是勉勉强强，不过至少不是爆炸，所以应该算是好消息把！祝大家新年快乐，希望明年即使灵车爆炸也可以有好看的烟花，可以和大家分享。</p>\n","plain":"自从去年十一月从美国回来以后，一直没有什么时间收拾东西，甚至旅行箱还原样摆在地上。今天花了半天时间打扫屋子，拆了两包马拉松的物资包，竟然发现了好多小零嘴，很开心。最大的成就是把吃灰的扫地机器人插上电了，这样过年期间我可以躺平然后看他四处乱跑，也算是有小宠物陪着过春节了。\n然而赛博空间的各个东西也需要收拾，每年总是都忘记一些东西然后发生巨大倒闭事件（例如邮箱挂了大半年），因此今年做一个记录，用作以后参考。\n\n域名和服务器续费\n有两个服务器是年付的没有开自动续费，需要手动续一下，看银行卡余额很疼。主要是把主域名从新网挪到腾讯云了，原因是腾讯云现在加了 plus 的注册，而新网一直不支持 plus 域的 DNSSEC。本来还想多写写新网有多糟糕，后来仔细看了一看，只是系统太老旧了。工作人员大过年半夜还在回工单，十分辛苦。\n好消息是 Transfer 以后有了 DNSSEC，就可以把 SSH server fingerprints 放到 DNS 里了，Trust anchor 现在落到了根域的 DNSSEC 上面，把底裤都交出去了。之后也许研究一些灵车 DNS as PKI，有了 DNSSEC 会更心里有底一点。\n\nDNSSEC 更新 DSK\n去年就让域名的 DNSSEC 过期了半年，但是竟然什么事情都没有发生！这也反应了 DNSSEC 的部署现状把…\n\nPGP Key 修改过期时间\n其实根本没有人一起用 PGP 通信，我的 PGP enc key 在 Yubikey 里面，还在上述的行李箱里呢。不过无论如何，Password store 的 key 是每天都要用的，所以一起更新了。\n\n把 Beancount 整理了一下\n去年电脑大爆炸，一修修了一个半月，因此 Beancount 暂停了半年没有维护。考虑到每次不记账就快速逼近破产，这两天重新把去年所有的账单都导入进去了。今年有机会写一下我的 Beancount 配置把…\nAlso，我给 FANBOX 打了快两万块钱了…Subscription 害人\n\n检查邮箱还是工作的\n之前邮箱整天挂的主要原因是 Dovecot 用的 LE 的证书，但是 LE renew 之后默认是 root:root 640 的，所以 Dovecot 就读不出来了。现在写了个 inotify -> setfacl 给 dovecot 权限读证书，目前暂时工作。感觉之后需要设置一个定时发送邮件的功能，这样邮箱挂了可以第一时间知道。现在我都不敢用我的这个邮箱去注册邮件列表。\n---\n以上是所有这两天完成的赛博灵车扫除工作，新年新气象，但灵车运行状态还是勉勉强强，不过至少不是爆炸，所以应该算是好消息把！祝大家新年快乐，希望明年即使灵车爆炸也可以有好看的烟花，可以和大家分享。\n"},{"metadata":{"id":"c-ptr-cast","lang":"zh-CN","title":"When is C pointer casting sound?","tags":["胡说八道"],"publish_time":"2025-01-15T04:37:34.424Z","update_time":"2025-01-15T04:46:37.048Z","title_outline":{"groups":[{"chars":[{"char":"W","components":[["M 9 -713L 161 -698L 196 -698L 347 -713L 347 -747L 9 -747Z",[-0.785,0.009]],["M 284 2L 377 2L 550 -576L 554 -590L 534 -590L 713 2L 806 2L 1030 -747L 972 -747L 811 -157L 808 -140L 826 -140L 655 -747L 553 -747L 385 -160L 381 -145L 399 -145L 244 -747L 63 -747Z",[-0.209,0.055]],["M 446 -713L 572 -698L 637 -698L 774 -713L 774 -747L 446 -747Z",[-0.673,0.043]],["M 867 -713L 973 -698L 1002 -698L 1108 -713L 1108 -747L 867 -747Z",[-0.544,0.089]]],"bbox":{"top":-747,"bottom":2,"left":9,"right":1108},"hadv":1111},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"When","hadv":3094,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"is","hadv":870,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708}],"text":"C","hadv":708,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"pointer","hadv":3893,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612}],"text":"casting","hadv":3763,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"sound","hadv":3210,"breakAfter":false},{"chars":[{"char":"?","components":[["M 431 -522C 431 -657 262 -742 154 -769C 112 -758 90 -736 90 -695C 90 -656 113 -627 177 -619L 401 -587L 306 -657C 355 -622 374 -596 375 -561C 376 -521 356 -506 296 -484L 225 -462C 164 -440 139 -415 139 -369C 139 -348 146 -325 159 -289L 172 -248L 204 -248L 206 -288C 211 -316 222 -325 267 -344L 320 -364C 398 -393 431 -435 431 -522Z",[-0.054,0.383]],["M 189 16C 245 16 286 -25 286 -78C 286 -130 245 -172 189 -172C 136 -172 93 -130 93 -78C 93 -25 136 16 189 16Z",[0.026,-0.0]]],"bbox":{"top":-769,"bottom":16,"left":90,"right":431},"hadv":494}],"text":"?","hadv":494,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>新标签：胡说八道 = 有 99% 的可能性有错 = 今天工科猪喵喵又和群友学了什么</p>\n<!--\n<style>\n  code {\n    margin: -5px 0;\n  border-left: none;\n  filter: grayscale(1);\n  }\n</style>\n-->\n<hr />\n<p><del>今天</del>前几天跟 <a href=\"https://sharzy.in\">@Sharzy</a> 和 <a href=\"https://t.me/lancern_chest\">@Lancern</a> 学了 C 语言的指针转换什么时候是安全的。具体而言，<code>X *</code> 可以 By-value 转换为 <code>Y *</code>（其实就是一个 X 类型的 lvalue 可以当成一个 Y 类型的 lvalue），当且仅当：</p>\n<blockquote>\n<p>存在一个类型 T（自身可能是指针），自然数 N（可能是 0）：</p>\n<ul>\n<li><code>X = T (N 个 * 或者 *const)</code></li>\n<li><code>Y = T' (N 个 *const)</code></li>\n</ul>\n<p>其中 <code>T' = T or const T</code></p>\n</blockquote>\n<p>因此以下转换是安全的：</p>\n<div class=\"highlighted highlighted-c\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-c\"><span style=\"color:#839496;\">T </span><span style=\"color:#859900;\">* </span><span style=\"color:#839496;\">-&gt; T </span><span style=\"color:#859900;\">*\n</span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">* </span><span style=\"color:#839496;\">-&gt; </span><span style=\"color:#93a1a1;\">const </span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">*\n</span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">** </span><span style=\"color:#839496;\">-&gt; </span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">*</span><span style=\"color:#93a1a1;\">const </span><span style=\"color:#859900;\">* </span><span style=\"color:#839496;\">-&gt; </span><span style=\"color:#93a1a1;\">const </span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">*</span><span style=\"color:#93a1a1;\">const </span><span style=\"color:#859900;\">*\n</span></code></pre>\n</div>\n<p>以下转换是不安全的：</p>\n<div class=\"highlighted highlighted-C\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-C\"><span style=\"color:#93a1a1;\">const </span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">* </span><span style=\"color:#839496;\">-&gt; </span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">*\n</span><span style=\"color:#586e75;\">// 允许修改 const char\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">** </span><span style=\"color:#839496;\">-&gt; </span><span style=\"color:#93a1a1;\">const </span><span style=\"color:#268bd2;\">char </span><span style=\"color:#859900;\">**\n</span><span style=\"color:#586e75;\">// 允许将一个 const char * transmute 到 char *，然后和上面那个一样允许修改 const char\n</span></code></pre>\n</div>\n<p>其中最后一个例子是去找群友学习的动机。如果只把例子列出来看上去很像函数的负类型上的 contravariance，但是由于指针既能读又能写，事实上更接近 Invariant（写的那一半是 Contravariant 的，读的那一半是 Covariant 的）。作为工科猪喵喵对上述规则的理解方式如下：</p>\n<p>从想允许的行为考虑，以 <code>X -&gt; Y</code> 表示 X 的 lvalue 可以当成 Y 的 lvalue 用，这个关系可以以以下方式生成：</p>\n<pre><code>T type\n--------------------\nT -&gt; T, T -&gt; const T\n\nX, Y type, X -&gt; Y\n--------------------\nX * -&gt; Y *const\n\nX, Y type, X -&gt; Y\n--------------------\nX *const -&gt; Y *const\n</code></pre>\n<p>这几条规则分别来自于：</p>\n<ol>\n<li>类型不变或者加个 const 是安全的</li>\n<li>如果 X 类型的 lvalue 可以被安全地当成 Y 类型的 lvalue 用，那么 X 类型的指针变成 Y 类型的 <strong>const</strong> 指针，后者只允许读，一定是安全的。</li>\n<li>和 2 类似，但是 X 的 lvalue 也只读，这也是安全的。由于转换后是 <strong>const</strong> 指针，因此这个 lvalue 也不会被覆写，因此 <strong>const</strong> 保证也被保留。</li>\n</ol>\n<p>可以注意到上面这几条规则生成的和本文开头的规则一致。</p>\n<hr />\n<p>从想禁止的行为考虑，剥掉最外面一层指针考虑 lvalue，希望避免把一个不可写的 lvalue 当成一个可写的 lvalue。这件事情会发生当且仅当在剩下的可能很多层的指针中，有相邻的几层形如（以下也是讨论 lvalue 的类型，<code>*const?</code> 表示 <code>*const</code> 或者 <code>*</code>）：</p>\n<ol start=\"0\">\n<li><code>const A -&gt; B</code> （const 直接丢失）</li>\n<li><code>A * -&gt; const B *</code> （允许将 <code>const B *</code> 写到一个 <code>A *</code> lvalue 里，一次解引用后让 <code>const B</code> 变成了 <code>A</code>）</li>\n<li><code>A *const *</code> -&gt; <code>const B *const *</code> （允许将 <code>const B *const *</code> 写到一个 <code>A *const *</code> 的 lvalue 里，两次解引用后让 <code>const B</code> 变成了 <code>A</code>）</li>\n<li><code>A *const *const * -&gt; const B *const *const *</code> （同上，三次解引用）</li>\n<li>…</li>\n</ol>\n<p>给定原始类型，这些禁止规则的补也正好生成了本文开头的目标类型集合：</p>\n<p>考虑转换前后类型 const-qualifier 不同的最内层，假设是第 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>k</mi><mn>0</mn></msub></mrow><annotation encoding=\"application/x-tex\">k_0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">0</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 层。那么 <code>T</code> 正好就是这最内 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>k</mi><mn>0</mn></msub></mrow><annotation encoding=\"application/x-tex\">k_0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">0</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 层。对于任意 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>k</mi><mo>&gt;</mo><msub><mi>k</mi><mn>0</mn></msub></mrow><annotation encoding=\"application/x-tex\">k &gt; k_0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7335em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">&gt;</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8444em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em;\"><span style=\"top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">0</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 可以归纳证明被转换到的类型中第 <code>k</code> 层一定带 const。</p>\n<ul>\n<li>如果第 k 层 const-qualifier 不同，那么根据规则 0，一定是转换前 non-const，转换后 const</li>\n<li>如果 const-qualifier 相同，考虑 <code>A = { j &lt; k | 第 j 层转换前后不同 }</code>。A 非空，取 A 最大值 <code>k'</code>，归纳假设说明 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>j</mi><mo>∈</mo><mo stretchy=\"false\">(</mo><msup><mi>k</mi><mo mathvariant=\"normal\" lspace=\"0em\" rspace=\"0em\">′</mo></msup><mo separator=\"true\">,</mo><mi>k</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">j \\in (k&#x27;, k)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0019em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7519em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">′</span></span></span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mclose\">)</span></span></span></span> 内每一层转换后都是 const。然后使用规则 (k - k’)。</li>\n</ul>\n","plain":"新标签：胡说八道 = 有 99% 的可能性有错 = 今天工科猪喵喵又和群友学了什么\n---\n今天前几天跟 @Sharzy 和 @Lancern 学了 C 语言的指针转换什么时候是安全的。具体而言，X * 可以 By-value 转换为 Y *（其实就是一个 X 类型的 lvalue 可以当成一个 Y 类型的 lvalue），当且仅当：\n存在一个类型 T（自身可能是指针），自然数 N（可能是 0）：\n- X = T (N 个 * 或者 *const)\n- Y = T' (N 个 *const)\n其中 T' = T or const T\n\n因此以下转换是安全的：\nT * -> T *\nchar * -> const char *\nchar ** -> char *const * -> const char *const *\n\n以下转换是不安全的：\nconst char * -> char *\n// 允许修改 const char\n\nchar ** -> const char **\n// 允许将一个 const char * transmute 到 char *，然后和上面那个一样允许修改 const char\n\n其中最后一个例子是去找群友学习的动机。如果只把例子列出来看上去很像函数的负类型上的 contravariance，但是由于指针既能读又能写，事实上更接近 Invariant（写的那一半是 Contravariant 的，读的那一半是 Covariant 的）。作为工科猪喵喵对上述规则的理解方式如下：\n从想允许的行为考虑，以 X -> Y 表示 X 的 lvalue 可以当成 Y 的 lvalue 用，这个关系可以以以下方式生成：\nT type\n--------------------\nT -> T, T -> const T\n\nX, Y type, X -> Y\n--------------------\nX * -> Y *const\n\nX, Y type, X -> Y\n--------------------\nX *const -> Y *const\n\n这几条规则分别来自于：\n- 类型不变或者加个 const 是安全的\n- 如果 X 类型的 lvalue 可以被安全地当成 Y 类型的 lvalue 用，那么 X 类型的指针变成 Y 类型的 const 指针，后者只允许读，一定是安全的。\n- 和 2 类似，但是 X 的 lvalue 也只读，这也是安全的。由于转换后是 const 指针，因此这个 lvalue 也不会被覆写，因此 const 保证也被保留。\n可以注意到上面这几条规则生成的和本文开头的规则一致。\n---\n从想禁止的行为考虑，剥掉最外面一层指针考虑 lvalue，希望避免把一个不可写的 lvalue 当成一个可写的 lvalue。这件事情会发生当且仅当在剩下的可能很多层的指针中，有相邻的几层形如（以下也是讨论 lvalue 的类型，*const? 表示 *const 或者 *）：\n- const A -> B （const 直接丢失）\n- A * -> const B * （允许将 const B * 写到一个 A * lvalue 里，一次解引用后让 const B 变成了 A）\n- A *const * -> const B *const * （允许将 const B *const * 写到一个 A *const * 的 lvalue 里，两次解引用后让 const B 变成了 A）\n- A *const *const * -> const B *const *const * （同上，三次解引用）\n- …\n给定原始类型，这些禁止规则的补也正好生成了本文开头的目标类型集合：\n考虑转换前后类型 const-qualifier 不同的最内层，假设是第 k_0 层。那么 T 正好就是这最内 k_0 层。对于任意 k > k_0 可以归纳证明被转换到的类型中第 k 层一定带 const。\n- 如果第 k 层 const-qualifier 不同，那么根据规则 0，一定是转换前 non-const，转换后 const\n- 如果 const-qualifier 相同，考虑 A = { j < k | 第 j 层转换前后不同 }。A 非空，取 A 最大值 k'，归纳假设说明 j \\in (k', k) 内每一层转换后都是 const。然后使用规则 (k - k’)。\n"},{"metadata":{"id":"lean4-heq-notes","lang":"zh-CN","title":"Notes about HEq in Lean4 (Part 1?)","tags":["摸鱼","TT"],"publish_time":"2025-01-07T04:44:22.397Z","update_time":"2025-01-15T04:56:26.371Z","title_outline":{"groups":[{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Notes","hadv":2966,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"about","hadv":3022,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"H","components":[["M 41 -0L 387 -0L 387 -34L 227 -50L 196 -50L 41 -34Z",[-0.865,0.0]],["M 41 -713L 196 -698L 227 -698L 387 -713L 387 -747L 41 -747Z",[-0.504,0.014]],["M 128 -0L 305 -0C 301 -117 301 -235 301 -365L 301 -395C 301 -514 301 -632 305 -747L 128 -747C 131 -630 131 -513 131 -395L 131 -351C 131 -232 131 -114 128 -0Z",[0.0,0.771]],["M 216 -361L 654 -361L 654 -399L 216 -399Z",[-0.931,0.006]],["M 482 -0L 829 -0L 829 -34L 671 -50L 641 -50L 482 -34Z",[-0.863,0.002]],["M 482 -713L 641 -698L 671 -698L 829 -713L 829 -747L 482 -747Z",[-0.608,0.05]],["M 565 -0L 742 -0C 739 -117 739 -235 739 -351L 739 -395C 739 -514 739 -632 742 -747L 565 -747C 569 -630 569 -513 569 -395L 569 -365C 569 -232 569 -114 565 -0Z",[-0.001,0.77]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":829},"hadv":870},{"char":"E","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 634 -0L 632 -207L 576 -207L 519 -1L 605 -39L 218 -39Z",[0.604,0.185]],["M 218 -363L 467 -363L 467 -399L 218 -399Z",[-0.86,0.001]],["M 554 -548L 612 -548L 613 -747L 218 -747L 218 -708L 583 -708L 499 -747Z",[-0.58,0.193]],["M 454 -263L 504 -263L 504 -505L 454 -505L 438 -395L 438 -374Z",[0.007,0.742]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":634},"hadv":674},{"char":"q","components":[["M 261 17C 335 17 400 -16 448 -84L 455 -84L 440 -95C 408 -66 380 -54 343 -54C 264 -54 208 -109 208 -270C 208 -434 264 -494 342 -494C 377 -494 409 -482 442 -450L 460 -461L 455 -465C 416 -530 356 -563 289 -563C 146 -563 35 -450 35 -267C 35 -86 133 17 261 17Z",[0.019,0.474]],["M 344 259L 646 259L 646 230L 544 219L 444 219L 344 230Z",[0.875,0.002]],["M 420 259L 586 259C 583 180 582 101 582 22L 582 -398L 586 -552L 571 -561L 420 -478L 420 -77L 424 -63L 424 22C 424 101 423 180 420 259Z",[0.007,0.803]]],"bbox":{"top":-563,"bottom":259,"left":35,"right":646},"hadv":657}],"text":"HEq","hadv":2201,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"in","hadv":1055,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"L","components":[["M 41 -0L 218 -0L 219 -50L 202 -50L 42 -34Z",[0.751,0.04]],["M 41 -713L 202 -698L 240 -698L 403 -713L 403 -747L 41 -747Z",[-0.878,0.008]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -346L 303 -411C 303 -514 303 -632 306 -747L 130 -747C 133 -631 133 -513 133 -395L 133 -324C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 619 -0L 617 -224L 562 -224L 503 -2L 588 -39L 219 -39Z",[0.547,0.208]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":619},"hadv":651},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"4","components":[["M 333 15L 476 15L 476 -760L 364 -760L 33 -253L 33 -169L 585 -169L 585 -273L 82 -273L 82 -292L 71 -248L 220 -478L 350 -679L 315 -670L 333 -670L 333 -203Z",[0.026,0.399]]],"bbox":{"top":-760,"bottom":15,"left":33,"right":585},"hadv":612}],"text":"Lean4","hadv":3145,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"(","components":[["M 206 -315C 206 -504 242 -638 376 -803L 352 -825C 180 -684 86 -529 86 -315C 86 -101 180 53 352 195L 376 173C 249 12 206 -126 206 -315Z",[-0.002,0.755]]],"bbox":{"top":-825,"bottom":195,"left":86,"right":376},"hadv":418}],"text":"(","hadv":418,"breakAfter":false},{"chars":[{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Part","hadv":2215,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463}],"text":"1","hadv":463,"breakAfter":false},{"chars":[{"char":"?","components":[["M 431 -522C 431 -657 262 -742 154 -769C 112 -758 90 -736 90 -695C 90 -656 113 -627 177 -619L 401 -587L 306 -657C 355 -622 374 -596 375 -561C 376 -521 356 -506 296 -484L 225 -462C 164 -440 139 -415 139 -369C 139 -348 146 -325 159 -289L 172 -248L 204 -248L 206 -288C 211 -316 222 -325 267 -344L 320 -364C 398 -393 431 -435 431 -522Z",[-0.054,0.383]],["M 189 16C 245 16 286 -25 286 -78C 286 -130 245 -172 189 -172C 136 -172 93 -130 93 -78C 93 -25 136 16 189 16Z",[0.026,-0.0]]],"bbox":{"top":-769,"bottom":16,"left":90,"right":431},"hadv":494}],"text":"?","hadv":494,"breakAfter":false},{"chars":[{"char":")","components":[["M 212 -315C 212 -126 176 8 42 173L 66 195C 238 54 332 -101 332 -315C 332 -529 238 -683 66 -825L 42 -803C 169 -642 212 -504 212 -315Z",[-0.001,0.755]]],"bbox":{"top":-825,"bottom":195,"left":42,"right":332},"hadv":418}],"text":")","hadv":418,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>Edit TL;DR: Lean4 有 Definitional proof irrelevance，所以本篇内容纯瞎搞。不过还有一部分没瞎搞的，所以留着。</p>\n<hr />\n<p>上上次被 Heterogeneous identity 创还是<a href=\"https://proofassistants.stackexchange.com/questions/2694/does-equality-in-sigma-x-x-x-x-implies-uip\">上上次</a>。上次被 JMeq 创过一次后就想着迟早写点 Notes 给自己看以防下次被创，结果消极怠工然后又被创了，hence this note.</p>\n<p>Apparently 在 Lean4 里可以直接证明 UIP，不需要使用任何公理（Quot 那些东西），十分纯净：</p>\n<div class=\"highlighted highlighted-lean4\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-lean4\"><span style=\"color:#859900;\">theorem </span><span style=\"color:#b58900;\">pair_inj2 </span><span style=\"color:#839496;\">{A : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} {B : A -&gt; </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> v} (x y : (a : A) ×&#39; B a)\n</span><span style=\"color:#839496;\">  : x = y -&gt; HEq x.snd y.snd := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> { intro Heq; rw [Heq] }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">theorem </span><span style=\"color:#b58900;\">pair_eq </span><span style=\"color:#839496;\">{A : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} (base : A) (l : base = base)\n</span><span style=\"color:#839496;\">  : @Eq ((a : A) ×&#39; (a = a)) (PSigma.mk base l) (PSigma.mk base (Eq.refl base)) := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> { cases l; rfl }\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">theorem </span><span style=\"color:#b58900;\">UIP </span><span style=\"color:#839496;\">{A : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} (base : A) (l : base = base) : l = Eq.refl base := </span><span style=\"color:#859900;\">by</span><span style=\"color:#839496;\"> {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">let</span><span style=\"color:#839496;\"> Hpeq := pair_eq base l\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">let</span><span style=\"color:#839496;\"> Heq : HEq l (Eq.refl base) := @pair_inj2 A (</span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> x =&gt; x = x) (PSigma.mk base l) (PSigma.mk base (Eq.refl base)) Hpeq\n</span><span style=\"color:#839496;\">  exact eq_of_heq Heq\n</span><span style=\"color:#839496;\">}\n</span></code></pre>\n</div>\n<p>这非常神秘。</p>\n<p>HEq 就是 Coq 里面的 <a href=\"https://coq.inria.fr/doc/v8.9/stdlib/Coq.Logic.JMeq.html\">JMeq</a>，一个广为人知的性质是如果有 <code>JMeq -&gt; Eq</code> 那么 <code>K</code>（来源找不到了，G）。在 HoTT 的框架内其实可以把这种 Heterogeneous identity 理解成 Identity of pointed-types <code>{ A : Type &amp; A }</code> <super>[1]</super> (把 Pointed-types 理解成 Fibration over <code>Type</code> 或者无论什么 base space，现在 Path 可以在整个 Fibration 上跑了)。可以看到其实 <code>JMeq -&gt; Eq</code> 其实就是 Injectivity of dependent pair 的一个特殊情况。事实上，这两者是等价的：</p>\n<div class=\"highlighted highlighted-coq\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-coq\"><span style=\"color:#859900;\">Inductive </span><span style=\"color:#b58900;\">HEq</span><span style=\"color:#839496;\"> {</span><span style=\"color:#268bd2;\">A </span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">Type</span><span style=\"background-color:#6e2e32;color:#839496;\">}</span><span style=\"color:#839496;\"> : </span><span style=\"color:#268bd2;\">A </span><span style=\"color:#859900;\">-&gt; forall</span><span style=\"color:#839496;\"> {</span><span style=\"color:#268bd2;\">B</span><span style=\"background-color:#6e2e32;color:#839496;\">}</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">B </span><span style=\"color:#859900;\">-&gt; Prop :=\n</span><span style=\"color:#859900;\">| </span><span style=\"color:#b58900;\">HEq_refl </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">a </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A</span><span style=\"color:#657b83;\">) </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">HEq a a\n</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">Definition </span><span style=\"color:#b58900;\">Thm_HEq_eq</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">Prop := forall </span><span style=\"color:#268bd2;\">A </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">a b </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">HEq a b </span><span style=\"color:#859900;\">-&gt; </span><span style=\"color:#268bd2;\">a </span><span style=\"color:#859900;\">= </span><span style=\"color:#268bd2;\">b</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#859900;\">Definition </span><span style=\"color:#b58900;\">Thm_pair_inj2 </span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">Prop := forall </span><span style=\"color:#268bd2;\">A </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">B </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A </span><span style=\"color:#859900;\">-&gt; Type</span><span style=\"color:#657b83;\">) (</span><span style=\"color:#268bd2;\">bp </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A</span><span style=\"color:#657b83;\">) (</span><span style=\"color:#268bd2;\">x y </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">B bp</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">existT B bp x </span><span style=\"color:#859900;\">= </span><span style=\"color:#268bd2;\">existT B bp y </span><span style=\"color:#859900;\">-&gt; </span><span style=\"color:#268bd2;\">x </span><span style=\"color:#859900;\">= </span><span style=\"color:#268bd2;\">y</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">Theorem </span><span style=\"color:#b58900;\">Thm_pair_inj2_implies_Thm_HEq_eq </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">Thm_pair_inj2 </span><span style=\"color:#859900;\">-&gt; </span><span style=\"color:#268bd2;\">Thm_HEq_eq</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#859900;\">Proof</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">intros </span><span style=\"color:#268bd2;\">pair_inj2 A a b Heq_ab</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">inversion </span><span style=\"color:#268bd2;\">Heq_ab</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">apply </span><span style=\"color:#268bd2;\">pair_inj2 </span><span style=\"color:#859900;\">in </span><span style=\"color:#268bd2;\">H2</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">exact </span><span style=\"color:#268bd2;\">H2</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#859900;\">Qed</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">Lemma </span><span style=\"color:#b58900;\">HEq_lift</span><span style=\"color:#839496;\"> {</span><span style=\"color:#268bd2;\">A </span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">Type</span><span style=\"background-color:#6e2e32;color:#839496;\">}</span><span style=\"color:#839496;\"> </span><span style=\"color:#657b83;\">{</span><span style=\"color:#268bd2;\">B </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A </span><span style=\"color:#859900;\">-&gt; Type</span><span style=\"color:#657b83;\">} (</span><span style=\"color:#268bd2;\">f </span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">forall </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">a </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">B a</span><span style=\"color:#657b83;\">) </span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">forall </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">a b </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">a </span><span style=\"color:#859900;\">= </span><span style=\"color:#268bd2;\">b </span><span style=\"color:#859900;\">-&gt; </span><span style=\"color:#268bd2;\">HEq </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">f a</span><span style=\"color:#657b83;\">) (</span><span style=\"color:#268bd2;\">f b</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#859900;\">Proof</span><span style=\"color:#839496;\">.  </span><span style=\"color:#859900;\">intros </span><span style=\"color:#268bd2;\">a b Heq</span><span style=\"color:#839496;\">.  </span><span style=\"color:#859900;\">case </span><span style=\"color:#268bd2;\">Heq</span><span style=\"color:#839496;\">. </span><span style=\"color:#859900;\">apply </span><span style=\"color:#268bd2;\">HEq_refl</span><span style=\"color:#839496;\">.  </span><span style=\"color:#859900;\">Qed</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">Definition </span><span style=\"color:#b58900;\">pair_inj2_weak</span><span style=\"color:#839496;\"> {</span><span style=\"color:#268bd2;\">A</span><span style=\"background-color:#6e2e32;color:#839496;\">}</span><span style=\"color:#839496;\"> </span><span style=\"color:#657b83;\">{</span><span style=\"color:#268bd2;\">B </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">A </span><span style=\"color:#859900;\">-&gt; Type</span><span style=\"color:#657b83;\">} {</span><span style=\"color:#268bd2;\">p1 p2 </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">sigT B</span><span style=\"color:#657b83;\">} </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">p1 </span><span style=\"color:#859900;\">= </span><span style=\"color:#268bd2;\">p2 </span><span style=\"color:#859900;\">-&gt; </span><span style=\"color:#268bd2;\">HEq </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">projT2 p1</span><span style=\"color:#657b83;\">) (</span><span style=\"color:#268bd2;\">projT2 p2</span><span style=\"color:#657b83;\">)\n</span><span style=\"color:#839496;\"> </span><span style=\"color:#859900;\">:= </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">HEq_lift </span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">fun </span><span style=\"color:#268bd2;\">x </span><span style=\"color:#859900;\">=&gt; </span><span style=\"color:#268bd2;\">projT2 x</span><span style=\"color:#657b83;\">) </span><span style=\"color:#268bd2;\">p1 p2</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">Theorem </span><span style=\"color:#b58900;\">Thm_HEq_eq_implies_Thm_pair_inj2 </span><span style=\"color:#839496;\">: </span><span style=\"color:#268bd2;\">Thm_HEq_eq </span><span style=\"color:#859900;\">-&gt; </span><span style=\"color:#268bd2;\">Thm_pair_inj2</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#859900;\">Proof</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">intros </span><span style=\"color:#268bd2;\">HEq_eq A B bp x y Heq_xy</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">exact </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">HEq_eq </span><span style=\"color:#859900;\">_ _ _ </span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">pair_inj2_weak Heq_xy</span><span style=\"color:#657b83;\">))</span><span style=\"color:#839496;\">.\n</span><span style=\"color:#859900;\">Qed</span><span style=\"color:#839496;\">.\n</span></code></pre>\n</div>\n<p>再加上另一个广为人知的性质 Injectivity of dependent pairs -&gt; UIP <super>[2]</super>，所以只要让 JMeq 和普通的 identity 一样强，那么也可以证出来 UIP。</p>\n<p>因此上述 Lean4 证明中唯一一个比较 Dubious 的地方就是 HEq 和 Eq 的转换，也就是 <a href=\"https://leanprover-community.github.io/mathlib4_docs/Init/Prelude.html#eq_of_heq\"><code>eq_of_heq</code></a> 这个定理，和 <a href=\"https://coq.inria.fr/doc/v8.20/stdlib/Coq.Logic.JMeq.html\">JMeq_eq</a> 一模一样：</p>\n<div class=\"highlighted highlighted-lean4\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-lean4\"><span style=\"color:#859900;\">theorem </span><span style=\"color:#b58900;\">eq_of_heq </span><span style=\"color:#839496;\">{α : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} {a a&#39; : α} (h : HEq a a&#39;) : Eq a a&#39; :=\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> : (α β : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u) → (a : α) → (b : β) → HEq a b → (h : Eq α β) → Eq (cast h a) b :=\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> _ _ _ _ h₁ =&gt;\n</span><span style=\"color:#839496;\">      h₁.rec (</span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> _ =&gt; rfl)\n</span><span style=\"color:#839496;\">  this α α a a&#39; h rfl\n</span></code></pre>\n</div>\n<p>使用了 HEq 的 recursion principle，如果我们仔细看这个 recursion principle 的定义，并且把上面那句 <code>h₁.rec (fun _ =&gt; rfl)</code> 展开的话：</p>\n<div class=\"highlighted highlighted-lean4\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-lean4\"><span style=\"color:#839496;\">Heq.rec : {α : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} →\n</span><span style=\"color:#839496;\">  {a : α} →\n</span><span style=\"color:#839496;\">    {motive : {β : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} → (b : β) → HEq a b → </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> v} →\n</span><span style=\"color:#839496;\">      motive a (HEq.refl a) → {β : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} → {b : β} → (t : HEq a b) → motive b t\n</span><span style=\"color:#586e75;\">---\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">have</span><span style=\"color:#839496;\"> : (α β : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u) → (a : α) → (b : β) → HEq a b → (h : Eq α β) → (cast h a) = b :=\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> α β a b =&gt;\n</span><span style=\"color:#839496;\">      @HEq.rec\n</span><span style=\"color:#839496;\">        α a\n</span><span style=\"color:#839496;\">        (</span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> {β} a_1 _ =&gt; (h : α = β) -&gt; (cast h a) = a_1) </span><span style=\"color:#586e75;\">-- motive\n</span><span style=\"color:#839496;\">        (</span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> _ =&gt; rfl) </span><span style=\"color:#586e75;\">-- Should have type motive a _ :== (h : α = β) -&gt; (cast h a) = a ???????\n</span><span style=\"color:#839496;\">        β b\n</span></code></pre>\n</div>\n<p>我的猪脑感觉就根本不应该 Typecheck…</p>\n<p>躺平了，去 Zulip 问一下…</p>\n<hr />\n<p>Edit 01-06:\nApparently Lean4 对于 Pattern Matching 的处理比较神秘：</p>\n<div class=\"highlighted highlighted-lean\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-lean\"><span style=\"color:#859900;\">theorem </span><span style=\"color:#b58900;\">meow </span><span style=\"color:#839496;\">{α : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} (a : α) : (h : α = α) -&gt; (cast h a) = a :=\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> _ =&gt; rfl\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">theorem </span><span style=\"color:#b58900;\">meow_meow </span><span style=\"color:#839496;\">{A : </span><span style=\"color:#268bd2;\">Sort</span><span style=\"color:#839496;\"> u} {a : A} : (i : a = a) -&gt; i = rfl\n</span><span style=\"color:#839496;\">:= </span><span style=\"color:#859900;\">fun</span><span style=\"color:#839496;\"> _ =&gt; rfl\n</span></code></pre>\n</div>\n<p>那能证出来 UIP 一点也不奇怪…那么应该问的问题是：Lean4 的 Pattern matching 到底是怎么处理的呢？</p>\n<hr />\n<p>Edit 01-07:</p>\n<p>在 Zulip 提问了，原来是 Lean 有 Definitional proof irrelevance:</p>\n<p>https://leanprover.zulipchat.com/#narrow/channel/113489-new-members/topic/How.20are.20functions.20taking.20equalities.20type.20checked.3F/near/492251131</p>\n<p>那么一切都不奇怪了（</p>\n<p>我是工科猪.jpg</p>\n<p>相关阅读：LeanTT [3], Definitional proof irrelevance without K [4].</p>\n<p>References</p>\n<ul>\n<li>[1] https://homotopytypetheory.org/2012/11/21/on-heterogeneous-equality/</li>\n<li>[2] https://coq.discourse.group/t/dependent-pair-injectivity-equivalent-to-k</li>\n<li>[3] Mario Carneiro, <a href=\"https://github.com/digama0/lean-type-theory/releases\">The Type Theory of Lean</a>. 2019</li>\n<li>[4] Gaëtan Gilbert, Jesper Cockx, Matthieu Sozeau, and Nicolas Tabareau. 2019. Definitional proof-irrelevance without K. Proc. ACM Program. Lang. 3, POPL, Article 3 (January 2019), 28 pages. https://doi.org/10.1145/3290316</li>\n</ul>\n","plain":"Edit TL;DR: Lean4 有 Definitional proof irrelevance，所以本篇内容纯瞎搞。不过还有一部分没瞎搞的，所以留着。\n---\n上上次被 Heterogeneous identity 创还是上上次。上次被 JMeq 创过一次后就想着迟早写点 Notes 给自己看以防下次被创，结果消极怠工然后又被创了，hence this note.\nApparently 在 Lean4 里可以直接证明 UIP，不需要使用任何公理（Quot 那些东西），十分纯净：\ntheorem pair_inj2 {A : Sort u} {B : A -> Sort v} (x y : (a : A) ×' B a)\n  : x = y -> HEq x.snd y.snd := by { intro Heq; rw [Heq] }\n\ntheorem pair_eq {A : Sort u} (base : A) (l : base = base)\n  : @Eq ((a : A) ×' (a = a)) (PSigma.mk base l) (PSigma.mk base (Eq.refl base)) := by { cases l; rfl }\n\ntheorem UIP {A : Sort u} (base : A) (l : base = base) : l = Eq.refl base := by {\n  let Hpeq := pair_eq base l\n  let Heq : HEq l (Eq.refl base) := @pair_inj2 A (fun x => x = x) (PSigma.mk base l) (PSigma.mk base (Eq.refl base)) Hpeq\n  exact eq_of_heq Heq\n}\n\n这非常神秘。\nHEq 就是 Coq 里面的 JMeq，一个广为人知的性质是如果有 JMeq -> Eq 那么 K（来源找不到了，G）。在 HoTT 的框架内其实可以把这种 Heterogeneous identity 理解成 Identity of pointed-types { A : Type & A } [1] (把 Pointed-types 理解成 Fibration over Type 或者无论什么 base space，现在 Path 可以在整个 Fibration 上跑了)。可以看到其实 JMeq -> Eq 其实就是 Injectivity of dependent pair 的一个特殊情况。事实上，这两者是等价的：\nInductive HEq {A : Type} : A -> forall {B}, B -> Prop :=\n| HEq_refl (a : A) : HEq a a\n.\n\nDefinition Thm_HEq_eq: Prop := forall A (a b : A), HEq a b -> a = b.\nDefinition Thm_pair_inj2 : Prop := forall A (B : A -> Type) (bp : A) (x y : B bp), existT B bp x = existT B bp y -> x = y.\n\nTheorem Thm_pair_inj2_implies_Thm_HEq_eq : Thm_pair_inj2 -> Thm_HEq_eq.\nProof.\n  intros pair_inj2 A a b Heq_ab.\n  inversion Heq_ab.\n  apply pair_inj2 in H2.\n  exact H2.\nQed.\n\nLemma HEq_lift {A : Type} {B : A -> Type} (f : forall (a : A), B a) : forall (a b : A), a = b -> HEq (f a) (f b).\nProof.  intros a b Heq.  case Heq. apply HEq_refl.  Qed.\n\nDefinition pair_inj2_weak {A} {B : A -> Type} {p1 p2 : sigT B} : p1 = p2 -> HEq (projT2 p1) (projT2 p2)\n := (HEq_lift (fun x => projT2 x) p1 p2).\n\nTheorem Thm_HEq_eq_implies_Thm_pair_inj2 : Thm_HEq_eq -> Thm_pair_inj2.\nProof.\n  intros HEq_eq A B bp x y Heq_xy.\n  exact (HEq_eq _ _ _ (pair_inj2_weak Heq_xy)).\nQed.\n\n再加上另一个广为人知的性质 Injectivity of dependent pairs -> UIP [2]，所以只要让 JMeq 和普通的 identity 一样强，那么也可以证出来 UIP。\n因此上述 Lean4 证明中唯一一个比较 Dubious 的地方就是 HEq 和 Eq 的转换，也就是 eq_of_heq 这个定理，和 JMeq_eq 一模一样：\ntheorem eq_of_heq {α : Sort u} {a a' : α} (h : HEq a a') : Eq a a' :=\n  have : (α β : Sort u) → (a : α) → (b : β) → HEq a b → (h : Eq α β) → Eq (cast h a) b :=\n    fun _ _ _ _ h₁ =>\n      h₁.rec (fun _ => rfl)\n  this α α a a' h rfl\n\n使用了 HEq 的 recursion principle，如果我们仔细看这个 recursion principle 的定义，并且把上面那句 h₁.rec (fun _ => rfl) 展开的话：\nHeq.rec : {α : Sort u} →\n  {a : α} →\n    {motive : {β : Sort u} → (b : β) → HEq a b → Sort v} →\n      motive a (HEq.refl a) → {β : Sort u} → {b : β} → (t : HEq a b) → motive b t\n---\n  have : (α β : Sort u) → (a : α) → (b : β) → HEq a b → (h : Eq α β) → (cast h a) = b :=\n    fun α β a b =>\n      @HEq.rec\n        α a\n        (fun {β} a_1 _ => (h : α = β) -> (cast h a) = a_1) -- motive\n        (fun _ => rfl) -- Should have type motive a _ :== (h : α = β) -> (cast h a) = a ???????\n        β b\n\n我的猪脑感觉就根本不应该 Typecheck…\n躺平了，去 Zulip 问一下…\n---\nEdit 01-06: Apparently Lean4 对于 Pattern Matching 的处理比较神秘：\ntheorem meow {α : Sort u} (a : α) : (h : α = α) -> (cast h a) = a :=\n  fun _ => rfl\n\ntheorem meow_meow {A : Sort u} {a : A} : (i : a = a) -> i = rfl\n:= fun _ => rfl\n\n那能证出来 UIP 一点也不奇怪…那么应该问的问题是：Lean4 的 Pattern matching 到底是怎么处理的呢？\n---\nEdit 01-07:\n在 Zulip 提问了，原来是 Lean 有 Definitional proof irrelevance:\nhttps://leanprover.zulipchat.com/#narrow/channel/113489-new-members/topic/How.20are.20functions.20taking.20equalities.20type.20checked.3F/near/492251131\n那么一切都不奇怪了（\n我是工科猪.jpg\n相关阅读：LeanTT [3], Definitional proof irrelevance without K [4].\nReferences\n- [1] https://homotopytypetheory.org/2012/11/21/on-heterogeneous-equality/\n- [2] https://coq.discourse.group/t/dependent-pair-injectivity-equivalent-to-k\n- [3] Mario Carneiro, The Type Theory of Lean. 2019\n- [4] Gaëtan Gilbert, Jesper Cockx, Matthieu Sozeau, and Nicolas Tabareau. 2019. Definitional proof-irrelevance without K. Proc. ACM Program. Lang. 3, POPL, Article 3 (January 2019), 28 pages. https://doi.org/10.1145/3290316\n"},{"metadata":{"id":"hello-2025","lang":"zh-CN","title":"2025","tags":["扯淡"],"publish_time":"2025-01-01T18:05:29.963Z","update_time":"2025-01-01T19:56:37.324Z","title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"5","components":[["M 269 17C 440 17 564 -65 564 -219C 564 -368 460 -446 291 -446C 227 -446 170 -437 112 -412L 154 -399L 176 -715L 150 -623L 538 -623L 538 -747L 129 -747L 105 -395L 135 -375C 170 -386 203 -392 241 -392C 334 -392 393 -327 393 -212C 393 -85 332 -18 240 -18C 204 -18 186 -24 155 -40L 189 -15L 173 -125C 167 -184 143 -206 102 -206C 74 -206 48 -191 37 -161C 45 -52 129 17 269 17Z",[-0.012,0.418]]],"bbox":{"top":-747,"bottom":17,"left":37,"right":564},"hadv":613}],"text":"2025","hadv":2451,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>本来信心满满地在一月一号晚上留了充足的时间写点东西，结果博客后端爆炸了，一边读自己快十年前的 C++ 代码修理了两个小时，感觉代码复杂超出我的理解，节目效果非常好。</p>\n<p>重新阅读了两年前的年初展望，感觉到有点难堪，并不是因为感觉自己之前的文字略有幼稚。刚刚跟群友开玩笑说我要先把博客之前的丢人文章删掉再发这篇，不过说心里话，真要删丢人文章估计本篇是第一个被删的。真奇怪，明明客观来看我现在的精神状态、生活情况都要比两年、五年前要好得多，不过我感觉再难以写出那种文字了，就像我觉得十年过后，我再也没有什么能力去用 C++ 写一个网站后端一样。当然可以说那样的文字软弱、浮夸、揉捻造作，不过我还是觉得它充满希望、勇气和爱，不像这般冰冷。</p>\n<p>过去两年，发生了很多重要的事情，不过好像并没有很多想让我 Show off 的事情。开始读硕士，继续穷学生的身份，好像并没有比担任 TUNA 会长更令人骄傲——不过会长做的十分磕绊；发了一篇论文，不过因为 I 人自带 Debuff，数次展示都感觉效果糟糕；就连长跑也是不上不下的位置：半马1个小时22分，正好在校队入队标准外面看门。这几天想要再多加训练，不过被北京的东北风一吹，本来计划的跑步路线就变成了觅食路线。</p>\n<p>不过最令我高兴的其中一件事情，是认识到本博客居然有读者，令喵喵大为震惊，本来以为是我自己的瞎堆东西的杂物间了，一旦了解到有他人阅读，难以面对它的情绪就更加加剧。很高兴听到大家很喜欢随便写的那些东西，不过也很抱歉，我反而失去了平常心，开始躲避这里。不过终于，不论是因为习惯、仪式感，还是丑陋的表达欲，终于还是决定回到这里。</p>\n<p>然而这篇总结/展望就要写完了，再之后呢？即使文章并不多，这个博客凝结的也是小喵喵变成大喵喵的历程，他遇到的困难，他的自豪。喵喵意识到很多朋友的博客<super>[1][2][3]</super>，虽然和此处不一样是纯技术博客，不过传达出的激情远超此处。喵喵意识到，就像一些网友发来的私信中所说的，他也希望能在自己的文字中，更多注入一些对生活的热情。喵喵也意识到，他的很多朋友可能正需要一些这样的对生活的热情——也许他本人有时也是。</p>\n<p>于是这就是今年的目标，也是过去几年的一贯的目标：分享，连接，并也许可以激励他人。一部分将会从这里开始：即使在害怕着发现自己已经变得冷漠、刻薄，我还是要再挣扎一下，在这里多留下一些文字。在 2020 年的“变得有趣”，2023 年的“变得乐观”以后，喵喵总算觉得似乎已经准备好了。今年的目标也许更加务实，也许更加严峻，也许反映在这篇年初展望的风格上。</p>\n<p>今天收拾了屋子，并且喝了甜甜的南瓜粥，十分开心。祝大家新年快乐，一切顺利。</p>\n<hr/>\n<ul>\n<li><code>[1]</code> 杰哥的{运维，编程，调板子}小笔记 <a href=\"https://jia.je/\">https://jia.je/</a></li>\n<li><code>[2]</code> Harry Chen’s Blog <a href=\"https://harrychen.xyz\">https://harrychen.xyz</a></li>\n<li><code>[3]</code> 属于CYY自己的世界 <a href=\"https://blog.cyyself.name/\">https://blog.cyyself.name/</a></li>\n</ul>\n<hr/>\n<p>Apparently SSR 爆炸了，所以没有 SEO。Also Firefox 给后端发送了两遍 Cookie，感觉是 FF 的 Bug。Also Also https://github.com/CrowCpp/Crow/issues/967</p>\n","plain":"本来信心满满地在一月一号晚上留了充足的时间写点东西，结果博客后端爆炸了，一边读自己快十年前的 C++ 代码修理了两个小时，感觉代码复杂超出我的理解，节目效果非常好。\n重新阅读了两年前的年初展望，感觉到有点难堪，并不是因为感觉自己之前的文字略有幼稚。刚刚跟群友开玩笑说我要先把博客之前的丢人文章删掉再发这篇，不过说心里话，真要删丢人文章估计本篇是第一个被删的。真奇怪，明明客观来看我现在的精神状态、生活情况都要比两年、五年前要好得多，不过我感觉再难以写出那种文字了，就像我觉得十年过后，我再也没有什么能力去用 C++ 写一个网站后端一样。当然可以说那样的文字软弱、浮夸、揉捻造作，不过我还是觉得它充满希望、勇气和爱，不像这般冰冷。\n过去两年，发生了很多重要的事情，不过好像并没有很多想让我 Show off 的事情。开始读硕士，继续穷学生的身份，好像并没有比担任 TUNA 会长更令人骄傲——不过会长做的十分磕绊；发了一篇论文，不过因为 I 人自带 Debuff，数次展示都感觉效果糟糕；就连长跑也是不上不下的位置：半马1个小时22分，正好在校队入队标准外面看门。这几天想要再多加训练，不过被北京的东北风一吹，本来计划的跑步路线就变成了觅食路线。\n不过最令我高兴的其中一件事情，是认识到本博客居然有读者，令喵喵大为震惊，本来以为是我自己的瞎堆东西的杂物间了，一旦了解到有他人阅读，难以面对它的情绪就更加加剧。很高兴听到大家很喜欢随便写的那些东西，不过也很抱歉，我反而失去了平常心，开始躲避这里。不过终于，不论是因为习惯、仪式感，还是丑陋的表达欲，终于还是决定回到这里。\n然而这篇总结/展望就要写完了，再之后呢？即使文章并不多，这个博客凝结的也是小喵喵变成大喵喵的历程，他遇到的困难，他的自豪。喵喵意识到很多朋友的博客[1][2][3]，虽然和此处不一样是纯技术博客，不过传达出的激情远超此处。喵喵意识到，就像一些网友发来的私信中所说的，他也希望能在自己的文字中，更多注入一些对生活的热情。喵喵也意识到，他的很多朋友可能正需要一些这样的对生活的热情——也许他本人有时也是。\n于是这就是今年的目标，也是过去几年的一贯的目标：分享，连接，并也许可以激励他人。一部分将会从这里开始：即使在害怕着发现自己已经变得冷漠、刻薄，我还是要再挣扎一下，在这里多留下一些文字。在 2020 年的“变得有趣”，2023 年的“变得乐观”以后，喵喵总算觉得似乎已经准备好了。今年的目标也许更加务实，也许更加严峻，也许反映在这篇年初展望的风格上。\n今天收拾了屋子，并且喝了甜甜的南瓜粥，十分开心。祝大家新年快乐，一切顺利。\n- [1] 杰哥的{运维，编程，调板子}小笔记 https://jia.je/\n- [2] Harry Chen’s Blog https://harrychen.xyz\n- [3] 属于CYY自己的世界 https://blog.cyyself.name/\nApparently SSR 爆炸了，所以没有 SEO。Also Firefox 给后端发送了两遍 Cookie，感觉是 FF 的 Bug。Also Also https://github.com/CrowCpp/Crow/issues/967\n"},{"metadata":{"id":"restic-hdd","lang":"zh-CN","title":"restic store on HDD","tags":["踩坑"],"publish_time":"2023-08-14T14:34:46.656Z","update_time":"2023-08-14T14:34:46.656Z","title_outline":{"groups":[{"chars":[{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579}],"text":"restic","hadv":2961,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586}],"text":"store","hadv":2661,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"H","components":[["M 41 -0L 387 -0L 387 -34L 227 -50L 196 -50L 41 -34Z",[-0.865,0.0]],["M 41 -713L 196 -698L 227 -698L 387 -713L 387 -747L 41 -747Z",[-0.504,0.014]],["M 128 -0L 305 -0C 301 -117 301 -235 301 -365L 301 -395C 301 -514 301 -632 305 -747L 128 -747C 131 -630 131 -513 131 -395L 131 -351C 131 -232 131 -114 128 -0Z",[0.0,0.771]],["M 216 -361L 654 -361L 654 -399L 216 -399Z",[-0.931,0.006]],["M 482 -0L 829 -0L 829 -34L 671 -50L 641 -50L 482 -34Z",[-0.863,0.002]],["M 482 -713L 641 -698L 671 -698L 829 -713L 829 -747L 482 -747Z",[-0.608,0.05]],["M 565 -0L 742 -0C 739 -117 739 -235 739 -351L 739 -395C 739 -514 739 -632 742 -747L 565 -747C 569 -630 569 -513 569 -395L 569 -365C 569 -232 569 -114 565 -0Z",[-0.001,0.77]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":829},"hadv":870},{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799}],"text":"HDD","hadv":2468,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>因为懒得倒垃圾，现在 Restic 里面一共有快 40k 个 snapshot</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#657b83;\">&gt; </span><span style=\"color:#d33682;\">~</span><span style=\"color:#839496;\"> ls /srv/restic/snapshots </span><span style=\"color:#859900;\">| </span><span style=\"color:#b58900;\">wc</span><span style=\"color:#268bd2;\"> -l\n</span><span style=\"color:#b58900;\">39236\n</span></code></pre>\n</div>\n<p>之前 restic 是放在 MinIO 里的，但是每次 restic 需要推新的 snapshot 或者列出 snapshot 的时候，需要把整个 snapshot 全量同步到本地。MinIO 放在 ext4 上，底下是 HDD，读 40k 个小文件直接把 IO 打爆了，然后超时。</p>\n<p>灵车 Idea：RAID1 on HDD/tmpfs。然后读取全都从 tmpfs 里读，相当于让 tmpfs 作为一个 writeback cache。mdadm 里有两个选项专门用来处理这件事：</p>\n<ul>\n<li><code>--write-mostly</code>: 指定某个设备主要处理写，读从其他设备读。把比较慢的设备 (In our case, storage on HDD) 放在这个选项后面。</li>\n<li><code>--write-behind</code>: 允许写提前完成。</li>\n</ul>\n<p>这样可以搞出来一个 Good enough™ 的缓存。如果一致性需要更好一些，可以把 write-behind 去掉。最后由于 mdadm 需要在设备上面建 raid，需要把 dd 出来的文件给 loop mount 一下。</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> dd if=/dev/zero of=/restic-disk bs=1M count=768\n</span><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> cp /restic-disk /tmp/restic-disk-0\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> losetup /dev/loop0 /restic-disk\n</span><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> losetup /dev/loop1 /tmp/restic-disk-0\n</span><span style=\"color:#657b83;\">&gt;</span><span style=\"color:#839496;\"> mdadm</span><span style=\"color:#268bd2;\"> --create --verbose</span><span style=\"color:#839496;\"> /dev/md0</span><span style=\"color:#268bd2;\"> --level</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">1</span><span style=\"color:#268bd2;\"> --raid-devices</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">2 /dev/loop1</span><span style=\"color:#268bd2;\"> --write-mostly</span><span style=\"color:#839496;\"> /dev/loop0</span><span style=\"color:#268bd2;\"> --write-behind</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">256</span><span style=\"color:#268bd2;\"> --bitmap</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">internal\n</span></code></pre>\n</div>\n<p>最后，在重启之后这个 md 会挂掉（因为两个 loop device 都不在）。重建的时候需要先把 HDD 上的镜像给加上，然后 mark clear，之后再重建，要不一键删库。</p>\n","plain":"因为懒得倒垃圾，现在 Restic 里面一共有快 40k 个 snapshot\n> ~ ls /srv/restic/snapshots | wc -l\n39236\n\n之前 restic 是放在 MinIO 里的，但是每次 restic 需要推新的 snapshot 或者列出 snapshot 的时候，需要把整个 snapshot 全量同步到本地。MinIO 放在 ext4 上，底下是 HDD，读 40k 个小文件直接把 IO 打爆了，然后超时。\n灵车 Idea：RAID1 on HDD/tmpfs。然后读取全都从 tmpfs 里读，相当于让 tmpfs 作为一个 writeback cache。mdadm 里有两个选项专门用来处理这件事：\n- --write-mostly: 指定某个设备主要处理写，读从其他设备读。把比较慢的设备 (In our case, storage on HDD) 放在这个选项后面。\n- --write-behind: 允许写提前完成。\n这样可以搞出来一个 Good enough™ 的缓存。如果一致性需要更好一些，可以把 write-behind 去掉。最后由于 mdadm 需要在设备上面建 raid，需要把 dd 出来的文件给 loop mount 一下。\n> dd if=/dev/zero of=/restic-disk bs=1M count=768\n> cp /restic-disk /tmp/restic-disk-0\n\n> losetup /dev/loop0 /restic-disk\n> losetup /dev/loop1 /tmp/restic-disk-0\n> mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/loop1 --write-mostly /dev/loop0 --write-behind=256 --bitmap=internal\n\n最后，在重启之后这个 md 会挂掉（因为两个 loop device 都不在）。重建的时候需要先把 HDD 上的镜像给加上，然后 mark clear，之后再重建，要不一键删库。\n"},{"metadata":{"id":"hello-2023","lang":"zh-CN","title":"2023","tags":["扯淡"],"publish_time":"2023-01-19T05:48:41.571Z","update_time":"2023-01-19T05:49:33.603Z","title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"3","components":[["M 283 17C 454 17 559 -67 559 -189C 559 -307 488 -389 279 -400L 279 -384C 468 -401 536 -482 536 -587C 536 -690 461 -764 303 -764C 181 -764 76 -713 73 -593C 84 -574 104 -562 129 -562C 164 -562 195 -579 204 -630L 224 -733L 161 -708C 198 -723 229 -730 256 -730C 332 -730 377 -680 377 -581C 377 -462 318 -408 230 -408L 196 -408L 196 -369L 235 -369C 337 -369 391 -306 391 -188C 391 -76 334 -18 231 -18C 196 -18 174 -26 145 -41L 196 -12L 178 -120C 169 -187 144 -207 104 -207C 78 -207 52 -193 41 -161C 50 -49 131 17 283 17Z",[0.011,0.423]]],"bbox":{"top":-764,"bottom":17,"left":41,"right":559},"hadv":612}],"text":"2023","hadv":2450,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\nimg, video {\n  max-width: 100%;\n}\n</style>\n<p><img src=\"https://storage.c-3.moe/meow/bonsai.jpg\" alt=\"LEGO Bonsai Tree 10281\" /></p>\n<p>三年前就想买的 LEGO Set 10281，在元旦和家人一起逛街的时候，忽然就觉得必须要买。花了一个上午拼了起来，套装给的花瓣比标定的多了一倍还多，让樱花盛开到了完全不真实的地步。</p>\n<p>时间过得真快，上次写博客已经快接近三年前了，Year in Preview 则是超过了三年，让我怀疑我是不是已经忘记了怎么写这种文章。如你还在关注这个博客，请让我为我的摸鱼道歉。还记得小的时候参加我妈的同学聚会，结束之后和妈妈走向公交站的路上。秋天的落叶踩上去会咔嚓咔嚓地响，妈妈说：“你知道为什么有几个同学这几年从来没有来过同学聚会吗？因为他们不好意思见我们。”喵喵当时还小，还不明白这些，但是落叶发出的声音就像草莓威化饼干，听起来很好吃的样子。</p>\n<p>2020 年 6 月，喵喵临床诊断为抑郁症和强迫症，并受此影响休学了一年半。虽然到现在为止抑郁症早就恢复了，但 OCD 的症状已伴随我所经历的全部时间的一半，很难否定它已经内化成喵喵的一部分了。2020-2022 年，是喵喵认识自己的三年。普普通通地踮起脚尖，大概丈量了一下自己所能触及的地方，然后在那里画了一条线，这样便不再会随便因为自己没做到什么而气馁。而且如果努努力，好像还能碰到更高一些的地方呢。</p>\n<p>虽然很想躺平，但是从 20 年初开始，在 TG 新的朋友一个又一个地出现，善良而可爱的人们，帮助我度过了最困难的时期。在新朋友、旧朋友和自己的鼓励和陪伴下，喵喵做到了很多一直想做的事情。讲了 Tunight，然后又讲了两次 Tunight，看完了半本 HoTT，参加了很多定向比赛，开始练习长距离，重新开始玩 osu…数不胜数的只靠 20 年初的喵喵自己无法做到的事情。“友谊是魔法”，其中一个朋友跟我说我博客上的文字很可爱，所以才有这篇文章。很遗憾，可能我现在没办法写下 20 年初之前，“那么就把愿望设置成变得有趣吧！”这样充满希望的，可爱而不失勇气的文字，但是喵喵会努力的！</p>\n<p>认识自己除了有认识自己有限的能力范围，也有认识到自己的已经做到的东西，和想要去做的东西。喵喵很幸运，在朋友们的帮助下，相比于前者，收获了更多后面两种东西，逐渐地逐渐地，成为了可以跑下来半马的喵喵。想尽快把他们的博客友链放在这里，但是很可惜，这个前端还是没有留友链的地方。果然功能如果没人写就不会自己出来呢（难过）。</p>\n<p>说到博客改版，2021 年 10 月开始，曾经短暂进行过一段时间的新版开发。现在看来，设计的实在是有些浮夸，但是写代码还是一件很有趣的事情！最近应该会重新拾起来，也许会发现，今年我还是很喜欢鼓捣这些东西，即使这样想一想就会很开心。</p>\n<video controls>\n  <source src=\"https://storage.c-3.moe/meow/pointwise-wip.mp4\" type=\"video/mp4\" />\n</video>\n<p>我已经过了 24 岁生日了，但是总感觉在这些角度上，我还是永远长不大的小喵喵。喜欢做的东西，就像草莓威化饼干一样，遍地都是，但是无论岁月如何流转，无论体验了多少次那种甜甜的味道，还是完全不会损失吸引力的样子。还有太多太多可以做的事情，太多的东西想学，厕纸想看，代码想写，游戏想玩，没有见过的云彩的形状也想一一目睹。所以今年的愿望简单一点，就是去寻找更多的草莓饼干，然后吃掉，变得开心，然后把开心分享给身边的人——这三年喵喵玩过看过的、喜欢的动画片和游戏什么的，希望新的一年也能有时间写博客给大家安利呢。</p>\n<p>就这样，吃着草莓饼干，每天努力的话，应该会抵达都是猫咪的乐园。但是如果乐园不存在呢？那就有无穷无尽的草莓饼干吃，好像也不错呢。</p>\n<div style=\"text-align: center\">\n  <img src=\"https://storage.c-3.moe/meow/paradise.png\" style=\"width: 200px\" />\n</div>","plain":"LEGO Bonsai Tree 10281\n三年前就想买的 LEGO Set 10281，在元旦和家人一起逛街的时候，忽然就觉得必须要买。花了一个上午拼了起来，套装给的花瓣比标定的多了一倍还多，让樱花盛开到了完全不真实的地步。\n时间过得真快，上次写博客已经快接近三年前了，Year in Preview 则是超过了三年，让我怀疑我是不是已经忘记了怎么写这种文章。如你还在关注这个博客，请让我为我的摸鱼道歉。还记得小的时候参加我妈的同学聚会，结束之后和妈妈走向公交站的路上。秋天的落叶踩上去会咔嚓咔嚓地响，妈妈说：“你知道为什么有几个同学这几年从来没有来过同学聚会吗？因为他们不好意思见我们。”喵喵当时还小，还不明白这些，但是落叶发出的声音就像草莓威化饼干，听起来很好吃的样子。\n2020 年 6 月，喵喵临床诊断为抑郁症和强迫症，并受此影响休学了一年半。虽然到现在为止抑郁症早就恢复了，但 OCD 的症状已伴随我所经历的全部时间的一半，很难否定它已经内化成喵喵的一部分了。2020-2022 年，是喵喵认识自己的三年。普普通通地踮起脚尖，大概丈量了一下自己所能触及的地方，然后在那里画了一条线，这样便不再会随便因为自己没做到什么而气馁。而且如果努努力，好像还能碰到更高一些的地方呢。\n虽然很想躺平，但是从 20 年初开始，在 TG 新的朋友一个又一个地出现，善良而可爱的人们，帮助我度过了最困难的时期。在新朋友、旧朋友和自己的鼓励和陪伴下，喵喵做到了很多一直想做的事情。讲了 Tunight，然后又讲了两次 Tunight，看完了半本 HoTT，参加了很多定向比赛，开始练习长距离，重新开始玩 osu…数不胜数的只靠 20 年初的喵喵自己无法做到的事情。“友谊是魔法”，其中一个朋友跟我说我博客上的文字很可爱，所以才有这篇文章。很遗憾，可能我现在没办法写下 20 年初之前，“那么就把愿望设置成变得有趣吧！”这样充满希望的，可爱而不失勇气的文字，但是喵喵会努力的！\n认识自己除了有认识自己有限的能力范围，也有认识到自己的已经做到的东西，和想要去做的东西。喵喵很幸运，在朋友们的帮助下，相比于前者，收获了更多后面两种东西，逐渐地逐渐地，成为了可以跑下来半马的喵喵。想尽快把他们的博客友链放在这里，但是很可惜，这个前端还是没有留友链的地方。果然功能如果没人写就不会自己出来呢（难过）。\n说到博客改版，2021 年 10 月开始，曾经短暂进行过一段时间的新版开发。现在看来，设计的实在是有些浮夸，但是写代码还是一件很有趣的事情！最近应该会重新拾起来，也许会发现，今年我还是很喜欢鼓捣这些东西，即使这样想一想就会很开心。\n我已经过了 24 岁生日了，但是总感觉在这些角度上，我还是永远长不大的小喵喵。喜欢做的东西，就像草莓威化饼干一样，遍地都是，但是无论岁月如何流转，无论体验了多少次那种甜甜的味道，还是完全不会损失吸引力的样子。还有太多太多可以做的事情，太多的东西想学，厕纸想看，代码想写，游戏想玩，没有见过的云彩的形状也想一一目睹。所以今年的愿望简单一点，就是去寻找更多的草莓饼干，然后吃掉，变得开心，然后把开心分享给身边的人——这三年喵喵玩过看过的、喜欢的动画片和游戏什么的，希望新的一年也能有时间写博客给大家安利呢。\n就这样，吃着草莓饼干，每天努力的话，应该会抵达都是猫咪的乐园。但是如果乐园不存在呢？那就有无穷无尽的草莓饼干吃，好像也不错呢。\n"},{"metadata":{"id":"sth-about-jielabs","lang":"zh-CN","title":"Sth. about JieLabs","tags":["开发"],"publish_time":"2020-03-12T03:49:07.946Z","update_time":"2020-03-16T21:04:17.885Z","title_outline":{"groups":[{"chars":[{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"Sth","hadv":1718,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"about","hadv":3022,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"J","components":[["M 74 162C 131 162 194 140 248 75C 295 18 317 -49 317 -201L 317 -404C 317 -520 317 -636 321 -747L 151 -747C 154 -423 155 -298 155 -208C 155 -60 159 43 142 134L 142 142L 157 142L 157 136L 111 79C 76 40 58 33 23 33C -14 33 -42 49 -51 93C -44 142 -1 162 74 162Z",[0.111,0.745]],["M 43 -713L 204 -698L 246 -698L 409 -713L 409 -747L 43 -747Z",[-0.888,0.008]]],"bbox":{"top":-747,"bottom":162,"left":-51,"right":409},"hadv":442},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"L","components":[["M 41 -0L 218 -0L 219 -50L 202 -50L 42 -34Z",[0.751,0.04]],["M 41 -713L 202 -698L 240 -698L 403 -713L 403 -747L 41 -747Z",[-0.878,0.008]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -346L 303 -411C 303 -514 303 -632 306 -747L 130 -747C 133 -631 133 -513 133 -395L 133 -324C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 619 -0L 617 -224L 562 -224L 503 -2L 588 -39L 219 -39Z",[0.547,0.208]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":619},"hadv":651},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"JieLabs","hadv":3837,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>最近和川川杰哥一起写了 JieLabs，在线进行数电实验。板子上的川川写的，我完全看不懂，后端和前端算法部分全靠杰哥，喵喵就写了几千行 CSS，基本没干活。虽然只写了 UI 有点内疚，但是摸鱼真爽啊。</p>\n<p>杰哥’s side: <a href=\"https://jiege.ch/jielabs/\">https://jiege.ch/jielabs/</a></p>\n<p>但是听说有人对前端 UI 我写的部分的实现感兴趣，还是蛮开心的。于是稍微写一点可能对前端入门有点帮助的知识？毕竟喵喵的前端水平也就业余。对于其他不打算学前端的同学们，以下是你不需要知道的 Somethings about JieLabs.</p>\n<h2>众所周知，CSS Transition 不应该用…</h2>\n<p>首先是<del>比较清楚的</del>部分: CSS Transition。</p>\n<p>既然我们都是在写 CSS，我们就先不需要关心 JS 的事件循环啊，怎么算 Sytle set 啊之类的。因此我们需要关心的就是，DOM 确定不变，Style set 浏览器帮忙计算，究竟用什么属性来做 CSS Transition 又快又好还省电呢？</p>\n<p>众所周知<sup>[来源请求?]</sup>，在浏览器里，这部分渲染一般实现为三个不同的阶段：</p>\n<ul>\n<li>Layout: 算位置，宽高</li>\n<li>Paint/Render: 画</li>\n<li>Composite: 叠加</li>\n</ul>\n<p>一般而言，如果前两个阶段需要重新做，我们通常分别叫他们 Reflow, Repaint/Rerender。重新进行 Composite 没有单独的名字？我们通常叫他 Composite。</p>\n<p>首先，Paint 依赖 Layout 的结果，要不然我们没办法知道特定绘制的参数（<code>background-size: cover</code> 时背景的缩放，<code>calc(100vw - 10%)</code> 究竟是几个像素，etc.)。Composite 依赖 Paint 的结果，Paint 的东西改变了之后需要重新混合。因此越靠上的阶段如果重新做了，需要把下面所有的事情都重新做一次。</p>\n<p>此外，Reflow 是本身代价最高的操作，因为 Reflow 可能会涉及非常非常多的元素。比如这样的 HTML：</p>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.animated </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">font-size</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">18</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">transition</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">font-size </span><span style=\"color:#6c71c4;\">.2</span><span style=\"color:#859900;\">s ease</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.animated</span><span style=\"color:#657b83;\">:hover {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">font-size</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">24</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">parent</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">p </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">animated</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;</span><span style=\"color:#839496;\">First paragraph </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">span</span><span style=\"color:#586e75;\">&gt;</span><span style=\"color:#839496;\">inner</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">span</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">p</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">p</span><span style=\"color:#586e75;\">&gt;</span><span style=\"color:#839496;\">Second paragrapn</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">p</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span></code></pre>\n</div>\n<p><code>p.animated</code> 会在鼠标经过的时候变<span style=\"font-size: 24px\">大</span>，这个变大是可能改变元素的大小的，所以当 <code>p.animated</code> 被撑大之后，<code>p.animated + p</code> 也需要 Reflow，之后把整个父元素也撑大了，所以 <code>.parent</code> 也需要 Reflow。同时因为 Style 的继承，<code>p.animated &gt; span</code> 也会经历一遍相似的事情。如果是大段文字前面发生了某个元素 Reflow，场面就尤其壮观，因为算一个现代字体具体怎么画，在哪里换行，可能是很慢而且很难的事情。因此，如果发生了 Reflow，不需要区分到底是哪个元素 Reflow 了，因为其实大家都在 Reflow。</p>\n<p>随后，当一大坨元素都 Reflow 完成了之后，他们还需要 Repaint，最后再 Composite，新画出来的东西还得都发给 GPU。</p>\n<p>Paint 就安分很多，可以把这个元素单独拿出来，自己画自己的。但是画画这件事情其实也挺复杂的，比如画个字，浏览器一般自己都懒得做，全都丢给 OS，导致 Windows 上字体渲染水准和 macOS 比完全比不上（碎碎念）。因此这部分虽然不很慢，但是如果每帧都做，一般你能确保 20 FPS，具体上限在哪里看渲染面积和造化。</p>\n<p>然后是 Composite，这步通常靠 GPU 加速一下，用各种 gl 直接叠起来就行了，而且只需要 Composite 变化了的部份，因此它是最快的。</p>\n<p>根据刚刚的分析，越靠前的阶段，我们越不希望重做。所以我猜前两个之所以有名字，就是因为大家都在写博客，说</p>\n<blockquote>\n<p>Don’t cause a reflow in CSS animation!</p>\n</blockquote>\n<p>久而久之大家就都这么叫了。结果就是虽然大家整天都在导致重新 Composite，但是它却没有名字，稍微有点心疼。</p>\n<p>说了这么多背景知识，到底能干什么呢？假设如果我们要让一个一个图片往下动，略加思索得到的 transition 选择包括：</p>\n<ul>\n<li>img { top }</li>\n<li>img { margin-top }</li>\n<li>div { background-position }</li>\n<li>img { transform }</li>\n</ul>\n<p>前两者会导致 Reflow，即使你把它安排成一个 <code>position: fixed</code>，浏览器依旧决定 Reflow 一大堆元素，然后大家全部 Reapint。第三种会导致 Repaint，第四种只影响 Composite，因此它最快，而且最省电。</p>\n<p>同样地，如果要改变一个字的透明度，可以通过 <code>color</code> 或者 <code>opacity</code>，如果能用后者永远是更好的。</p>\n<p>At the time of writing，JieLabs 里用到的 Transition 属性统计如下：</p>\n<pre><code>&gt; grep -r -h -oP -i --include \\*.scss \"^ *transition: [a-zA-Z\\-]+\" src | grep -h -oP -i \"[a-zA-Z\\-]*$\" | sort | uniq -c | sort -n\n      1 background-color\n      1 border-color\n      1 box-shadow\n      1 color\n      1 mask-position\n      4 filter\n     12 transform\n     39 opacity\n</code></pre>\n<p>前四个会有 Repaint，其中第三个稍微贵一点，因为他要重新决定 Composite 的边界。剩下的理论上来说都可以在 Composite 时解决，但是好像 WebKit 没好好写 <code>mask-position</code> 的动画。可以理解，毕竟这个属性没啥人用。</p>\n<p>除了 Transition 以外，动画里还有到了一个 clip-path，这个理论上来说应该可以在 Composite 的时候实现？但是 Chrome 好像也摸了。这个喵喵没有发现简单地办法看出来它有没有触发 Repaint，因为如果把 Repaint flash 打开，其实改变 style 也会闪烁，所以在 Composite 属性改变的时候也会绿绿绿。</p>\n<blockquote>\n<p>吐槽： Chrome 好像会把 Composite 丢到另外一个后台线程上去做，然后如果 Tab 开太多，这个线程就会比较摸鱼，但是一打开 Profiler 它就不摸了，导致只有在 Profile 的时候跑得快（混乱邪恶：说明打开 Profiler 即可瞬间优化）</p>\n</blockquote>\n<p>总体而言，为了达成常用的动画效果，喵喵的习惯是：</p>\n<ul>\n<li>移动: <code>transform: translate</code></li>\n<li>强调 - 渐变: <code>transition: opacity</code></li>\n<li>渐变+隐藏: <code>transition: opacity</code>, 额外用 <code>pointer-events</code> 控制鼠标事件的捕捉</li>\n<li>模糊: <code>filter: blur</code></li>\n<li>背景模糊: <code>backdrop-filter: blur</code> (这个在比较新的 Chrome 里支持了，动画也很流畅，但是在最新的 Windows Insider 上会把我的系统打绿屏)</li>\n<li>颜色: 如果可能的话，用 <code>filter: hue-rotate</code></li>\n<li>背景渐变: 放一个 <code>:after { position: absolute; }</code>，然后在这个上面 <code>transition: opacity</code></li>\n<li>背景颜色改变: 放一个 <code>:after</code> 和一个 <code>:before</code>，然后控制 <code>:after</code> 的透明度</li>\n<li>显示区域变化: <code>transition: clip-path</code> 或者 <code>mask-image + transtiion: mask-position</code></li>\n</ul>\n<p>剩下如果必须要发生 Repaint 了，一定不要改变定位属性，还有改变 bouding box 的那一堆东西（<code>margin</code>, <code>padding</code>, <code>top</code>, etc.)</p>\n<h2>React rendering flow</h2>\n<p>老生常谈了。这次 JieLabs 在写的时候所有 React 组件都是用了 <code>React.memo</code> 的函数式组件，用了十万个 Hook，然后叠了个 Redux 管大范围分享的状态。</p>\n<p>写了大半年 React，对 React 组件感觉上除了重用以外，另外还有作为渲染边界使用。在这里讨论 React 的渲染流，即 React component -&gt; V-DOM 这部分。React 是单向向下的渲染流，如果一个组件发生重新渲染，它会通知 React 渲染自己的子组件，React 去拿渲染好的 Cached V-DOM 或者重绘，然后把渲染出来的结果返回。</p>\n<p>React.memo 作为渲染边界的时候，决定一个子组件是否需要重新渲染是通过属性的 Weak equality。所以写这样的代码就基本 GG：</p>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">Component\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">prop</span><span style=\"color:#657b83;\">=</span><span style=\"color:#2aa198;\">{list.map(mapper)}\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">cb</span><span style=\"color:#657b83;\">=</span><span style=\"color:#2aa198;\">{e</span><span style=\"color:#657b83;\"> =</span><span style=\"color:#586e75;\">&gt;</span><span style=\"color:#839496;\"> { /* Literal callback */ }}\n</span><span style=\"color:#839496;\">/&gt;\n</span></code></pre>\n</div>\n<p>即使 list 是个 immutable list 也一样，因为每次都吐了个新的 mapped list 出来。</p>\n<p>一般而言这样的代码写在一个 HTML 元素上不会有大问题，因为反正每次渲染到底层都得重新算一遍 attribute，然后和 Cached V-DOM 比对，对于 Event listener 而言也不会直接注册到 DOM 上面，而是 React-dom 自己把自己的 Listener 注册上去，然后在里面再调用写在 JSX 里的 callback，所以也不会涉及 DOM 上 listener 的注册/注销。但是放到 Component 上，这么写肯定和上次渲染不满足 Weak equality，所以子组件一定会重绘，即使最后渲染出来结果一样。</p>\n<p>那么怎么办呢？一个办法是所有东西都丢到 Redux 里，Redux 里面同时存原数据和一个 map 过的数据，用 Action 控制更新的原子性。此时，无论是用 connect 还是 useSelector，Redux 会帮忙通过一个 weak equality 决定是否需要通知重绘。</p>\n<p>但是当然还是单一 source of truth 比较好，而且 Redux 里放太多组件自己的不需要持久化的状态就很怪。然后代码里就充满了 <code>useCallback</code>, <code>useMemo</code>, <code>useEffect</code> 之类的垃圾代码。只有这个时候想起了 Vue 的好，自动计算依赖图。当然有一些 Corner case 可以跳过一部分依赖图的节点进行优化，以及显式的决定各种 Hook 回调的通知顺序，这个时候 Vue 就没办法做这些。</p>\n<p>当然，优化到最后就会涉及到状态改变但是不希望重绘的情况（例如 Canvas 正在被隐藏，有一个 <code>useLayoutEffect</code> 是用来画它的，希望暂时暂停）。这个时候感觉没有特别好的解决方法，只能把数据存到 <code>useRef</code> 里面，然后真的需要重新渲染的时候 <code>setXX(XXRef.current)</code></p>\n<h2>DOM patching</h2>\n<p>写 key 这种东西就不用说了，这里要吐槽一些东西。</p>\n<p>DOM 本身是要带状态的，包括 class 导致的 CSS transition。由于 React 是把映射出来的 V-DOM 给 Patch 到 DOM 上。所以写这种代码，就算没写 key，也是可以显示出来一个 loading 类消失的过渡动画的:</p>\n<div class=\"highlighted highlighted-js\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-js\"><span style=\"color:#859900;\">if</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">loading</span><span style=\"color:#657b83;\">) </span><span style=\"color:#859900;\">return &lt;</span><span style=\"color:#839496;\">div className</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">container loading</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#657b83;\">/</span><span style=\"color:#859900;\">&gt;</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#859900;\">return </span><span style=\"color:#657b83;\">(\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">&lt;</span><span style=\"color:#839496;\">div className</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">container</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#859900;\">&gt;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">{ </span><span style=\"color:#586e75;\">/* ... */ </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">&lt;</span><span style=\"color:#839496;\">/</span><span style=\"color:#2aa198;\">div&gt;\n</span><span style=\"color:#2aa198;\">);\n</span></code></pre>\n</div>\n<p>但是用 Suspense 就不行，不知道为什么会不重用 DOM。可能 Suspense 是一套完全不同的渲染方法？</p>\n<p>喵喵反正不太喜欢 Suspense 这种结构，如果以后有等待 Promise 的东西会好用一些。现在只有 <code>React.lazy</code> 加载组件好像没啥用（</p>\n<h2>Initial load speed</h2>\n<p>怎么能够加载的快呢？Cache 是浏览器提供的好东西，但是我们能够通过 Service Worker，实现更加激进的缓存策略。</p>\n<h3>Service worker</h3>\n<p>CRA 吐出来的模板自带一个 Workbox，稍微调教了一下让它能够从本地加载 Workbox 库，而不是隔着万里长城去找 Google CDN。</p>\n<p>为了让加载比较快，选择的 Workbox 缓存策略非常激进，用 Local only，做 Pre-caching，包括 index.html 都从 Cache 返回。一般而言这样的行为会导致页面没办法更新，也就是就算 index.html 里面的 version string (文件名内的 hash 或者 query string) 发生改变，也不会被浏览器察觉。</p>\n<p>解决更新问题的方法是在安装的时候加载一下 manifest。由于 manifest 和所有的 asset 文件名都有 hashing，如果服务器上的 asset 更新了，那么 service worker 的代码一定会变，这个时候让它在后台安装，预先下载好资源，然后显示一个刷新通知。</p>\n<p>这样的设计的结果包括：</p>\n<ul>\n<li>只有 Asset 更新的时候需要向服务器请求</li>\n<li>只有第一次加载的时候，Asset 请求会阻塞渲染流</li>\n</ul>\n<p>这个渲染流不只包括 DOM 渲染，也包括 React 的渲染。所有的字体都是用 Webpack 包了一下，因此除了第一次访问，以后每次刷新的时候应该都是瞬间加载的。</p>\n<p>所以我们需要 Care 的就是第一次加载到渲染出有效内容之中，加载的内容。这分为两部分：加载出来“加载页面”，和 React 渲染出来有效内容。</p>\n<h3>Critical style</h3>\n<p>浏览器一般（写Web的时候什么东西都是一般…）如果没有明确指定（defer），在加载 HTML 的时候同时渲染，其中同步加载、执行脚本，异步加载 <code>&lt;link rel=\"stylesheet\"&gt;</code>。这里加载、解析、执行脚本的时候需要阻塞接下来 HTML 的渲染，但是不会阻塞渲染线程本身。</p>\n<p>所以如果我们认为一些 HTML 元素是需要在脚本加载、执行完成之前显示出来，需要把它写到 <code>&lt;script&gt;</code> 标签前面。</p>\n<p>Webpack 会按照程序入口开始的依赖图，向 HTML 里注入一个或者多个 <code>&lt;script&gt;</code>，没有 <code>defer</code>。CRA 默认会把这些标签注入到 body 的结尾，因此我们在 body 开头写的 HTML 元素，是可以很快显示出来的。这个时间中，我们能控制的因素是这个标签前面的字节数。因此放的越靠前，加载出来更快。</p>\n<p>麻烦的是样式表。一般而言，我们把初始显示时就需要的样式称为 Critical style，在静态页面中传统意义上指不滚动的第一屏中显示的内容需要的样式。</p>\n<p><code>&lt;link&gt;</code> 里的样式表永远异步加载，然后加载完成后应用新样式。所以为了保证样式是有效的，我们需要把这部分样式表内联到 <code>&lt;style&gt;</code> 标签里，这样可以保证样式表先于标签加载出来。</p>\n<p>在 Webpack 里完成这件事也比较麻烦，<code>ExtractTextPlugin</code> 或者 <code>MiniCSSPlugin</code> 只会生成 <code>&lt;link&gt;</code> 标签，<code>style-loader</code> 会生成一个用 JS 注入的代码，喂这个要在 JS 加载开始之前就渲染好啊。</p>\n<p>还好 <code>HTMLWebpackPlugin</code> 可以写 ejs 语法，而且可以干奇怪的事情：</p>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  &lt;%=</span><span style=\"color:#657b83;\"> require(&#39;!!</span><span style=\"color:#268bd2;\">css-loader</span><span style=\"color:#657b83;\">!</span><span style=\"color:#268bd2;\">sass-loader</span><span style=\"color:#657b83;\">!..</span><span style=\"color:#839496;\">/</span><span style=\"color:#657b83;\">src</span><span style=\"color:#839496;\">/</span><span style=\"color:#657b83;\">prelude</span><span style=\"color:#b58900;\">.scss</span><span style=\"color:#657b83;\">&#39;</span><span style=\"color:#839496;\">) %&gt;\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span></code></pre>\n</div>\n<p>这里用了 Webpack 的一个特殊语法:</p>\n<ul>\n<li><code>!!</code> 表示禁用所有配置里写好的 loader，这里 scss 默认是 <code>['style', 'css', 'sass']</code></li>\n<li>之后，只执行 <code>sass -&gt; css</code> 两个 loader，得到一个字符串，然后就内嵌进来了</li>\n</ul>\n<p>另一个据说可行的方法是添加一个 entry，然后指定特殊的 loader，但是我们没有找到 <code>customize-cra</code> 里面怎么加 entry，因此没有考证这个方法是否可行。</p>\n<h3>Code splitting</h3>\n<p>现在加载页面已经加载了（笑），我们需要加快 React 渲染出来有效内容的速度。</p>\n<p>Webpack 会把内容拆分成不同的 Chunk，然后每个 Chunk 加载完了一起解析执行。一般而言 Webpack 的分块策略是所有 <code>node_modules</code> 放到一起，剩下的代码积极分块，这样的理由是如果应用代码更新了，绝大多数 Asset 不需要重新下载。但是我们重新下载的延迟都用 Service worker 藏起来了，而且按照默认分块方法，Monaco 需要一开始就加载，这是最大的一块儿内容。</p>\n<p>渲染出来有效内容可能要做这些事情：</p>\n<ul>\n<li>Redux 创建 store</li>\n<li>加载编辑器、 Verilog / VHDL 语言支持</li>\n<li>加载 WASM 模块</li>\n<li>加载两个 Route:\n<ul>\n<li>Login</li>\n<li>Workspace</li>\n</ul>\n</li>\n<li>Redux store 初始化，尝试向服务器询问是否已登录</li>\n</ul>\n<p>由于是初次加载，肯定没有登录。因此只有 Login Route 会用到。编辑器只在 Workspace 里和构建详情里用到，因此也可以延迟加载。 WASM 同样只在编辑器里用到，因此也延迟加载。最后的结果是，我们相当于需要在加载过程中插入这么几个 yield point:</p>\n<ul>\n<li>App 请求加载 Workspace 时</li>\n<li>App 请求加载 Monaco 时</li>\n<li>App 请求加载 WASM 时</li>\n</ul>\n<p>其中，最后一个因为本来就是用 redux 加载完放到 state 里的，直接不 <code>await</code> 到它上面就行了。</p>\n<p>第一个需要 Webpack 的一些特性：使用 <code>const ModulePromise = import('./module')</code> 加载的模块，可以分到一个不同的 chunk 中。</p>\n<p>第二个最麻烦，因为我们不仅需要一个 async import，还需要把 Monaco 从 vendor chunk 里拆出来。这个时候需要额外配置一下 Webpack，强制把 Monaco 自己分一个 chunk:</p>\n<div class=\"highlighted highlighted-js\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-js\"><span style=\"color:#b58900;\">setWebpackOptimizationSplitChunks</span><span style=\"color:#657b83;\">({\n</span><span style=\"color:#839496;\">  chunks: &#39;</span><span style=\"color:#2aa198;\">all</span><span style=\"color:#839496;\">&#39;,\n</span><span style=\"color:#839496;\">  name: </span><span style=\"color:#b58900;\">false</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  cacheGroups: </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    monaco: </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">      test: /</span><span style=\"color:#cb4b16;\">[</span><span style=\"color:#dc322f;\">\\\\</span><span style=\"color:#cb4b16;\">/]</span><span style=\"color:#2aa198;\">node_modules</span><span style=\"color:#cb4b16;\">[</span><span style=\"color:#dc322f;\">\\\\</span><span style=\"color:#cb4b16;\">/]</span><span style=\"color:#2aa198;\">monaco-editor</span><span style=\"color:#839496;\">/,\n</span><span style=\"color:#839496;\">      reuseExistingChunk: </span><span style=\"color:#b58900;\">false</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">,\n</span></code></pre>\n</div>\n<p>对于延迟加载的模块，可以造一个 React hook:</p>\n<div class=\"highlighted highlighted-js\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-js\"><span style=\"color:#268bd2;\">function </span><span style=\"color:#b58900;\">useLoader</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">loader</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const [</span><span style=\"color:#839496;\">Comp, setComp</span><span style=\"color:#268bd2;\">] </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">useState</span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">null</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">useEffect</span><span style=\"color:#657b83;\">(() </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    loader.</span><span style=\"color:#b58900;\">then</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">mod =&gt; </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">      </span><span style=\"color:#b58900;\">setComp</span><span style=\"color:#657b83;\">(() </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#839496;\">mod.default</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">[]</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">Nullify </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">useCallback</span><span style=\"color:#657b83;\">(() </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#b58900;\">null</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">[]</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">return </span><span style=\"color:#839496;\">Comp </span><span style=\"color:#859900;\">|| </span><span style=\"color:#839496;\">Nullify;\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">WorkspaceLoader </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">import</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">./routes/Workspace</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">// Somewhere within App component:\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">Worksapce </span><span style=\"color:#657b83;\">= </span><span style=\"color:#b58900;\">useLoader</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">WorkspaceLoader</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>这样写即使 App 没有被渲染，也会积极加载 Workspace，但是不会阻塞程序入口所在 chunk 的解析和执行。</p>\n","plain":"最近和川川杰哥一起写了 JieLabs，在线进行数电实验。板子上的川川写的，我完全看不懂，后端和前端算法部分全靠杰哥，喵喵就写了几千行 CSS，基本没干活。虽然只写了 UI 有点内疚，但是摸鱼真爽啊。\n杰哥’s side: https://jiege.ch/jielabs/\n但是听说有人对前端 UI 我写的部分的实现感兴趣，还是蛮开心的。于是稍微写一点可能对前端入门有点帮助的知识？毕竟喵喵的前端水平也就业余。对于其他不打算学前端的同学们，以下是你不需要知道的 Somethings about JieLabs.\n\n众所周知，CSS Transition 不应该用…\n首先是比较清楚的部分: CSS Transition。\n既然我们都是在写 CSS，我们就先不需要关心 JS 的事件循环啊，怎么算 Sytle set 啊之类的。因此我们需要关心的就是，DOM 确定不变，Style set 浏览器帮忙计算，究竟用什么属性来做 CSS Transition 又快又好还省电呢？\n众所周知[来源请求?]，在浏览器里，这部分渲染一般实现为三个不同的阶段：\n- Layout: 算位置，宽高\n- Paint/Render: 画\n- Composite: 叠加\n一般而言，如果前两个阶段需要重新做，我们通常分别叫他们 Reflow, Repaint/Rerender。重新进行 Composite 没有单独的名字？我们通常叫他 Composite。\n首先，Paint 依赖 Layout 的结果，要不然我们没办法知道特定绘制的参数（background-size: cover 时背景的缩放，calc(100vw - 10%) 究竟是几个像素，etc.)。Composite 依赖 Paint 的结果，Paint 的东西改变了之后需要重新混合。因此越靠上的阶段如果重新做了，需要把下面所有的事情都重新做一次。\n此外，Reflow 是本身代价最高的操作，因为 Reflow 可能会涉及非常非常多的元素。比如这样的 HTML：\n<style>\n  .animated {\n    font-size: 18px;\n    transition: font-size .2s ease;\n  }\n  .animated:hover {\n    font-size: 24px;\n  }\n</style>\n<div class=\"parent\">\n  <p class=\"animated\">First paragraph <span>inner</span></p>\n  <p>Second paragrapn</p>\n</div>\n\np.animated 会在鼠标经过的时候变大，这个变大是可能改变元素的大小的，所以当 p.animated 被撑大之后，p.animated + p 也需要 Reflow，之后把整个父元素也撑大了，所以 .parent 也需要 Reflow。同时因为 Style 的继承，p.animated > span 也会经历一遍相似的事情。如果是大段文字前面发生了某个元素 Reflow，场面就尤其壮观，因为算一个现代字体具体怎么画，在哪里换行，可能是很慢而且很难的事情。因此，如果发生了 Reflow，不需要区分到底是哪个元素 Reflow 了，因为其实大家都在 Reflow。\n随后，当一大坨元素都 Reflow 完成了之后，他们还需要 Repaint，最后再 Composite，新画出来的东西还得都发给 GPU。\nPaint 就安分很多，可以把这个元素单独拿出来，自己画自己的。但是画画这件事情其实也挺复杂的，比如画个字，浏览器一般自己都懒得做，全都丢给 OS，导致 Windows 上字体渲染水准和 macOS 比完全比不上（碎碎念）。因此这部分虽然不很慢，但是如果每帧都做，一般你能确保 20 FPS，具体上限在哪里看渲染面积和造化。\n然后是 Composite，这步通常靠 GPU 加速一下，用各种 gl 直接叠起来就行了，而且只需要 Composite 变化了的部份，因此它是最快的。\n根据刚刚的分析，越靠前的阶段，我们越不希望重做。所以我猜前两个之所以有名字，就是因为大家都在写博客，说\nDon’t cause a reflow in CSS animation!\n\n久而久之大家就都这么叫了。结果就是虽然大家整天都在导致重新 Composite，但是它却没有名字，稍微有点心疼。\n说了这么多背景知识，到底能干什么呢？假设如果我们要让一个一个图片往下动，略加思索得到的 transition 选择包括：\n- img { top }\n- img { margin-top }\n- div { background-position }\n- img { transform }\n前两者会导致 Reflow，即使你把它安排成一个 position: fixed，浏览器依旧决定 Reflow 一大堆元素，然后大家全部 Reapint。第三种会导致 Repaint，第四种只影响 Composite，因此它最快，而且最省电。\n同样地，如果要改变一个字的透明度，可以通过 color 或者 opacity，如果能用后者永远是更好的。\nAt the time of writing，JieLabs 里用到的 Transition 属性统计如下：\n> grep -r -h -oP -i --include \\*.scss \"^ *transition: [a-zA-Z\\-]+\" src | grep -h -oP -i \"[a-zA-Z\\-]*$\" | sort | uniq -c | sort -n\n      1 background-color\n      1 border-color\n      1 box-shadow\n      1 color\n      1 mask-position\n      4 filter\n     12 transform\n     39 opacity\n\n前四个会有 Repaint，其中第三个稍微贵一点，因为他要重新决定 Composite 的边界。剩下的理论上来说都可以在 Composite 时解决，但是好像 WebKit 没好好写 mask-position 的动画。可以理解，毕竟这个属性没啥人用。\n除了 Transition 以外，动画里还有到了一个 clip-path，这个理论上来说应该可以在 Composite 的时候实现？但是 Chrome 好像也摸了。这个喵喵没有发现简单地办法看出来它有没有触发 Repaint，因为如果把 Repaint flash 打开，其实改变 style 也会闪烁，所以在 Composite 属性改变的时候也会绿绿绿。\n吐槽： Chrome 好像会把 Composite 丢到另外一个后台线程上去做，然后如果 Tab 开太多，这个线程就会比较摸鱼，但是一打开 Profiler 它就不摸了，导致只有在 Profile 的时候跑得快（混乱邪恶：说明打开 Profiler 即可瞬间优化）\n\n总体而言，为了达成常用的动画效果，喵喵的习惯是：\n- 移动: transform: translate\n- 强调 - 渐变: transition: opacity\n- 渐变+隐藏: transition: opacity, 额外用 pointer-events 控制鼠标事件的捕捉\n- 模糊: filter: blur\n- 背景模糊: backdrop-filter: blur (这个在比较新的 Chrome 里支持了，动画也很流畅，但是在最新的 Windows Insider 上会把我的系统打绿屏)\n- 颜色: 如果可能的话，用 filter: hue-rotate\n- 背景渐变: 放一个 :after { position: absolute; }，然后在这个上面 transition: opacity\n- 背景颜色改变: 放一个 :after 和一个 :before，然后控制 :after 的透明度\n- 显示区域变化: transition: clip-path 或者 mask-image + transtiion: mask-position\n剩下如果必须要发生 Repaint 了，一定不要改变定位属性，还有改变 bouding box 的那一堆东西（margin, padding, top, etc.)\n\nReact rendering flow\n老生常谈了。这次 JieLabs 在写的时候所有 React 组件都是用了 React.memo 的函数式组件，用了十万个 Hook，然后叠了个 Redux 管大范围分享的状态。\n写了大半年 React，对 React 组件感觉上除了重用以外，另外还有作为渲染边界使用。在这里讨论 React 的渲染流，即 React component -> V-DOM 这部分。React 是单向向下的渲染流，如果一个组件发生重新渲染，它会通知 React 渲染自己的子组件，React 去拿渲染好的 Cached V-DOM 或者重绘，然后把渲染出来的结果返回。\nReact.memo 作为渲染边界的时候，决定一个子组件是否需要重新渲染是通过属性的 Weak equality。所以写这样的代码就基本 GG：\n<Component\n  prop={list.map(mapper)}\n  cb={e => { /* Literal callback */ }}\n/>\n\n即使 list 是个 immutable list 也一样，因为每次都吐了个新的 mapped list 出来。\n一般而言这样的代码写在一个 HTML 元素上不会有大问题，因为反正每次渲染到底层都得重新算一遍 attribute，然后和 Cached V-DOM 比对，对于 Event listener 而言也不会直接注册到 DOM 上面，而是 React-dom 自己把自己的 Listener 注册上去，然后在里面再调用写在 JSX 里的 callback，所以也不会涉及 DOM 上 listener 的注册/注销。但是放到 Component 上，这么写肯定和上次渲染不满足 Weak equality，所以子组件一定会重绘，即使最后渲染出来结果一样。\n那么怎么办呢？一个办法是所有东西都丢到 Redux 里，Redux 里面同时存原数据和一个 map 过的数据，用 Action 控制更新的原子性。此时，无论是用 connect 还是 useSelector，Redux 会帮忙通过一个 weak equality 决定是否需要通知重绘。\n但是当然还是单一 source of truth 比较好，而且 Redux 里放太多组件自己的不需要持久化的状态就很怪。然后代码里就充满了 useCallback, useMemo, useEffect 之类的垃圾代码。只有这个时候想起了 Vue 的好，自动计算依赖图。当然有一些 Corner case 可以跳过一部分依赖图的节点进行优化，以及显式的决定各种 Hook 回调的通知顺序，这个时候 Vue 就没办法做这些。\n当然，优化到最后就会涉及到状态改变但是不希望重绘的情况（例如 Canvas 正在被隐藏，有一个 useLayoutEffect 是用来画它的，希望暂时暂停）。这个时候感觉没有特别好的解决方法，只能把数据存到 useRef 里面，然后真的需要重新渲染的时候 setXX(XXRef.current)\n\nDOM patching\n写 key 这种东西就不用说了，这里要吐槽一些东西。\nDOM 本身是要带状态的，包括 class 导致的 CSS transition。由于 React 是把映射出来的 V-DOM 给 Patch 到 DOM 上。所以写这种代码，就算没写 key，也是可以显示出来一个 loading 类消失的过渡动画的:\nif(loading) return <div className=\"container loading\" />;\n\nreturn (\n  <div className=\"container\">\n    { /* ... */ }\n  </div>\n);\n\n但是用 Suspense 就不行，不知道为什么会不重用 DOM。可能 Suspense 是一套完全不同的渲染方法？\n喵喵反正不太喜欢 Suspense 这种结构，如果以后有等待 Promise 的东西会好用一些。现在只有 React.lazy 加载组件好像没啥用（\n\nInitial load speed\n怎么能够加载的快呢？Cache 是浏览器提供的好东西，但是我们能够通过 Service Worker，实现更加激进的缓存策略。\n\nService worker\nCRA 吐出来的模板自带一个 Workbox，稍微调教了一下让它能够从本地加载 Workbox 库，而不是隔着万里长城去找 Google CDN。\n为了让加载比较快，选择的 Workbox 缓存策略非常激进，用 Local only，做 Pre-caching，包括 index.html 都从 Cache 返回。一般而言这样的行为会导致页面没办法更新，也就是就算 index.html 里面的 version string (文件名内的 hash 或者 query string) 发生改变，也不会被浏览器察觉。\n解决更新问题的方法是在安装的时候加载一下 manifest。由于 manifest 和所有的 asset 文件名都有 hashing，如果服务器上的 asset 更新了，那么 service worker 的代码一定会变，这个时候让它在后台安装，预先下载好资源，然后显示一个刷新通知。\n这样的设计的结果包括：\n- 只有 Asset 更新的时候需要向服务器请求\n- 只有第一次加载的时候，Asset 请求会阻塞渲染流\n这个渲染流不只包括 DOM 渲染，也包括 React 的渲染。所有的字体都是用 Webpack 包了一下，因此除了第一次访问，以后每次刷新的时候应该都是瞬间加载的。\n所以我们需要 Care 的就是第一次加载到渲染出有效内容之中，加载的内容。这分为两部分：加载出来“加载页面”，和 React 渲染出来有效内容。\n\nCritical style\n浏览器一般（写Web的时候什么东西都是一般…）如果没有明确指定（defer），在加载 HTML 的时候同时渲染，其中同步加载、执行脚本，异步加载 <link rel=\"stylesheet\">。这里加载、解析、执行脚本的时候需要阻塞接下来 HTML 的渲染，但是不会阻塞渲染线程本身。\n所以如果我们认为一些 HTML 元素是需要在脚本加载、执行完成之前显示出来，需要把它写到 <script> 标签前面。\nWebpack 会按照程序入口开始的依赖图，向 HTML 里注入一个或者多个 <script>，没有 defer。CRA 默认会把这些标签注入到 body 的结尾，因此我们在 body 开头写的 HTML 元素，是可以很快显示出来的。这个时间中，我们能控制的因素是这个标签前面的字节数。因此放的越靠前，加载出来更快。\n麻烦的是样式表。一般而言，我们把初始显示时就需要的样式称为 Critical style，在静态页面中传统意义上指不滚动的第一屏中显示的内容需要的样式。\n<link> 里的样式表永远异步加载，然后加载完成后应用新样式。所以为了保证样式是有效的，我们需要把这部分样式表内联到 <style> 标签里，这样可以保证样式表先于标签加载出来。\n在 Webpack 里完成这件事也比较麻烦，ExtractTextPlugin 或者 MiniCSSPlugin 只会生成 <link> 标签，style-loader 会生成一个用 JS 注入的代码，喂这个要在 JS 加载开始之前就渲染好啊。\n还好 HTMLWebpackPlugin 可以写 ejs 语法，而且可以干奇怪的事情：\n<style>\n  <%= require('!!css-loader!sass-loader!../src/prelude.scss') %>\n</style>\n\n这里用了 Webpack 的一个特殊语法:\n- !! 表示禁用所有配置里写好的 loader，这里 scss 默认是 ['style', 'css', 'sass']\n- 之后，只执行 sass -> css 两个 loader，得到一个字符串，然后就内嵌进来了\n另一个据说可行的方法是添加一个 entry，然后指定特殊的 loader，但是我们没有找到 customize-cra 里面怎么加 entry，因此没有考证这个方法是否可行。\n\nCode splitting\n现在加载页面已经加载了（笑），我们需要加快 React 渲染出来有效内容的速度。\nWebpack 会把内容拆分成不同的 Chunk，然后每个 Chunk 加载完了一起解析执行。一般而言 Webpack 的分块策略是所有 node_modules 放到一起，剩下的代码积极分块，这样的理由是如果应用代码更新了，绝大多数 Asset 不需要重新下载。但是我们重新下载的延迟都用 Service worker 藏起来了，而且按照默认分块方法，Monaco 需要一开始就加载，这是最大的一块儿内容。\n渲染出来有效内容可能要做这些事情：\n- Redux 创建 store\n- 加载编辑器、 Verilog / VHDL 语言支持\n- 加载 WASM 模块\n- 加载两个 Route:- Login\n- Workspace\n\n- Redux store 初始化，尝试向服务器询问是否已登录\n由于是初次加载，肯定没有登录。因此只有 Login Route 会用到。编辑器只在 Workspace 里和构建详情里用到，因此也可以延迟加载。 WASM 同样只在编辑器里用到，因此也延迟加载。最后的结果是，我们相当于需要在加载过程中插入这么几个 yield point:\n- App 请求加载 Workspace 时\n- App 请求加载 Monaco 时\n- App 请求加载 WASM 时\n其中，最后一个因为本来就是用 redux 加载完放到 state 里的，直接不 await 到它上面就行了。\n第一个需要 Webpack 的一些特性：使用 const ModulePromise = import('./module') 加载的模块，可以分到一个不同的 chunk 中。\n第二个最麻烦，因为我们不仅需要一个 async import，还需要把 Monaco 从 vendor chunk 里拆出来。这个时候需要额外配置一下 Webpack，强制把 Monaco 自己分一个 chunk:\nsetWebpackOptimizationSplitChunks({\n  chunks: 'all',\n  name: false,\n\n  cacheGroups: {\n    monaco: {\n      test: /[\\\\/]node_modules[\\\\/]monaco-editor/,\n      reuseExistingChunk: false,\n    },\n  },\n}),\n\n对于延迟加载的模块，可以造一个 React hook:\nfunction useLoader(loader) {\n  const [Comp, setComp] = useState(null);\n  useEffect(() => {\n    loader.then(mod => {\n      setComp(() => mod.default);\n    });\n  }, []);\n\n  const Nullify = useCallback(() => null, []);\n\n  return Comp || Nullify;\n}\n\nconst WorkspaceLoader = import('./routes/Workspace');\n\n// Somewhere within App component:\n\nconst Worksapce = useLoader(WorkspaceLoader);\n\n这样写即使 App 没有被渲染，也会积极加载 Workspace，但是不会阻塞程序入口所在 chunk 的解析和执行。\n"},{"metadata":{"id":"hello-2020","lang":"zh-CN","title":"2020","tags":["扯淡"],"publish_time":"2019-12-31T16:19:15.102Z","update_time":"2019-12-31T16:19:52.419Z","title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612}],"text":"2020","hadv":2450,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>到了31号晚上忽然想起来还要写 Year in Review / New year resolution，甚至得翻到去年的才能想起来标题到底写 2020 还是 2019，实在是丢人。 But here it comes.</p>\n<p>2019 是忙碌的一年，仔细一想又什么事情都没有做，就结束奔三长跑的第一年了。翻了翻 GitHub 的历史，去年上半年上了我超喜欢的两节课，密码学和存储，接了几个皮条，这些印象全都没有了。反而记得最清楚的是去年元旦在 bgm 上发了自己写的 tty client，以及儿童节给妹子做的 Chrome 养猫小插件，看来还是讲相声比较适合我。下半年摸过了龙芯杯，又抱大腿造了好慢好慢的 CPU 还有路由器，还有小半个没写完的编译器，在追逐的过程中，呼啦一下半年就过去了，忙到连选课都忘了选。也许过两天会发几个跟这几个项目相关的博客？也许有，也许没有，因为仔细想想还真没什么好介绍的——抄别人的部分自然不必说，自己拍脑袋想出来的也肯定没啥价值就是了，毕竟只是一个在读本科的喵喵而已。</p>\n<p>接近 2020 年了，终于打开了 15 周没有登录的 steam，想起了硬盘里的女孩子立绘们。好久没有看书，没有看电影，全身干巴巴的感觉，对新年的展望也是干巴巴的感觉，一点仪式感都没有，满脑子都是什么“啊要多了解世界”，“啊要对别人温柔”这样跟古神的低语一样的东西，有点无聊呢！一点没有被地铁上小姑娘叫了大叔的人的级别的沉稳感，也没有文艺青年的丧气劲头，这样不行。</p>\n<p>那么就把愿望设置成<strong>变得有趣</strong>吧！也许能够保持乐观，也许能够更加深刻，也许能够做出有意义的事情，也许中的也许，能够成为某人前进的力量或方向。毕竟在这一年当中，喵喵收到我所爱的人的照顾，实在是太多太多了，如果变得无聊地平凡，实在是太对不起他们了。</p>\n<p>虽然是这么向往的，但是为 2019 年画上句号的是第十六周搬着服务器在楼梯上脚底一疼，差点和服务器一起从 8500 的楼梯上滚下来。第二天慢慢悠悠自己走到医院一检查，“疲劳性骨折”，第三天就熟练的拄拐走进编译原理的考试了。结果是脑残比脚残更严重，所有题目中间我最难。</p>\n<p>电脑的时钟跨过 0 点了，虽然没有钟声，但是还是到此为止吧！忽然有一点想看烟花了，隐隐约约觉得在夏天看最好。北京应该很难做到了？想想办法把它实现了吧。</p>\n","plain":"到了31号晚上忽然想起来还要写 Year in Review / New year resolution，甚至得翻到去年的才能想起来标题到底写 2020 还是 2019，实在是丢人。 But here it comes.\n2019 是忙碌的一年，仔细一想又什么事情都没有做，就结束奔三长跑的第一年了。翻了翻 GitHub 的历史，去年上半年上了我超喜欢的两节课，密码学和存储，接了几个皮条，这些印象全都没有了。反而记得最清楚的是去年元旦在 bgm 上发了自己写的 tty client，以及儿童节给妹子做的 Chrome 养猫小插件，看来还是讲相声比较适合我。下半年摸过了龙芯杯，又抱大腿造了好慢好慢的 CPU 还有路由器，还有小半个没写完的编译器，在追逐的过程中，呼啦一下半年就过去了，忙到连选课都忘了选。也许过两天会发几个跟这几个项目相关的博客？也许有，也许没有，因为仔细想想还真没什么好介绍的——抄别人的部分自然不必说，自己拍脑袋想出来的也肯定没啥价值就是了，毕竟只是一个在读本科的喵喵而已。\n接近 2020 年了，终于打开了 15 周没有登录的 steam，想起了硬盘里的女孩子立绘们。好久没有看书，没有看电影，全身干巴巴的感觉，对新年的展望也是干巴巴的感觉，一点仪式感都没有，满脑子都是什么“啊要多了解世界”，“啊要对别人温柔”这样跟古神的低语一样的东西，有点无聊呢！一点没有被地铁上小姑娘叫了大叔的人的级别的沉稳感，也没有文艺青年的丧气劲头，这样不行。\n那么就把愿望设置成变得有趣吧！也许能够保持乐观，也许能够更加深刻，也许能够做出有意义的事情，也许中的也许，能够成为某人前进的力量或方向。毕竟在这一年当中，喵喵收到我所爱的人的照顾，实在是太多太多了，如果变得无聊地平凡，实在是太对不起他们了。\n虽然是这么向往的，但是为 2019 年画上句号的是第十六周搬着服务器在楼梯上脚底一疼，差点和服务器一起从 8500 的楼梯上滚下来。第二天慢慢悠悠自己走到医院一检查，“疲劳性骨折”，第三天就熟练的拄拐走进编译原理的考试了。结果是脑残比脚残更严重，所有题目中间我最难。\n电脑的时钟跨过 0 点了，虽然没有钟声，但是还是到此为止吧！忽然有一点想看烟花了，隐隐约约觉得在夏天看最好。北京应该很难做到了？想想办法把它实现了吧。\n"},{"metadata":{"id":"chisel3-pitfalls","lang":"zh-CN","title":"Chisel3 踩坑实录","tags":["踩坑"],"publish_time":"2019-12-01T15:01:20.119Z","update_time":"2020-03-21T04:35:43.490Z","title_outline":{"groups":[{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"3","components":[["M 283 17C 454 17 559 -67 559 -189C 559 -307 488 -389 279 -400L 279 -384C 468 -401 536 -482 536 -587C 536 -690 461 -764 303 -764C 181 -764 76 -713 73 -593C 84 -574 104 -562 129 -562C 164 -562 195 -579 204 -630L 224 -733L 161 -708C 198 -723 229 -730 256 -730C 332 -730 377 -680 377 -581C 377 -462 318 -408 230 -408L 196 -408L 196 -369L 235 -369C 337 -369 391 -306 391 -188C 391 -76 334 -18 231 -18C 196 -18 174 -26 145 -41L 196 -12L 178 -120C 169 -187 144 -207 104 -207C 78 -207 52 -193 41 -161C 50 -49 131 17 283 17Z",[0.011,0.423]]],"bbox":{"top":-764,"bottom":17,"left":41,"right":559},"hadv":612}],"text":"Chisel3","hadv":3842,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"踩","components":[["M 22 -74L 82 82C 95 79 106 68 111 55C 263 -21 363 -86 434 -137L 432 -147C 277 -110 103 -82 22 -74Z",[0.638,0.231]],["M 178 -380L 56 -391L 56 -33L 158 -55L 158 -363C 173 -366 177 -372 178 -380Z",[0.01,0.701]],["M 62 -840L 62 -470L 83 -470C 143 -470 179 -495 179 -503L 179 -779L 193 -779Z",[-0.01,0.657]],["M 351 -544L 124 -544L 124 -513L 351 -513Z",[-0.787,0.02]],["M 351 -779L 124 -779L 124 -751L 351 -751Z",[-0.522,0.029]],["M 299 -531L 184 -531L 184 -66L 299 -96Z",[0.008,0.744]],["M 351 -406L 300 -324L 247 -324L 247 -296L 413 -296C 427 -296 437 -301 440 -312C 409 -349 351 -406 351 -406Z",[-0.625,0.02]],["M 280 -779L 290 -779L 290 -484L 310 -484C 348 -484 407 -505 408 -512L 408 -734C 426 -738 439 -746 444 -753L 333 -836Z",[0.02,0.624]],["M 733 -340L 733 -356L 581 -356C 547 -217 477 -71 373 26L 382 37C 555 -50 676 -177 733 -340Z",[0.427,0.594]],["M 869 -453L 809 -367L 409 -367L 417 -339L 951 -339C 965 -339 975 -344 978 -355C 938 -394 869 -453 869 -453Z",[0.854,0.054]],["M 960 -720L 819 -861C 736 -813 569 -746 439 -712L 440 -701C 591 -696 771 -706 885 -723C 920 -709 946 -710 960 -720Z",[0.591,0.132]],["M 452 -664L 442 -660C 460 -614 477 -550 475 -492C 568 -400 697 -581 452 -664Z",[-0.179,0.362]],["M 600 -686L 591 -682C 611 -637 631 -575 631 -518C 733 -422 867 -618 600 -686Z",[-0.1,0.341]],["M 786 -452L 621 -467L 621 96L 647 96C 696 96 758 70 758 60L 758 -430C 779 -433 784 -441 786 -452Z",[0.012,0.727]],["M 755 -358L 745 -354C 767 -188 803 -56 875 34C 894 -32 930 -72 979 -84L 982 -94C 892 -146 800 -240 755 -358Z",[-0.254,0.468]],["M 981 -629L 815 -702C 808 -653 785 -549 766 -482L 773 -478C 836 -518 907 -579 942 -614C 964 -610 977 -619 981 -629Z",[0.279,0.385]]],"bbox":{"top":-861,"bottom":96,"left":22,"right":982},"hadv":1000}],"text":"踩","hadv":1000,"breakAfter":true},{"chars":[{"char":"坑","components":[["M 16 -217L 89 -55C 102 -59 113 -70 118 -83C 266 -172 364 -240 423 -289L 422 -298C 255 -261 84 -228 16 -217Z",[0.599,0.242]],["M 324 -663L 271 -568L 21 -568L 29 -540L 387 -540C 401 -540 411 -545 414 -556C 384 -597 324 -663 324 -663Z",[0.813,0.087]],["M 310 -823L 134 -838L 134 -170L 273 -214L 273 -794C 301 -799 308 -809 310 -823Z",[0.011,0.781]],["M 448 -510L 448 -337C 448 -190 417 -34 218 88L 224 97C 549 -3 582 -194 582 -338L 582 -500L 602 -500L 448 -553Z",[0.211,0.69]],["M 851 -760L 776 -655L 358 -655L 366 -627L 954 -627C 969 -627 980 -632 983 -643C 935 -690 851 -760 851 -760Z",[0.749,0.089]],["M 525 -853L 518 -848C 549 -807 574 -745 576 -687C 699 -588 834 -825 525 -853Z",[-0.199,0.244]],["M 751 -500L 529 -500L 529 -472L 751 -472Z",[-0.661,0.083]],["M 687 -500L 699 -500L 699 -43C 699 37 711 64 796 64L 843 64C 940 64 984 36 984 -14C 984 -39 978 -53 950 -68L 947 -208L 936 -208C 920 -152 903 -93 893 -76C 887 -66 882 -64 876 -64C 871 -63 866 -63 860 -63L 843 -63C 833 -63 830 -68 830 -80L 830 -461C 850 -464 860 -470 866 -478L 750 -572Z",[-0.113,0.631]]],"bbox":{"top":-853,"bottom":97,"left":16,"right":984},"hadv":1000}],"text":"坑","hadv":1000,"breakAfter":true},{"chars":[{"char":"实","components":[["M 170 -743L 160 -743C 161 -704 116 -667 84 -652C 42 -634 11 -597 24 -546C 40 -492 106 -473 145 -496C 199 -528 224 -619 170 -743Z",[0.171,0.314]],["M 662 -617L 466 -634C 465 -297 489 -83 24 82L 30 95C 625 -23 616 -247 626 -589C 649 -593 660 -602 662 -617Z",[0.325,0.62]],["M 818 -365L 741 -257L 56 -257L 64 -229L 927 -229C 942 -229 954 -234 957 -245C 906 -293 818 -365 818 -365Z",[0.899,0.048]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 170 -453L 164 -448C 202 -410 240 -349 250 -290C 384 -206 491 -461 170 -453Z",[-0.27,0.26]],["M 244 -618L 237 -612C 271 -578 307 -520 316 -467C 439 -390 540 -622 244 -618Z",[-0.187,0.226]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 512 -188L 509 -178C 648 -96 756 17 795 79C 937 157 1059 -145 512 -188Z",[-0.529,0.36]],["M 780 -680L 791 -680C 790 -638 784 -567 777 -520L 783 -514C 834 -541 899 -587 937 -622C 958 -623 968 -626 976 -635L 851 -752Z",[-0.442,0.364]]],"bbox":{"top":-871,"bottom":157,"left":11,"right":1059},"hadv":1000}],"text":"实","hadv":1000,"breakAfter":true},{"chars":[{"char":"录","components":[["M 834 -592L 753 -492L 36 -492L 44 -464L 951 -464C 966 -464 978 -469 981 -480C 925 -526 834 -592 834 -592Z",[0.88,0.042]],["M 39 -118L 144 20C 156 14 164 2 166 -12C 331 -135 436 -228 502 -294L 498 -304C 308 -221 118 -145 39 -118Z",[0.624,0.363]],["M 705 -791L 139 -791L 148 -763L 705 -763Z",[0.633,0.024]],["M 153 -437L 146 -432C 182 -390 217 -324 226 -263C 354 -174 469 -419 153 -437Z",[-0.265,0.301]],["M 698 -637L 170 -637L 179 -609L 698 -609Z",[0.715,0.02]],["M 569 -74L 569 -492L 424 -492L 424 -77C 424 -67 419 -60 404 -60C 381 -60 270 -66 270 -66L 270 -54C 327 -44 349 -28 365 -8C 382 13 388 47 390 93C 546 82 569 19 569 -74Z",[0.072,0.691]],["M 563 -475L 557 -472C 605 -195 700 -71 857 25C 872 -42 911 -95 967 -110L 970 -120C 809 -160 627 -245 563 -475Z",[-0.471,0.476]],["M 618 -791L 628 -791L 612 -478L 763 -478L 776 -741C 798 -744 806 -748 814 -758L 674 -859Z",[0.04,0.56]],["M 917 -348L 773 -448C 749 -398 695 -309 650 -252L 659 -243C 736 -269 820 -307 878 -338C 902 -333 912 -339 917 -348Z",[0.418,0.291]]],"bbox":{"top":-859,"bottom":93,"left":36,"right":981},"hadv":1000}],"text":"录","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>简单记一下最近写 Chisel3 遇到的各种各样玄学问题，作为参考。</p>\n<ol>\n<li>Verilator 是唯一一个可以正常仿真 SyncReadMem 而且可以输出波形图的后端，而且跑得很快，问题是 printf 的时候会丢东西，所以如果用 printf 调试，treadle 比较好</li>\n<li>Mem[Vec[T]] 比 Seq[Mem[T]] 好，后者在 Verilator 里 VecInit(mems.map…) 可能读不出来东西，生成出来时序也不太行，但是前者的信号名字会有个前缀</li>\n<li>Mux1H is a thing, 生成出来的时序比 MuxCase(seq.map(f)) 效果好很多</li>\n<li>ChiselEnum 甚至时序会好一些，神秘</li>\n</ol>\n<p>然后是一些犄角旮旯里的东西：</p>\n<h2>MultiIOModule</h2>\n<p>就不用把十万个信号都写到同一个 val io 里面了。比如如果在写处理器的 InstrFetch:</p>\n<div class=\"highlighted highlighted-scala\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-scala\"><span style=\"color:#268bd2;\">class </span><span style=\"color:#b58900;\">InstrFetch</span><span style=\"color:#839496;\">(</span><span style=\"color:#93a1a1;\">implicit </span><span style=\"color:#268bd2;\">val opts</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">CoreOpts</span><span style=\"color:#839496;\">) </span><span style=\"color:#859900;\">extends </span><span style=\"color:#268bd2;\">MultiIOModule </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">toCtrl </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">IO</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">new Bundle </span><span style=\"color:#657b83;\">{ </span><span style=\"color:#586e75;\">/* ... */ </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">)\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">toL1IC </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">IO</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">new Bundle </span><span style=\"color:#657b83;\">{ </span><span style=\"color:#586e75;\">/* ... */ </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">)\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">toExec </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">IO</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">new Bundle </span><span style=\"color:#657b83;\">{ </span><span style=\"color:#586e75;\">/* ... */ </span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">)\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>然后在外面就可以</p>\n<div class=\"highlighted highlighted-scala\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-scala\"><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">instrfetch </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">Module</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">new InstrFetch</span><span style=\"color:#839496;\">())\n</span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">l1ic </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">Module</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">new L1IC</span><span style=\"color:#839496;\">())\n</span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">exec </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">Module</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">new Exec</span><span style=\"color:#839496;\">())\n</span><span style=\"color:#586e75;\">/* ... */\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">instrfetch.toL1IC &lt;&gt; l1ic.toIF\n</span><span style=\"color:#839496;\">instrfetch.toExec &lt;&gt; exec.toIF\n</span><span style=\"color:#586e75;\">/* ... */\n</span></code></pre>\n</div>\n<h2>Memory elaboration</h2>\n<p>SyncReadMem 通常会被 Vivado 整成 BRAM, Mem 会被整成 LUTRAM，但是前提是，读取口和写入口的数量有限。例如如果要求零周期，但是同时最多可能有两个并发写入口的话，就会被整成 Register bank。</p>\n<p>读取口的复用应该是 firrtl 可以完成的优化，但是有的时候这个优化不生效。即使是两个互斥条件下的写入也会被 firrtl 生成两个写入口，然后就爆炸。例如这种：</p>\n<div class=\"highlighted highlighted-scala\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-scala\"><span style=\"color:#839496;\">when(cond) </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  mem.write(addr, data1);\n</span><span style=\"color:#657b83;\">}</span><span style=\"color:#839496;\">.otherwise </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  mem.write(addr, data2)\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<p>这个可能会生成两个写入口。因此写成这样更好</p>\n<div class=\"highlighted highlighted-scala\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-scala\"><span style=\"color:#839496;\">mem.write(addr, </span><span style=\"color:#859900;\">Mux</span><span style=\"color:#839496;\">(cond, data1, data2))\n</span></code></pre>\n</div>\n<p>或者用另外一个 wire 控制写入。</p>\n<div class=\"highlighted highlighted-scala\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-scala\"><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">writing </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">Wire</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">Bool</span><span style=\"color:#839496;\">())\n</span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">waddr </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">Wire</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">UInt</span><span style=\"color:#839496;\">())\n</span><span style=\"color:#268bd2;\">val </span><span style=\"color:#b58900;\">wdata </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">Wire</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">UInt</span><span style=\"color:#839496;\">())\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#839496;\">mem.write(waddr, wdata, writing)\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">// Default value\n</span><span style=\"color:#839496;\">writing := </span><span style=\"color:#b58900;\">false</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">B\n</span><span style=\"color:#839496;\">waddr := </span><span style=\"color:#859900;\">DontCare\n</span><span style=\"color:#839496;\">wdata := </span><span style=\"color:#859900;\">DontCare\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#268bd2;\">def </span><span style=\"color:#b58900;\">write</span><span style=\"color:#839496;\">(addr, data) </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  waddr := addr\n</span><span style=\"color:#839496;\">  wdata := data\n</span><span style=\"color:#839496;\">  writing := </span><span style=\"color:#b58900;\">true</span><span style=\"color:#839496;\">.</span><span style=\"color:#859900;\">B\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<h2>Memory mask</h2>\n<p>如果 Memory 的类型是一个 <code>Vec[T]</code>，传进去的第三个参数就可以是一个 <code>Vec[Bool]</code> 表示写入 mask。如果不是一个 <code>Vec[T]</code>，第三个参数可以是一个 <code>Bool</code></p>\n","plain":"简单记一下最近写 Chisel3 遇到的各种各样玄学问题，作为参考。\n- Verilator 是唯一一个可以正常仿真 SyncReadMem 而且可以输出波形图的后端，而且跑得很快，问题是 printf 的时候会丢东西，所以如果用 printf 调试，treadle 比较好\n- Mem[Vec[T]] 比 Seq[Mem[T]] 好，后者在 Verilator 里 VecInit(mems.map…) 可能读不出来东西，生成出来时序也不太行，但是前者的信号名字会有个前缀\n- Mux1H is a thing, 生成出来的时序比 MuxCase(seq.map(f)) 效果好很多\n- ChiselEnum 甚至时序会好一些，神秘\n然后是一些犄角旮旯里的东西：\n\nMultiIOModule\n就不用把十万个信号都写到同一个 val io 里面了。比如如果在写处理器的 InstrFetch:\nclass InstrFetch(implicit val opts: CoreOpts) extends MultiIOModule {\n  val toCtrl = IO(new Bundle { /* ... */ })\n  val toL1IC = IO(new Bundle { /* ... */ })\n  val toExec = IO(new Bundle { /* ... */ })\n}\n\n然后在外面就可以\nval instrfetch = Module(new InstrFetch())\nval l1ic = Module(new L1IC())\nval exec = Module(new Exec())\n/* ... */\n\ninstrfetch.toL1IC <> l1ic.toIF\ninstrfetch.toExec <> exec.toIF\n/* ... */\n\n\nMemory elaboration\nSyncReadMem 通常会被 Vivado 整成 BRAM, Mem 会被整成 LUTRAM，但是前提是，读取口和写入口的数量有限。例如如果要求零周期，但是同时最多可能有两个并发写入口的话，就会被整成 Register bank。\n读取口的复用应该是 firrtl 可以完成的优化，但是有的时候这个优化不生效。即使是两个互斥条件下的写入也会被 firrtl 生成两个写入口，然后就爆炸。例如这种：\nwhen(cond) {\n  mem.write(addr, data1);\n}.otherwise {\n  mem.write(addr, data2)\n}\n\n这个可能会生成两个写入口。因此写成这样更好\nmem.write(addr, Mux(cond, data1, data2))\n\n或者用另外一个 wire 控制写入。\nval writing = Wire(Bool())\nval waddr = Wire(UInt())\nval wdata = Wire(UInt())\n\nmem.write(waddr, wdata, writing)\n\n// Default value\nwriting := false.B\nwaddr := DontCare\nwdata := DontCare\n\ndef write(addr, data) {\n  waddr := addr\n  wdata := data\n  writing := true.B\n}\n\n\nMemory mask\n如果 Memory 的类型是一个 Vec[T]，传进去的第三个参数就可以是一个 Vec[Bool] 表示写入 mask。如果不是一个 Vec[T]，第三个参数可以是一个 Bool\n"},{"metadata":{"id":"sort-by-pinyin-in-js","lang":"zh-CN","title":"拼音排序 \\w JavaScript","tags":["踩坑"],"publish_time":"2019-07-03T00:07:58.484Z","update_time":"2019-07-30T10:23:12.884Z","title_outline":{"groups":[{"chars":[{"char":"拼","components":[["M 15 -384L 64 -218C 77 -221 89 -233 94 -246C 242 -334 345 -406 406 -454L 404 -463C 246 -427 78 -394 15 -384Z",[0.617,0.261]],["M 137 -856L 137 -67C 137 -56 133 -52 119 -52C 100 -52 22 -57 22 -57L 22 -44C 65 -35 82 -21 94 -1C 107 20 111 52 113 95C 253 83 272 34 272 -58L 272 -811C 297 -815 307 -825 309 -840Z",[0.029,0.841]],["M 26 -615L 34 -587L 393 -587C 407 -587 417 -592 420 -603C 386 -643 322 -706 322 -706L 267 -615Z",[0.854,0.077]],["M 456 -615L 456 -363C 456 -200 438 -37 290 91L 297 98C 575 -11 599 -201 599 -364L 599 -615Z",[0.14,0.746]],["M 326 -356L 334 -328L 965 -328C 980 -328 990 -333 993 -344C 951 -385 879 -446 879 -446L 815 -356Z",[0.895,0.049]],["M 363 -618L 371 -590L 946 -590C 960 -590 971 -595 974 -606C 931 -647 856 -708 856 -708L 791 -618Z",[0.899,0.067]],["M 426 -846L 418 -841C 449 -792 476 -722 477 -656C 594 -556 726 -786 426 -846Z",[-0.16,0.34]],["M 718 -855C 703 -772 680 -678 662 -621L 673 -614C 735 -652 801 -710 855 -774C 878 -773 892 -781 896 -794Z",[0.308,0.106]],["M 682 -615L 682 95L 709 95C 783 95 826 67 827 59L 827 -615Z",[0.008,0.772]]],"bbox":{"top":-856,"bottom":98,"left":15,"right":993},"hadv":1000}],"text":"拼","hadv":1000,"breakAfter":true},{"chars":[{"char":"音","components":[["M 831 -573L 756 -474L 38 -474L 46 -446L 939 -446C 953 -446 965 -451 968 -462C 917 -507 831 -573 831 -573Z",[0.918,0.04]],["M 798 -808L 725 -713L 82 -713L 90 -685L 901 -685C 916 -685 927 -690 930 -701C 881 -744 798 -808 798 -808Z",[0.897,0.046]],["M 350 47L 350 -317L 749 -317L 749 -345L 358 -345L 205 -404L 205 93L 226 93C 287 93 350 61 350 47Z",[0.191,0.319]],["M 261 -692L 253 -688C 278 -637 300 -570 301 -505C 418 -399 563 -626 261 -692Z",[-0.153,0.33]],["M 728 -13L 258 -13L 258 15L 728 15Z",[0.94,0.0]],["M 728 -181L 258 -181L 258 -153L 728 -153Z",[0.929,0.001]],["M 401 -858L 395 -853C 417 -824 442 -776 447 -730C 570 -645 696 -870 401 -858Z",[-0.031,0.126]],["M 804 -638L 620 -694C 606 -628 579 -531 553 -467L 564 -467C 635 -511 717 -575 766 -620C 789 -618 800 -626 804 -638Z",[0.356,0.427]],["M 638 -345L 649 -345L 649 88L 675 88C 731 88 801 52 802 41L 802 -291C 824 -296 837 -306 844 -314L 707 -420Z",[0.016,0.656]]],"bbox":{"top":-870,"bottom":93,"left":38,"right":968},"hadv":1000}],"text":"音","hadv":1000,"breakAfter":true},{"chars":[{"char":"排","components":[["M 300 -839L 128 -855L 128 -85C 128 -75 124 -70 109 -70C 89 -70 3 -75 3 -75L 3 -61C 48 -52 67 -37 81 -13C 94 10 99 44 102 93C 245 79 263 25 263 -72L 263 -811C 288 -814 298 -824 300 -839Z",[0.033,0.836]],["M 14 -380L 68 -224C 81 -228 91 -241 95 -254C 227 -346 319 -423 374 -473L 372 -482C 227 -436 72 -393 14 -380Z",[0.564,0.305]],["M 301 -695L 252 -615L 21 -615L 29 -587L 361 -587C 374 -587 384 -592 387 -603C 357 -639 301 -695 301 -695Z",[0.718,0.082]],["M 537 -217L 324 -217L 333 -189L 537 -189Z",[-0.89,0.008]],["M 531 -442L 347 -442L 356 -414L 531 -414Z",[0.73,0.018]],["M 530 -648L 360 -648L 369 -620L 530 -620Z",[0.796,0.002]],["M 642 -838L 471 -855L 471 94L 496 94C 547 94 605 61 605 48L 605 -810C 632 -814 640 -824 642 -838Z",[0.005,0.849]],["M 840 -835L 669 -852L 669 97L 694 97C 745 97 803 64 803 51L 803 -807C 830 -811 838 -821 840 -835Z",[0.005,0.847]],["M 875 -736L 817 -648L 754 -648L 754 -620L 951 -620C 965 -620 975 -625 978 -636C 941 -676 875 -736 875 -736Z",[-0.179,0.05]],["M 877 -306L 819 -218L 756 -218L 756 -190L 953 -190C 967 -190 977 -195 980 -206C 943 -246 877 -306 877 -306Z",[-0.476,0.022]],["M 868 -524L 814 -444L 756 -444L 756 -416L 936 -416C 950 -416 960 -421 963 -432C 929 -469 868 -524 868 -524Z",[0.438,0.114]]],"bbox":{"top":-855,"bottom":97,"left":3,"right":980},"hadv":1000}],"text":"排","hadv":1000,"breakAfter":true},{"chars":[{"char":"序","components":[["M 98 -688L 98 -424C 98 -253 95 -59 15 92L 23 98C 232 -40 243 -258 243 -424L 243 -678L 264 -678L 98 -734Z",[0.074,0.796]],["M 854 -773L 785 -678L 180 -678L 180 -650L 949 -650C 963 -650 974 -655 977 -666C 932 -709 854 -773 854 -773Z",[0.883,0.044]],["M 831 -338L 256 -338L 265 -310L 831 -310Z",[0.88,0.012]],["M 746 -580L 295 -580L 304 -552L 746 -552Z",[0.72,0.018]],["M 639 -59L 639 -338L 492 -338L 492 -62C 492 -52 487 -46 472 -46C 449 -46 336 -53 336 -53L 336 -41C 394 -31 415 -15 432 4C 450 24 455 56 457 100C 615 90 639 32 639 -59Z",[0.101,0.562]],["M 404 -503L 397 -495C 451 -462 518 -399 547 -344C 669 -301 707 -530 404 -503Z",[-0.34,0.24]],["M 426 -856L 420 -851C 456 -809 493 -745 504 -683C 640 -594 756 -851 426 -856Z",[-0.298,0.271]],["M 683 -580L 695 -580C 664 -533 599 -460 550 -415L 556 -409C 644 -433 769 -480 843 -521C 865 -522 875 -525 884 -534L 760 -652Z",[0.483,0.362]],["M 784 -338L 796 -338C 786 -288 761 -205 740 -153L 748 -147C 809 -180 886 -238 931 -282C 952 -283 962 -286 971 -295L 853 -406Z",[0.295,0.353]]],"bbox":{"top":-856,"bottom":100,"left":15,"right":977},"hadv":1000}],"text":"序","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"\\","components":[["M 398 181L 95 -804L 26 -804L 329 181Z",[-0.277,0.895]]],"bbox":{"top":-804,"bottom":181,"left":26,"right":398},"hadv":425}],"text":"\\","hadv":425,"breakAfter":false},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893}],"text":"w","hadv":893,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"J","components":[["M 74 162C 131 162 194 140 248 75C 295 18 317 -49 317 -201L 317 -404C 317 -520 317 -636 321 -747L 151 -747C 154 -423 155 -298 155 -208C 155 -60 159 43 142 134L 142 142L 157 142L 157 136L 111 79C 76 40 58 33 23 33C -14 33 -42 49 -51 93C -44 142 -1 162 74 162Z",[0.111,0.745]],["M 43 -713L 204 -698L 246 -698L 409 -713L 409 -747L 43 -747Z",[-0.888,0.008]]],"bbox":{"top":-747,"bottom":162,"left":-51,"right":409},"hadv":442},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"JavaScript","hadv":5397,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#839496;\">array.</span><span style=\"color:#859900;\">sort</span><span style=\"color:#657b83;\">((</span><span style=\"color:#268bd2;\">a</span><span style=\"color:#839496;\">, </span><span style=\"color:#268bd2;\">b</span><span style=\"color:#657b83;\">) </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#839496;\">a.</span><span style=\"color:#b58900;\">localeCompare</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">b, &#39;</span><span style=\"color:#2aa198;\">zh-Hans-CN-u-co-pinyin</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">))</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<p>… which does not work all the time.</p>\n<h2>Explanation</h2>\n<p>String.localeCompare 可以吃进去第二个参数，是 <a href=\"http://tools.ietf.org/html/rfc5646\">BCP 47 language tag</a></p>\n<p><code>zh-Hans-CN-u-co-pinyin</code> 这个 Locale 意思是：</p>\n<ul>\n<li><code>zh</code>: 是中文</li>\n<li><code>Hans</code>: 简体中文</li>\n<li><code>CN</code>: 大陆地区</li>\n<li><code>u</code>: 启用之后的 Unicode Extension</li>\n<li><code>co</code>: 使用一个 Collation</li>\n<li><code>pinyin</code>: Pinyin Collation</li>\n</ul>\n<p>然后就可以根据拼音排序啦。</p>\n<p>除非在用 Node。如果是 Node，这个<strong>偶尔</strong>工作。</p>\n<h2>With Node</h2>\n<p>比较弱智的方法是用 <code>node-pinyin</code>，这个 Works all the time. 但是其实这个也要依赖一个 GYP Module，所以说到底还是 Platform-dependent</p>\n<p>上面那个 Locale，在 ArchLinux 的 node 上可以用，NodeSource 给的 node  上不能用，也就是 Node Foundation 的 Distribution。观察了一下 PKGBUILD 和 Node Foundation 的 Makefile，发现编译的时候带的 <a href=\"https://nodejs.org/api/intl.html\">ICU 数据</a>不同。</p>\n<p>所以对于只带有部分 ICU 数据的 Node，可以通过另外下载 ICU 数据然后喂给 Node:</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> yarn global add full-icu\n</span><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> NODE_ICU_DATA=</span><span style=\"color:#859900;\">$</span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">dirname </span><span style=\"color:#859900;\">$</span><span style=\"color:#657b83;\">(</span><span style=\"color:#b58900;\">node-full-icu-path</span><span style=\"color:#657b83;\">))\n</span><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> node\n</span><span style=\"color:#586e75;\"># Or with node --icu-data-dir=$(dirname $(node-full-icu-path))\n</span></code></pre>\n</div>\n<p>然后 <code>localeCompare</code> 给出正确结果</p>\n<h2>Alternatives</h2>\n<p><a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator\"><code>Intl.Collator</code></a></p>\n<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#839496;\">array.</span><span style=\"color:#859900;\">sort</span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">new </span><span style=\"color:#268bd2;\">Collator</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">zh-Hans-CN-u-co-pinyin</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">.compare</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>","plain":"array.sort((a, b) => a.localeCompare(b, 'zh-Hans-CN-u-co-pinyin'));\n\n… which does not work all the time.\n\nExplanation\nString.localeCompare 可以吃进去第二个参数，是 BCP 47 language tag\nzh-Hans-CN-u-co-pinyin 这个 Locale 意思是：\n- zh: 是中文\n- Hans: 简体中文\n- CN: 大陆地区\n- u: 启用之后的 Unicode Extension\n- co: 使用一个 Collation\n- pinyin: Pinyin Collation\n然后就可以根据拼音排序啦。\n除非在用 Node。如果是 Node，这个偶尔工作。\n\nWith Node\n比较弱智的方法是用 node-pinyin，这个 Works all the time. 但是其实这个也要依赖一个 GYP Module，所以说到底还是 Platform-dependent\n上面那个 Locale，在 ArchLinux 的 node 上可以用，NodeSource 给的 node  上不能用，也就是 Node Foundation 的 Distribution。观察了一下 PKGBUILD 和 Node Foundation 的 Makefile，发现编译的时候带的 ICU 数据不同。\n所以对于只带有部分 ICU 数据的 Node，可以通过另外下载 ICU 数据然后喂给 Node:\n$ yarn global add full-icu\n$ NODE_ICU_DATA=$(dirname $(node-full-icu-path))\n$ node\n# Or with node --icu-data-dir=$(dirname $(node-full-icu-path))\n\n然后 localeCompare 给出正确结果\n\nAlternatives\nIntl.Collator\narray.sort(new Collator('zh-Hans-CN-u-co-pinyin').compare);\n\n"},{"metadata":{"id":"read-半分の月がのぼる空","lang":"zh-CN","title":"被记忆和普通的花所祝福","tags":["瞎读"],"publish_time":"2019-06-30T08:00:20.988Z","update_time":"2019-06-30T12:49:14.263Z","title_outline":{"groups":[{"chars":[{"char":"被","components":[["M 214 -637L 225 -637C 193 -499 108 -334 7 -227L 15 -216C 182 -305 302 -449 362 -592C 385 -594 394 -597 400 -608L 283 -706Z",[0.392,0.633]],["M 306 -637L 27 -637L 36 -609L 306 -609Z",[0.776,0.001]],["M 98 -857L 91 -852C 120 -814 148 -755 154 -700C 275 -610 398 -839 98 -857Z",[-0.151,0.267]],["M 260 55L 260 -447L 130 -340L 130 95L 154 95C 218 95 260 63 260 55Z",[0.03,0.736]],["M 245 -397L 235 -392C 264 -346 297 -279 305 -221C 400 -147 496 -331 245 -397Z",[-0.273,0.417]],["M 417 -699L 417 -441C 417 -262 405 -68 283 85L 292 92C 531 -45 548 -268 548 -442L 548 -689L 568 -689L 417 -741Z",[0.107,0.8]],["M 454 -435L 338 -505C 322 -454 302 -401 285 -368L 297 -359C 339 -375 379 -399 413 -424C 433 -419 448 -425 454 -435Z",[0.319,0.317]],["M 760 -456L 773 -456C 734 -217 616 -22 370 86L 376 97C 707 20 849 -164 915 -403C 939 -406 949 -409 956 -421L 833 -529Z",[0.434,0.628]],["M 863 -456L 483 -456L 483 -428L 863 -428Z",[0.7,0.064]],["M 880 -689L 491 -689L 491 -661L 880 -661Z",[0.537,0.091]],["M 591 -452L 578 -446C 611 -140 697 -10 863 93C 886 26 930 -17 989 -28L 991 -39C 801 -101 641 -198 591 -452Z",[-0.436,0.51]],["M 786 -833L 614 -847L 614 -439L 749 -439L 749 -804C 777 -809 784 -819 786 -833Z",[0.027,0.657]],["M 807 -689L 818 -689C 816 -647 808 -577 799 -529L 807 -523C 856 -550 913 -598 946 -635C 967 -636 977 -639 985 -648L 871 -755Z",[0.117,0.298]]],"bbox":{"top":-857,"bottom":97,"left":7,"right":991},"hadv":1000}],"text":"被","hadv":1000,"breakAfter":true},{"chars":[{"char":"记","components":[["M 228 -565L 25 -565L 34 -537L 228 -537Z",[-0.711,0.011]],["M 255 -542L 151 -542L 151 -140C 151 -116 143 -105 96 -76L 198 71C 227 51 259 -5 232 -91L 166 -37L 289 -90L 289 -521Z",[0.043,0.753]],["M 105 -852L 98 -846C 144 -795 198 -719 222 -648C 361 -569 454 -831 105 -852Z",[-0.331,0.335]],["M 123 -75L 204 56C 298 -51 367 -153 399 -203L 396 -211C 285 -152 170 -95 123 -75Z",[0.437,0.386]],["M 153 -565L 151 -565L 151 -485L 289 -485L 289 -524L 279 -514C 310 -516 322 -525 329 -533L 216 -627Z",[0.034,0.07]],["M 820 -766L 369 -766L 378 -738L 820 -738Z",[0.589,0.033]],["M 410 -501L 410 -68C 410 27 449 47 578 47L 710 47C 926 47 982 31 982 -28C 982 -52 970 -67 928 -82L 925 -206L 915 -206C 890 -144 871 -104 857 -85C 847 -75 837 -71 820 -70C 801 -69 763 -69 725 -69L 597 -69C 559 -69 550 -74 550 -94L 550 -446L 564 -446L 410 -503Z",[-0.354,0.292]],["M 833 -446L 511 -446L 511 -418L 833 -418Z",[0.789,0.031]],["M 726 -766L 739 -766L 739 -333L 762 -333C 809 -333 880 -356 881 -363L 881 -706C 909 -711 926 -724 935 -734L 793 -843Z",[0.017,0.704]]],"bbox":{"top":-852,"bottom":71,"left":25,"right":982},"hadv":1000}],"text":"记","hadv":1000,"breakAfter":true},{"chars":[{"char":"忆","components":[["M 116 -663L 102 -663C 108 -594 77 -520 50 -491C 21 -469 7 -436 25 -404C 46 -369 99 -369 125 -402C 160 -448 169 -541 116 -663Z",[0.158,0.576]],["M 343 -837L 166 -854L 166 95L 194 95C 247 95 306 68 306 57L 306 -808C 334 -812 341 -823 343 -837Z",[0.004,0.849]],["M 316 -679L 306 -674C 327 -629 345 -565 342 -508C 434 -417 560 -600 316 -679Z",[-0.182,0.38]],["M 728 -747L 741 -747C 465 -362 352 -208 362 -95C 370 12 446 64 620 64L 728 64C 902 64 978 37 978 -30C 978 -59 966 -67 916 -86L 918 -219L 908 -219C 886 -154 865 -107 842 -82C 832 -72 813 -68 738 -68L 620 -68C 556 -68 513 -74 507 -111C 501 -172 595 -334 864 -681C 893 -684 913 -691 924 -701L 791 -818Z",[0.066,0.422]],["M 792 -747L 369 -747L 378 -719L 792 -719Z",[-0.772,0.002]]],"bbox":{"top":-854,"bottom":95,"left":7,"right":978},"hadv":1000}],"text":"忆","hadv":1000,"breakAfter":true},{"chars":[{"char":"和","components":[["M 331 -502L 331 -518L 187 -518C 159 -365 102 -191 17 -74L 27 -64C 177 -174 284 -322 331 -502Z",[0.339,0.666]],["M 416 -613L 352 -518L 36 -518L 44 -490L 503 -490C 518 -490 529 -495 531 -506C 490 -548 416 -613 416 -613Z",[0.751,0.082]],["M 529 -720L 382 -857C 308 -805 159 -731 40 -691L 42 -680C 185 -682 351 -698 455 -721C 491 -708 516 -710 529 -720Z",[0.639,0.13]],["M 352 56L 352 -759L 212 -703L 212 95L 238 95C 307 95 351 64 352 56Z",[0.008,0.829]],["M 346 -420L 337 -415C 365 -369 391 -303 392 -242C 497 -152 618 -357 346 -420Z",[-0.212,0.364]],["M 669 -28L 669 -659L 866 -659L 866 -687L 674 -687L 527 -746L 527 22L 550 22C 612 22 669 -12 669 -28Z",[0.043,0.734]],["M 875 -130L 591 -130L 591 -102L 875 -102Z",[0.893,0.006]],["M 760 -687L 770 -687L 770 7L 794 7C 845 7 913 -23 915 -33L 915 -636C 935 -641 948 -649 954 -658L 825 -759Z",[0.015,0.759]]],"bbox":{"top":-857,"bottom":95,"left":17,"right":954},"hadv":1000}],"text":"和","hadv":1000,"breakAfter":true},{"chars":[{"char":"普","components":[["M 31 -408L 39 -380L 943 -380C 958 -380 969 -385 972 -396C 924 -437 846 -496 846 -496L 777 -408Z",[0.952,0.033]],["M 75 -691L 83 -663L 913 -663C 927 -663 938 -668 941 -679C 894 -718 818 -774 818 -774L 751 -691Z",[0.902,0.026]],["M 150 -634L 142 -629C 167 -586 189 -524 188 -466C 294 -371 426 -578 150 -634Z",[-0.14,0.336]],["M 202 -299L 202 94L 223 94C 282 94 344 63 344 50L 344 -271L 738 -271L 738 -299L 352 -299L 202 -356Z",[0.222,0.273]],["M 265 -851L 258 -846C 287 -810 317 -754 323 -701C 440 -619 553 -839 265 -851Z",[-0.143,0.237]],["M 264 -158L 264 -130L 739 -130L 739 -158Z",[-0.951,0.001]],["M 264 -7L 264 21L 739 21L 739 -7Z",[0.941,0.0]],["M 326 -691L 326 -395L 459 -395L 459 -691Z",[-0.009,0.543]],["M 533 -691L 533 -395L 668 -395L 668 -691Z",[-0.012,0.546]],["M 583 -857C 574 -807 556 -733 541 -685L 570 -685C 623 -716 678 -759 718 -790C 741 -789 752 -797 756 -809Z",[0.311,0.452]],["M 653 -299L 653 88L 678 88C 725 88 797 64 798 56L 798 -248C 819 -252 831 -262 837 -270L 706 -369L 643 -299Z",[0.014,0.637]],["M 738 -639C 717 -570 692 -492 674 -447L 686 -439C 739 -468 802 -510 856 -552C 879 -549 893 -557 898 -569Z",[0.376,0.134]]],"bbox":{"top":-857,"bottom":94,"left":31,"right":972},"hadv":1000}],"text":"普","hadv":1000,"breakAfter":true},{"chars":[{"char":"通","components":[["M 227 -162C 202 -162 92 -86 21 -49L 113 93C 121 88 127 80 124 70C 154 8 198 -68 217 -106C 228 -126 239 -129 253 -106C 329 20 415 77 627 77C 706 77 826 77 885 77C 891 19 922 -31 976 -45L 976 -56C 868 -49 779 -48 672 -48C 450 -47 343 -70 267 -146C 254 -158 247 -162 227 -162Z",[-0.82,0.076]],["M 274 -137L 274 -442C 303 -447 318 -455 326 -465L 192 -572L 129 -488L 21 -488L 27 -460L 144 -460L 144 -105Z",[-0.026,0.604]],["M 65 -832L 57 -827C 99 -768 143 -685 158 -609C 287 -515 398 -766 65 -832Z",[-0.251,0.397]],["M 785 -782L 334 -782L 343 -754L 785 -754Z",[0.639,0.013]],["M 490 -112L 490 -551L 801 -551L 801 -579L 496 -579L 357 -634L 357 -68L 377 -68C 433 -68 490 -98 490 -112Z",[0.121,0.516]],["M 805 -302L 430 -302L 430 -274L 805 -274Z",[0.812,0.036]],["M 805 -442L 430 -442L 430 -414L 805 -414Z",[0.755,0.047]],["M 443 -719L 439 -707C 520 -678 565 -633 588 -596C 685 -499 907 -720 443 -719Z",[-0.407,0.156]],["M 684 -119L 684 -579L 560 -579L 560 -92L 583 -92C 646 -92 683 -113 684 -119Z",[0.003,0.745]],["M 716 -782L 727 -782C 707 -744 664 -684 630 -647L 636 -640C 709 -658 810 -693 869 -725C 891 -726 900 -729 909 -738L 788 -852Z",[0.718,0.043]],["M 748 -579L 758 -579L 758 -203C 758 -193 756 -187 744 -187C 731 -187 701 -189 701 -189L 701 -177C 729 -171 737 -157 743 -142C 750 -125 751 -98 752 -61C 875 -71 891 -113 891 -192L 891 -529C 912 -533 925 -543 931 -550L 807 -645Z",[0.038,0.724]]],"bbox":{"top":-852,"bottom":93,"left":21,"right":976},"hadv":1000}],"text":"通","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"花","components":[["M 252 -602C 202 -433 105 -270 14 -172L 23 -164C 170 -234 295 -341 390 -509C 414 -506 428 -513 433 -526Z",[0.427,0.569]],["M 27 -721L 34 -693L 273 -693L 273 -577L 296 -577C 358 -577 414 -596 414 -608L 414 -693L 577 -693L 577 -583L 600 -583C 664 -583 721 -602 721 -614L 721 -693L 946 -693C 961 -693 972 -698 974 -709C 931 -752 854 -814 854 -814L 785 -721L 721 -721L 721 -813C 748 -817 755 -826 756 -839L 577 -854L 577 -721L 414 -721L 414 -813C 440 -817 447 -826 448 -839L 273 -854L 273 -721Z",[0.635,0.034]],["M 204 -372L 204 93L 230 93C 284 93 342 67 344 58L 344 -371C 363 -375 372 -382 375 -391L 253 -436Z",[0.015,0.722]],["M 787 -549C 671 -360 502 -196 355 -109L 361 -97C 547 -150 733 -257 888 -432C 916 -424 928 -428 937 -439Z",[0.603,0.516]],["M 508 -581L 508 -55C 508 41 540 65 655 65L 753 65C 925 65 979 43 979 -16C 979 -41 968 -57 931 -73L 927 -213L 917 -213C 895 -150 875 -99 862 -79C 853 -68 844 -65 831 -65C 817 -64 794 -64 769 -64L 687 -64C 659 -64 650 -70 650 -89L 650 -538C 674 -541 683 -551 684 -565Z",[-0.222,0.455]]],"bbox":{"top":-854,"bottom":93,"left":14,"right":979},"hadv":1000}],"text":"花","hadv":1000,"breakAfter":true},{"chars":[{"char":"所","components":[["M 250 -726L 87 -777L 87 -456C 87 -278 86 -73 18 87L 28 97C 215 -51 222 -277 222 -451L 222 -712C 237 -714 247 -718 250 -726Z",[0.065,0.822]],["M 416 -328L 132 -328L 132 -300L 416 -300Z",[0.863,0.002]],["M 416 -589L 132 -589L 132 -561L 416 -561Z",[-0.838,0.01]],["M 504 -740L 365 -860C 315 -816 213 -747 135 -706L 138 -695C 241 -704 361 -722 435 -739C 468 -728 491 -729 504 -740Z",[0.509,0.138]],["M 315 -589L 325 -589L 325 -235L 348 -235C 391 -235 458 -258 459 -265L 459 -539C 480 -543 493 -553 499 -561L 375 -655Z",[0.02,0.642]],["M 678 -734L 510 -787L 510 -490C 510 -296 493 -85 347 83L 356 94C 628 -50 650 -295 650 -485L 650 -720C 665 -722 675 -726 678 -734Z",[0.125,0.79]],["M 976 -734L 831 -864C 772 -818 654 -746 563 -703L 565 -693C 682 -700 819 -717 903 -734C 937 -722 962 -723 976 -734Z",[0.492,0.157]],["M 866 -601L 801 -511L 588 -511L 588 -483L 955 -483C 969 -483 980 -488 983 -499C 940 -540 866 -601 866 -601Z",[0.766,0.094]],["M 877 45L 877 -511L 732 -511L 732 83L 759 83C 834 83 877 53 877 45Z",[-0.003,0.844]]],"bbox":{"top":-864,"bottom":97,"left":18,"right":983},"hadv":1000}],"text":"所","hadv":1000,"breakAfter":true},{"chars":[{"char":"祝","components":[["M 242 -637L 255 -637C 226 -496 136 -321 16 -196L 24 -188C 189 -276 323 -433 389 -577C 413 -580 424 -583 433 -593L 314 -707Z",[0.402,0.642]],["M 327 -637L 28 -637L 37 -609L 327 -609Z",[0.745,0.004]],["M 134 -860L 127 -856C 145 -815 163 -760 162 -705C 274 -603 425 -812 134 -860Z",[-0.19,0.246]],["M 287 55L 287 -459L 154 -350L 154 96L 179 96C 245 96 287 64 287 55Z",[0.03,0.735]],["M 282 -419L 273 -414C 297 -368 322 -304 325 -245C 432 -153 558 -357 282 -419Z",[-0.218,0.347]],["M 662 -435L 518 -435C 520 -227 495 -49 320 82L 325 93C 589 -3 652 -192 662 -435Z",[0.275,0.682]],["M 432 -831L 432 -365L 456 -365C 525 -365 566 -387 566 -396L 566 -749L 760 -749L 760 -381L 785 -381C 857 -381 901 -404 901 -410L 901 -739C 924 -743 933 -750 940 -759L 821 -850L 756 -777L 576 -777ZM 848 -435L 540 -435L 540 -407L 848 -407Z",[0.187,0.029]],["M 807 -435L 680 -435L 680 -40C 680 39 693 65 780 65L 832 65C 941 65 980 38 980 -10C 980 -34 974 -49 946 -64L 943 -202L 932 -202C 915 -144 898 -88 889 -70C 883 -61 878 -59 870 -58C 865 -58 857 -58 848 -58L 822 -58C 809 -58 807 -62 807 -75L 807 -399C 807 -408 807 -423 807 -435Z",[-0.15,0.502]]],"bbox":{"top":-860,"bottom":96,"left":16,"right":980},"hadv":1000}],"text":"祝","hadv":1000,"breakAfter":true},{"chars":[{"char":"福","components":[["M 245 -637L 258 -637C 226 -501 130 -331 8 -213L 16 -205C 182 -288 322 -438 392 -577C 417 -580 428 -583 437 -593L 318 -707Z",[0.422,0.622]],["M 337 -637L 34 -637L 43 -609L 337 -609Z",[0.738,0.005]],["M 127 -857L 120 -853C 141 -812 161 -755 163 -700C 278 -601 422 -816 127 -857Z",[-0.377,0.28]],["M 283 49L 283 -452L 149 -342L 149 90L 173 90C 240 90 283 58 283 49Z",[0.032,0.728]],["M 273 -430L 262 -426C 282 -380 303 -316 304 -260C 388 -181 495 -346 273 -430Z",[-0.176,0.424]],["M 851 -860L 783 -770L 397 -770L 405 -742L 947 -742C 961 -742 972 -747 975 -758C 929 -799 851 -860 851 -860Z",[0.81,0.07]],["M 538 52L 538 -324L 855 -324L 855 -352L 544 -352L 408 -405L 408 94L 427 94C 482 94 538 65 538 52Z",[0.15,0.429]],["M 585 -441L 585 -622L 812 -622L 812 -650L 589 -650L 455 -701L 455 -402L 473 -402C 526 -402 585 -430 585 -441Z",[0.207,0.194]],["M 886 -9L 506 -9L 506 19L 886 19Z",[-0.928,0.002]],["M 886 -186L 506 -186L 506 -158L 886 -158Z",[0.882,0.022]],["M 819 -484L 540 -484L 540 -456L 819 -456Z",[0.899,0.004]],["M 730 -350L 615 -350L 615 8L 730 8Z",[0.01,0.634]],["M 752 -650L 762 -650L 762 -418L 786 -418C 829 -418 898 -440 899 -446L 899 -600C 920 -604 933 -613 939 -621L 812 -716Z",[0.005,0.459]],["M 791 -352L 802 -352L 802 86L 825 86C 869 86 935 61 936 54L 936 -302C 957 -306 971 -315 977 -323L 852 -419Z",[0.017,0.681]]],"bbox":{"top":-860,"bottom":94,"left":8,"right":977},"hadv":1000}],"text":"福","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>大家好，又到了每月一次的小学生读后感环节。这次给大家带来的是和《半分の月がのぼる空》<strong>完全无关</strong>的口胡。虽然只看完了前六卷也就是本篇，但是还是有造一些垃圾数据的冲动，大概是我对这种题材毫无免疫力。于是尽管最近生产了不少学术垃圾，结果还是写了。</p>\n<p>当然这又充满了剧透，虽然我觉得 2019 年了没看过的就我一个人。</p>\n<h2>盲信</h2>\n<p>书中给我印象最深刻的句子不是广为流传的『我要拼上性命，成为你的人。』虽然这句话让我感觉到非常震撼——心里想着，啊，这个女孩子真的被拯救了。可能来自于和《Narcissus》的对比把。稍稍有点羡慕。</p>\n<p>属于我的那句是『就如同这句话，小夜子很努力。她后来又撑了一年。』</p>\n<p>橋本紡老师真的很優しい，因为小夜子在面对「多一天都好。就算是多一分钟、一秒钟都好。你要尽可能活久一点喔」这样的要求，也可以嗯的点点头，「我会努力的」。</p>\n<p>大概是我过度解读，但是我从这个对话中体会到的情感的强烈程度，远超了『我要拼上性命，成为你的人。』信念，勇气，满足。最关键的，她在简单的一句『对不起，我要先走一步了』之后，没有继续重复道歉。她说，恩，相信着在之后的日子里，夏目吾郎可以承载着她的存在，没有愧疚、痛苦地，坚强地继续走下去。不需要拼上性命，就这样平和地相信着。</p>\n<p>看到这里，我很愕然。</p>\n<p>小夜子也真的创造了奇迹，她又撑了一年，大概是在病床上看着天花板数日子，又撑了一年。然而仅此而已了，一年之后我还没确定毕业了干什么，不知道和爱人在一起因为什么鸡毛蒜皮的小事情而笑着或者闹着，但是小夜子一年的挣扎，在一句话内就带过了，感觉上和我的日常无异。</p>\n<p>说实话，我很惭愧。不知道是不是能够直到生命的最后一刻，也能够这样信任着那个人，支撑着那个人呢？或者说更彻底的，如果不逞强的话，是不是根本就没办法支撑别人呢？本应该慢慢长大的过程中，却开始愈发感觉自己是否是善良而本真是令人质疑的了，反而越来变得越小孩子了。</p>\n<p>里香与小夜子还不同——她是个更加任性的小姑娘。与其于继续做好接受命运的准备，她说：「我要拼上性命，成为你的人。」选择了反抗。宫园薰没有完成这条路，里香比她多走了一段。</p>\n<p>很遗憾，这两种力量我都无法体会，因为我未尝直面过死亡，于是便说它是盲信。我只能猜测：爱情这么回事儿事实上挺邪门的。它既可以给人离开的从容，也可以给人走下去的勇气。</p>\n<p>为什么要死去的是这样的人，而我还蹦蹦跳跳地活着呢？虽然这样想对那些深爱着我的人很不好，但是我远远不及她们啊。</p>\n<h2>『那被留下来的那个该怎么办呢？』</h2>\n<p>大概永远也不知道，但是时间总会经过，慢慢的总会有办法。</p>\n<p>裕一妈妈还是害臊地觉得还好和裕一爸爸两人有结婚。里香妈妈最后给裕一掏出的那本书，一翻开就自然翻到了五十七页，写着一个潇洒的『R』字。就连夏目的自白，排除掉自己的懊悔以外，也都全部是幸福的事情。</p>\n<p>时间久了，记忆最终决定留下来的点滴片段，是闪亮的日常，就像路边普通的花。在有限的时间里，不断扒开草丛，寻找这样的花朵。在有限的时间之后，留给他人的，也就是摘下来的一簇簇的小野花了，微微的带有草的气味。</p>\n<p>我不知道这是不是上面所说的“盲信”的来源，但是挺希望是这样的。</p>\n<p>夏目在第六卷末尾去了芝加哥。他对裕一说：「好好干喔，臭小鬼。不论发生什么事，都要好好守护里香。」</p>\n<p>第六卷的副标题是 Life goes on。</p>\n<h2>普通的花</h2>\n<p>想起著名妹控入間人間给《いもーとらいふ》的结尾是：</p>\n<blockquote>\n<p>假如能扔下，就會輕鬆很多。我一直很清楚。\n假如不強迫自己割捨，就只會碰上各種苦澀辛酸。我已經充分體會過了。\n但是，「幸好沒有放棄」的念頭，也不只一、二次閃過我腦中。\n所以，我覺得這樣子也很好。\n我已經很滿足了。</p>\n</blockquote>\n<p>感觉其实差不多。</p>\n<blockquote>\n<p>那个臭小鬼，你那个某某朋友，在自己没有察觉的时候，不知不觉地把一切全都抓在手中了呀，已经全都抓在手中了呢。</p>\n</blockquote>\n<p>于是这是我对橋本紡老师尝试传达的信息的理解：留下来的人被记忆和普通的花所祝福着，在他离开之前再交给别人，直到花被带到山的另一边去。</p>\n<blockquote>\n<p>我们的头顶上是一片往外延展的蔚蓝天空，天空的颜色已经完全和春天没两样，稍显模糊的云朵轮廓也和春天没两样。是的，冬天已经彻底远去，接下来换春天降临大地。樱花即将盛开，五十铃川的堤防也会彻头彻尾地被埋在绿草之下，运河上会有好多个鱼儿激起的波纹向外扩张。然后，紧接着春天之后，夏天也会到来。那时候，再和里香一起去吃赤福冰吧，还要去海边呢，手牵着手一起出游吧。我要和里香一起享受那样的时刻，那样的每一天。</p>\n</blockquote>\n","plain":"大家好，又到了每月一次的小学生读后感环节。这次给大家带来的是和《半分の月がのぼる空》完全无关的口胡。虽然只看完了前六卷也就是本篇，但是还是有造一些垃圾数据的冲动，大概是我对这种题材毫无免疫力。于是尽管最近生产了不少学术垃圾，结果还是写了。\n当然这又充满了剧透，虽然我觉得 2019 年了没看过的就我一个人。\n\n盲信\n书中给我印象最深刻的句子不是广为流传的『我要拼上性命，成为你的人。』虽然这句话让我感觉到非常震撼——心里想着，啊，这个女孩子真的被拯救了。可能来自于和《Narcissus》的对比把。稍稍有点羡慕。\n属于我的那句是『就如同这句话，小夜子很努力。她后来又撑了一年。』\n橋本紡老师真的很優しい，因为小夜子在面对「多一天都好。就算是多一分钟、一秒钟都好。你要尽可能活久一点喔」这样的要求，也可以嗯的点点头，「我会努力的」。\n大概是我过度解读，但是我从这个对话中体会到的情感的强烈程度，远超了『我要拼上性命，成为你的人。』信念，勇气，满足。最关键的，她在简单的一句『对不起，我要先走一步了』之后，没有继续重复道歉。她说，恩，相信着在之后的日子里，夏目吾郎可以承载着她的存在，没有愧疚、痛苦地，坚强地继续走下去。不需要拼上性命，就这样平和地相信着。\n看到这里，我很愕然。\n小夜子也真的创造了奇迹，她又撑了一年，大概是在病床上看着天花板数日子，又撑了一年。然而仅此而已了，一年之后我还没确定毕业了干什么，不知道和爱人在一起因为什么鸡毛蒜皮的小事情而笑着或者闹着，但是小夜子一年的挣扎，在一句话内就带过了，感觉上和我的日常无异。\n说实话，我很惭愧。不知道是不是能够直到生命的最后一刻，也能够这样信任着那个人，支撑着那个人呢？或者说更彻底的，如果不逞强的话，是不是根本就没办法支撑别人呢？本应该慢慢长大的过程中，却开始愈发感觉自己是否是善良而本真是令人质疑的了，反而越来变得越小孩子了。\n里香与小夜子还不同——她是个更加任性的小姑娘。与其于继续做好接受命运的准备，她说：「我要拼上性命，成为你的人。」选择了反抗。宫园薰没有完成这条路，里香比她多走了一段。\n很遗憾，这两种力量我都无法体会，因为我未尝直面过死亡，于是便说它是盲信。我只能猜测：爱情这么回事儿事实上挺邪门的。它既可以给人离开的从容，也可以给人走下去的勇气。\n为什么要死去的是这样的人，而我还蹦蹦跳跳地活着呢？虽然这样想对那些深爱着我的人很不好，但是我远远不及她们啊。\n\n『那被留下来的那个该怎么办呢？』\n大概永远也不知道，但是时间总会经过，慢慢的总会有办法。\n裕一妈妈还是害臊地觉得还好和裕一爸爸两人有结婚。里香妈妈最后给裕一掏出的那本书，一翻开就自然翻到了五十七页，写着一个潇洒的『R』字。就连夏目的自白，排除掉自己的懊悔以外，也都全部是幸福的事情。\n时间久了，记忆最终决定留下来的点滴片段，是闪亮的日常，就像路边普通的花。在有限的时间里，不断扒开草丛，寻找这样的花朵。在有限的时间之后，留给他人的，也就是摘下来的一簇簇的小野花了，微微的带有草的气味。\n我不知道这是不是上面所说的“盲信”的来源，但是挺希望是这样的。\n夏目在第六卷末尾去了芝加哥。他对裕一说：「好好干喔，臭小鬼。不论发生什么事，都要好好守护里香。」\n第六卷的副标题是 Life goes on。\n\n普通的花\n想起著名妹控入間人間给《いもーとらいふ》的结尾是：\n假如能扔下，就會輕鬆很多。我一直很清楚。 假如不強迫自己割捨，就只會碰上各種苦澀辛酸。我已經充分體會過了。 但是，「幸好沒有放棄」的念頭，也不只一、二次閃過我腦中。 所以，我覺得這樣子也很好。 我已經很滿足了。\n\n感觉其实差不多。\n那个臭小鬼，你那个某某朋友，在自己没有察觉的时候，不知不觉地把一切全都抓在手中了呀，已经全都抓在手中了呢。\n\n于是这是我对橋本紡老师尝试传达的信息的理解：留下来的人被记忆和普通的花所祝福着，在他离开之前再交给别人，直到花被带到山的另一边去。\n我们的头顶上是一片往外延展的蔚蓝天空，天空的颜色已经完全和春天没两样，稍显模糊的云朵轮廓也和春天没两样。是的，冬天已经彻底远去，接下来换春天降临大地。樱花即将盛开，五十铃川的堤防也会彻头彻尾地被埋在绿草之下，运河上会有好多个鱼儿激起的波纹向外扩张。然后，紧接着春天之后，夏天也会到来。那时候，再和里香一起去吃赤福冰吧，还要去海边呢，手牵着手一起出游吧。我要和里香一起享受那样的时刻，那样的每一天。\n\n"},{"metadata":{"id":"writing-meow-plus","lang":"zh-CN","title":"喵++","tags":["开发"],"publish_time":"2019-05-21T18:38:07.601Z","update_time":"2019-08-21T07:19:29.413Z","title_outline":{"groups":[{"chars":[{"char":"喵","components":[["M 178 -97L 178 -692L 321 -692L 321 -720L 182 -720L 61 -771L 61 -55L 80 -55C 132 -55 178 -83 178 -97Z",[0.034,0.786]],["M 326 -218L 128 -218L 128 -190L 326 -190Z",[-0.931,0.01]],["M 214 -720L 224 -720L 224 -119L 244 -119C 287 -119 343 -148 344 -158L 344 -672C 364 -676 378 -685 384 -693L 271 -782Z",[0.01,0.806]],["M 485 -686L 365 -686L 372 -658L 485 -658L 485 -531L 508 -531C 582 -531 606 -549 606 -555L 606 -658L 687 -658L 687 -534L 708 -534C 783 -534 808 -551 808 -558L 808 -658L 942 -658C 955 -658 965 -663 967 -674C 934 -710 877 -761 877 -761L 827 -686L 808 -686L 808 -798C 831 -802 838 -813 839 -825L 687 -838L 687 -686L 606 -686L 606 -798C 628 -803 634 -813 636 -825L 485 -838Z",[0.367,0.039]],["M 388 -523L 388 87L 411 87C 478 87 517 64 517 55L 517 -443L 772 -443L 772 76L 796 76C 865 76 908 51 908 44L 908 -432C 931 -436 942 -444 949 -453L 832 -545L 767 -471L 529 -471ZM 849 -37L 450 -37L 450 -9L 849 -9ZM 849 -274L 450 -274L 450 -246L 849 -246Z",[0.101,0.021]],["M 706 -471L 584 -471L 584 -19L 706 -19Z",[0.006,0.718]]],"bbox":{"top":-838,"bottom":87,"left":61,"right":967},"hadv":1000}],"text":"喵","hadv":1000,"breakAfter":true},{"chars":[{"char":"+","components":[["M 579 -340L 579 -395L 36 -395L 36 -340Z",[0.871,0.002]],["M 279 -87L 338 -87L 338 -642L 279 -642Z",[-0.006,0.909]]],"bbox":{"top":-642,"bottom":-87,"left":36,"right":579},"hadv":615}],"text":"+","hadv":615,"breakAfter":true},{"chars":[{"char":"+","components":[["M 579 -340L 579 -395L 36 -395L 36 -340Z",[0.871,0.002]],["M 279 -87L 338 -87L 338 -642L 279 -642Z",[-0.006,0.909]]],"bbox":{"top":-642,"bottom":-87,"left":36,"right":579},"hadv":615}],"text":"+","hadv":615,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>躺在床上忽然想做个作品页。于是做了。<del>CSS 真好玩。</del></p>\n<p><a href=\"https://meow.plus\">https://meow.plus</a></p>\n<p>没有 JS 和 SVG Clip，应该是确保了没有任何动画导致的 DOM repaint，所以在各种机子上都可以 60FPS 的说。</p>\n<p>以下是我的摸鱼和 StackOverflow 以及 CSS-Trick 搬运工</p>\n<h2>字颜色渐变</h2>\n<div class=\"highlighted highlighted-css\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-css\"><span style=\"color:#b58900;\">.foo </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">background</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">linear-gradient</span><span style=\"color:#839496;\">(/* ... */);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">color</span><span style=\"color:#839496;\">: </span><span style=\"color:#b58900;\">transparent</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">-webkit-background-clip</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">text</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">background-clip</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">text</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div><div class=\"text-test\">\n  哈哈哈哈哈哈哈哈\n</div>\n<style>\n.text-test {\nbackground: linear-gradient(to right, red 0%, blue 50%, green 100%);\ntext-align: center;\ncolor: transparent;\n-webkit-background-clip: text;\nbackground-clip: text;\nfont-size: 80px;\nwhite-space: nowrap;\noverflow: hidden;\ntext-overflow: ellipsis;\n}\n</style>\n<h2>Hover 区域比真实显示区域小</h2>\n<h3>方法 1</h3>\n<p>因为其实有很多用 absolute 叠起来的孩子，所以这是我使用的方法</p>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">parent</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">action</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">child</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">&lt;!-- Stuff --&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.parent </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">position</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">relative</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.action </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">position</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">absolute</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">top</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">10</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">bottom</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">10</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">right</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">10</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">left</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">10</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">z-index</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.action</span><span style=\"color:#657b83;\">:hover ~ </span><span style=\"color:#b58900;\">.child </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/* ... */\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span></code></pre>\n</div>\n<h3>方法 2</h3>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">parent</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">child</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">&lt;!-- Stuff --&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.parent </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">margin</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">10</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">overflow</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">visible</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.child </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">margin</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">-10</span><span style=\"color:#859900;\">px </span><span style=\"color:#6c71c4;\">-10</span><span style=\"color:#859900;\">px </span><span style=\"color:#6c71c4;\">-10</span><span style=\"color:#859900;\">px </span><span style=\"color:#6c71c4;\">-10</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.parent</span><span style=\"color:#657b83;\">:hover </span><span style=\"color:#b58900;\">.child </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#586e75;\">/* ... */\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span></code></pre>\n</div>\n<h2>写好几个一样的 linear-gradient 好麻烦</h2>\n<div class=\"highlighted highlighted-css\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-css\"><span style=\"color:#b58900;\">.parent </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">--bg-gradient</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">linear-gradient</span><span style=\"color:#839496;\">(/* ... */);\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">.parent .child </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">background-image</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--bg-gradient</span><span style=\"color:#839496;\">);\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<h2>linear-gradient 方向要写度数，但是斜着又不知道宽高比</h2>\n<div class=\"highlighted highlighted-css\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-css\"><span style=\"color:#b58900;\">.foo </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">background-image</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">linear-gradient</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">to top right</span><span style=\"color:#839496;\">, /* ... */);\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<h2>覆盖层动画</h2>\n<p>因为有渐变所以不能变形，没法用 <code>transform: scale</code>。顺便在 blur 的时候需要等待内部内容先恢复，所以要修改 transition 的延迟。</p>\n<div class=\"highlighted highlighted-css\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-css\"><span style=\"color:#b58900;\">.overlap </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">clip-path</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">inset</span><span style=\"color:#839496;\">(</span><span style=\"color:#6c71c4;\">0 100</span><span style=\"color:#859900;\">% </span><span style=\"color:#6c71c4;\">0 0</span><span style=\"color:#839496;\">);\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-property</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">clip</span><span style=\"color:#839496;\">-path;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-duration</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--step-duration</span><span style=\"color:#839496;\">);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-timing-function</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">ease</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-delay</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">calc</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--step-duration</span><span style=\"color:#839496;\">) </span><span style=\"color:#859900;\">+ var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--step-interval</span><span style=\"color:#839496;\">));\n</span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">.action</span><span style=\"color:#657b83;\">:hover ~ </span><span style=\"color:#b58900;\">.overlap </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">clip-path</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">inset</span><span style=\"color:#839496;\">(</span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#839496;\"> var(--row-margin));\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-delay</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#859900;\">s</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div><div class=\"box-test\">\n</div>\n<style>\n  @keyframes box-animation {\n  0% {\n  clip-path: inset(0 100% 0 0);\n  }\n  \n  50% {\n  clip-path: inset(0);\n  }\n  \n  100% {\n  clip-path: inset(0 0 0 100%);\n  }\n  }\n  .box-test {\n  margin: 0 auto;\n  background: linear-gradient(to right, red 0%, blue 50%, green 100%);\n  height: 20px;\n  animation: box-animation 1s ease infinite;\n  }\n</style>\n<h2>瞬间显示动画后面的小尾巴</h2>\n<h3>方法 1</h3>\n<p>最无脑，直接用了。</p>\n<div class=\"highlighted highlighted-css\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-css\"><span style=\"color:#b58900;\">.escape </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">opacity </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#859900;\">s linear</span><span style=\"color:#839496;\">, </span><span style=\"color:#859900;\">clip</span><span style=\"color:#839496;\">-path </span><span style=\"color:#859900;\">var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--escape-duration</span><span style=\"color:#839496;\">) </span><span style=\"color:#859900;\">ease</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<h3>方法 2</h3>\n<p>科学的方法，这个就算倒过来放也没有问题。但是因为在这个用例内不需要倒过来放所以没写。</p>\n<div class=\"highlighted highlighted-css\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-css\"><span style=\"color:#b58900;\">.escape </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-property</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">opacity</span><span style=\"color:#839496;\">, </span><span style=\"color:#859900;\">clip</span><span style=\"color:#839496;\">-path;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-duration</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--escape-duration</span><span style=\"color:#839496;\">);\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">transition-timing-function</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">step-start</span><span style=\"color:#839496;\">, </span><span style=\"color:#859900;\">ease</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div><div style=\"text-align: center; color: #AAA\">\n  <img src=\"https://mdn.mozillademos.org/files/3423/steps(1,start).png\" />\n<p>MDN: step-start = steps(1, jump-start) = steps(1, start)</p>\n</div>\n<h2>还可以再给力一点吗？</h2>\n<p>可以做成点击换背景色的</p>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">input </span><span style=\"color:#b58900;\">type</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">radio</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">id</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">select-a</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">name</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">foo-bar-color</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">input </span><span style=\"color:#b58900;\">type</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">radio</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">id</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">select-b</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">name</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">foo-bar-color</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">label </span><span style=\"color:#b58900;\">for</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">select-a</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">a-label</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">label</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">label </span><span style=\"color:#b58900;\">for</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">select-b</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">b-label</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">label</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">main</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">class</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">box</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">main</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">input</span><span style=\"color:#657b83;\">[</span><span style=\"color:#b58900;\">type</span><span style=\"color:#859900;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">radio</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#657b83;\">] {\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">position</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">fixed</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">bottom</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#859900;\">%</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">label </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">width</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">20</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">height</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">20</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">display</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">inline-block</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">cursor</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">pointer</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.a-label </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">background</span><span style=\"color:#839496;\">: </span><span style=\"color:#b58900;\">red</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.b-label </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">background</span><span style=\"color:#839496;\">: </span><span style=\"color:#b58900;\">blue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">main </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">--background</span><span style=\"color:#839496;\">: </span><span style=\"color:#cb4b16;\">#AAA</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">#select-a</span><span style=\"color:#657b83;\">:checked ~ </span><span style=\"color:#b58900;\">main </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">--background</span><span style=\"color:#839496;\">: </span><span style=\"color:#b58900;\">red</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">#select-b</span><span style=\"color:#657b83;\">:checked ~ </span><span style=\"color:#b58900;\">main </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">--background</span><span style=\"color:#839496;\">: </span><span style=\"color:#b58900;\">blue</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#657b83;\">  </span><span style=\"color:#b58900;\">.box </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">width</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">100</span><span style=\"color:#859900;\">%</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">height</span><span style=\"color:#839496;\">: </span><span style=\"color:#6c71c4;\">20</span><span style=\"color:#859900;\">px</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">    </span><span style=\"color:#859900;\">background</span><span style=\"color:#839496;\">: </span><span style=\"color:#859900;\">var</span><span style=\"color:#839496;\">(</span><span style=\"color:#859900;\">--background</span><span style=\"color:#839496;\">);\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">}\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">style</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">\n</span></code></pre>\n</div>\n<p>请点击下面的红蓝小方块</p>\n<div>\n  <input type=\"radio\" id=\"select-a\" name=\"foo-bar-color\">\n  <input type=\"radio\" id=\"select-b\" name=\"foo-bar-color\">\n<p><label for=\"select-a\" class=\"a-label\"></label>\n<label for=\"select-b\" class=\"b-label\"></label></p>\n  <main>\n    <div class=\"box\"></div>\n  </main>\n  <style>\n    input[type=\"radio\"] {\n      position: fixed;\n      bottom: 100%;\n    }\n    label {\n      width: 20px;\n      height: 20px;\n      display: inline-block;\n      cursor: pointer;\n    }\n\n    .a-label {\n      background: red;\n    }\n\n    .b-label {\n      background: blue;\n    }\n\n    main {\n      --background: #AAA;\n    }\n\n    #select-a:checked ~ main {\n      --background: red;\n    }\n\n    #select-b:checked ~ main {\n      --background: blue;\n    }\n\n    .box {\n      width: 100%;\n      height: 20px;\n      background: var(--background);\n    }\n  </style>\n</div>\n<p><del>最开始想做这件事情的，后来摸掉了，所以现在背景色是写在一个 variable 里的 :joy:</del></p>\n<p>已经加上了，Flag 回收!</p>\n","plain":"躺在床上忽然想做个作品页。于是做了。CSS 真好玩。\nhttps://meow.plus\n没有 JS 和 SVG Clip，应该是确保了没有任何动画导致的 DOM repaint，所以在各种机子上都可以 60FPS 的说。\n以下是我的摸鱼和 StackOverflow 以及 CSS-Trick 搬运工\n\n字颜色渐变\n.foo {\n  background: linear-gradient(/* ... */);\n  color: transparent;\n  -webkit-background-clip: text;\n  background-clip: text;\n}\n\n\nHover 区域比真实显示区域小\n\n方法 1\n因为其实有很多用 absolute 叠起来的孩子，所以这是我使用的方法\n<div class=\"parent\">\n  <div class=\"action\"></div>\n  <div class=\"child\">\n    <!-- Stuff -->\n  </div>\n</div>\n\n<style>\n  .parent {\n    position: relative;\n  }\n  \n  .action {\n    position: absolute;\n    top: 10px;\n    bottom: 10px;\n    right: 10px;\n    left: 10px;\n    z-index: 100;\n  }\n  \n  .action:hover ~ .child {\n    /* ... */\n  }\n</style>\n\n\n方法 2\n<div class=\"parent\">\n  <div class=\"child\">\n    <!-- Stuff -->\n  </div>\n</div>\n\n<style>\n  .parent {\n    margin: 10px;\n    overflow: visible;\n  }\n  \n  .child {\n    margin: -10px -10px -10px -10px;\n  }\n  \n  .parent:hover .child {\n    /* ... */\n  }\n</style>\n\n\n写好几个一样的 linear-gradient 好麻烦\n.parent {\n  --bg-gradient: linear-gradient(/* ... */);\n}\n\n.parent .child {\n  background-image: var(--bg-gradient);\n}\n\n\nlinear-gradient 方向要写度数，但是斜着又不知道宽高比\n.foo {\n  background-image: linear-gradient(to top right, /* ... */);\n}\n\n\n覆盖层动画\n因为有渐变所以不能变形，没法用 transform: scale。顺便在 blur 的时候需要等待内部内容先恢复，所以要修改 transition 的延迟。\n.overlap {\n  clip-path: inset(0 100% 0 0);\n  \n  transition-property: clip-path;\n  transition-duration: var(--step-duration);\n  transition-timing-function: ease;\n  transition-delay: calc(var(--step-duration) + var(--step-interval));\n}\n\n.action:hover ~ .overlap {\n  clip-path: inset(0 var(--row-margin));\n  transition-delay: 0s;\n}\n\n\n瞬间显示动画后面的小尾巴\n\n方法 1\n最无脑，直接用了。\n.escape {\n  transition: opacity 0s linear, clip-path var(--escape-duration) ease;\n}\n\n\n方法 2\n科学的方法，这个就算倒过来放也没有问题。但是因为在这个用例内不需要倒过来放所以没写。\n.escape {\n  transition-property: opacity, clip-path;\n  transition-duration: var(--escape-duration);\n  \n  transition-timing-function: step-start, ease;\n}\n\nMDN: step-start = steps(1, jump-start) = steps(1, start)\n\n还可以再给力一点吗？\n可以做成点击换背景色的\n<input type=\"radio\" id=\"select-a\" name=\"foo-bar-color\">\n<input type=\"radio\" id=\"select-b\" name=\"foo-bar-color\">\n\n<label for=\"select-a\" class=\"a-label\"></label>\n<label for=\"select-b\" class=\"b-label\"></label>\n\n<main>\n  <div class=\"box\"></div>\n</main>\n\n<style>\n  input[type=\"radio\"] {\n    position: fixed;\n    bottom: 100%;\n  }\n  label {\n    width: 20px;\n    height: 20px;\n    display: inline-block;\n    cursor: pointer;\n  }\n\n  .a-label {\n    background: red;\n  }\n\n  .b-label {\n    background: blue;\n  }\n\n  main {\n    --background: #AAA;\n  }\n\n  #select-a:checked ~ main {\n    --background: red;\n  }\n\n  #select-b:checked ~ main {\n    --background: blue;\n  }\n\n  .box {\n    width: 100%;\n    height: 20px;\n    background: var(--background);\n  }\n</style>\n\n\n请点击下面的红蓝小方块\n \n    最开始想做这件事情的，后来摸掉了，所以现在背景色是写在一个 variable 里的 :joy:\n已经加上了，Flag 回收!\n"},{"metadata":{"id":"offline-torrent-download","lang":"zh-CN","title":"在线种种子","tags":["搭积木","约稿"],"publish_time":"2019-05-18T09:18:45.095Z","update_time":"2019-05-18T10:30:41.305Z","title_outline":{"groups":[{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":true},{"chars":[{"char":"线","components":[["M 352 -779L 182 -848C 165 -766 98 -615 50 -572C 39 -564 14 -558 14 -558L 76 -409C 106 -422 127 -468 131 -541L 65 -541L 66 -529C 153 -580 270 -692 327 -773L 294 -766C 328 -756 347 -765 352 -779Z",[0.385,0.613]],["M 459 -584L 305 -677C 268 -572 144 -385 62 -328C 49 -320 20 -313 20 -313L 82 -165C 111 -178 133 -221 138 -296L 75 -296L 75 -284C 198 -350 363 -492 431 -584L 398 -579C 432 -564 452 -572 459 -584Z",[0.497,0.605]],["M 26 -110L 88 55C 101 51 112 40 117 26C 273 -60 375 -134 444 -189L 442 -198C 283 -156 104 -121 26 -110Z",[0.616,0.256]],["M 34 -549L 78 -424C 187 -468 281 -515 328 -540L 328 -552C 207 -549 86 -548 34 -549Z",[0.688,0.112]],["M 42 -308L 86 -174C 234 -231 353 -288 416 -321L 416 -332C 261 -320 106 -310 42 -308Z",[0.653,0.15]],["M 949 -305L 785 -398C 656 -165 482 -34 272 58L 277 71C 529 17 727 -82 903 -294C 928 -290 941 -293 949 -305Z",[0.629,0.493]],["M 841 -519L 776 -418L 365 -374L 375 -347L 962 -410C 975 -411 987 -419 988 -430C 932 -468 841 -519 841 -519Z",[0.827,0.157]],["M 797 -684L 731 -585L 404 -554L 414 -527L 914 -575C 928 -576 939 -583 941 -595C 885 -633 797 -684 797 -684Z",[0.738,0.157]],["M 685 -837L 508 -854C 509 -497 540 -176 777 35C 827 78 923 125 977 72C 996 53 991 17 951 -51L 977 -229L 968 -232C 945 -187 912 -129 894 -102C 883 -85 874 -85 859 -99C 668 -248 644 -528 650 -808C 676 -812 684 -824 685 -837Z",[-0.299,0.726]],["M 661 -820L 654 -815C 686 -780 721 -723 731 -671C 853 -594 954 -822 661 -820Z",[-0.136,0.161]]],"bbox":{"top":-854,"bottom":125,"left":14,"right":996},"hadv":1000}],"text":"线","hadv":1000,"breakAfter":true},{"chars":[{"char":"种","components":[["M 157 -534C 135 -381 89 -204 17 -85L 28 -75C 165 -188 262 -338 303 -518L 303 -534Z",[0.298,0.676]],["M 304 -855C 246 -799 125 -720 24 -676L 26 -666C 156 -672 299 -693 389 -721C 425 -710 449 -713 462 -724Z",[0.572,0.153]],["M 33 -535L 41 -507L 436 -507C 450 -507 460 -512 463 -523C 425 -563 357 -623 357 -623L 297 -535Z",[0.883,0.079]],["M 166 -702L 166 96L 192 96C 261 96 305 65 306 57L 306 -758Z",[0.008,0.829]],["M 306 -443L 297 -438C 322 -392 342 -325 339 -265C 436 -172 563 -367 306 -443Z",[-0.165,0.378]],["M 417 -621L 417 -175L 436 -175C 490 -175 546 -204 546 -217L 546 -593L 868 -593L 868 -621L 552 -621L 417 -674Z",[0.154,0.427]],["M 489 -295L 489 -267L 869 -267L 869 -295Z",[-0.955,0.007]],["M 608 -830L 608 92L 632 92C 685 92 741 60 741 46L 741 -778C 775 -783 783 -795 786 -813Z",[0.006,0.883]],["M 806 -621L 806 -200L 828 -200C 872 -200 937 -224 939 -231L 939 -571C 959 -576 972 -585 979 -593L 855 -687L 796 -621Z",[0.02,0.689]]],"bbox":{"top":-855,"bottom":96,"left":17,"right":979},"hadv":1000}],"text":"种","hadv":1000,"breakAfter":true},{"chars":[{"char":"种","components":[["M 157 -534C 135 -381 89 -204 17 -85L 28 -75C 165 -188 262 -338 303 -518L 303 -534Z",[0.298,0.676]],["M 304 -855C 246 -799 125 -720 24 -676L 26 -666C 156 -672 299 -693 389 -721C 425 -710 449 -713 462 -724Z",[0.572,0.153]],["M 33 -535L 41 -507L 436 -507C 450 -507 460 -512 463 -523C 425 -563 357 -623 357 -623L 297 -535Z",[0.883,0.079]],["M 166 -702L 166 96L 192 96C 261 96 305 65 306 57L 306 -758Z",[0.008,0.829]],["M 306 -443L 297 -438C 322 -392 342 -325 339 -265C 436 -172 563 -367 306 -443Z",[-0.165,0.378]],["M 417 -621L 417 -175L 436 -175C 490 -175 546 -204 546 -217L 546 -593L 868 -593L 868 -621L 552 -621L 417 -674Z",[0.154,0.427]],["M 489 -295L 489 -267L 869 -267L 869 -295Z",[-0.955,0.007]],["M 608 -830L 608 92L 632 92C 685 92 741 60 741 46L 741 -778C 775 -783 783 -795 786 -813Z",[0.006,0.883]],["M 806 -621L 806 -200L 828 -200C 872 -200 937 -224 939 -231L 939 -571C 959 -576 972 -585 979 -593L 855 -687L 796 -621Z",[0.02,0.689]]],"bbox":{"top":-855,"bottom":96,"left":17,"right":979},"hadv":1000}],"text":"种","hadv":1000,"breakAfter":true},{"chars":[{"char":"子","components":[["M 35 -397L 43 -369L 938 -369C 953 -369 965 -374 968 -385C 912 -432 820 -501 820 -501L 738 -397Z",[0.925,0.042]],["M 138 -754L 147 -726L 799 -726L 799 -754Z",[-0.646,0.015]],["M 425 -575L 425 -84C 425 -71 419 -65 402 -65C 373 -65 214 -74 214 -74L 214 -62C 286 -49 313 -33 337 -10C 362 13 369 46 375 95C 552 80 578 25 578 -74L 578 -532C 600 -536 610 -544 612 -559Z",[0.089,0.683]],["M 697 -754C 662 -698 583 -592 519 -535L 531 -535C 641 -575 768 -644 860 -701C 882 -703 893 -706 901 -716L 767 -832L 685 -754Z",[0.492,0.389]]],"bbox":{"top":-832,"bottom":95,"left":35,"right":968},"hadv":1000}],"text":"子","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>百度不太行，为了用离线下载还要购买<strong>大</strong>会员。自己摸一个</p>\n<h2>TL;DR</h2>\n<ul>\n<li><a href=\"https://github.com/rakshasa/rtorrent\">rTorrent</a>: 下载后台</li>\n<li><a href=\"https://github.com/Flood-UI/flood\">flood</a>: 下载前台</li>\n<li>filebrowser: 高端版本 Nginx autoindex</li>\n<li>nginx + LE: 转发</li>\n<li>systemd: dOiNg SyStEmD sTuFf</li>\n</ul>\n<h2>假设环境</h2>\n<p>一台独立的 Linux 主机，拥有 root 权限。</p>\n<p>以下以 ArchLinux 作为示例发行版</p>\n<h2>安装依赖</h2>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">pacman</span><span style=\"color:#268bd2;\"> -S</span><span style=\"color:#839496;\"> nginx certbot certbot-nginx rtorrent go nodejs npm git python2 base-devel\n</span></code></pre>\n</div>\n<p>go 是用来编译一个 filebrowser 的 fork 的，主仓库的版本没有缩略图，而且已经十万年没有 Commit 了。</p>\n<p>python2 是用来编译 Node 的 native extensions。由于 Arch 早就把 Python2 除名了，所以需要安一个。</p>\n<p>base-devel 是 Arch 的一个包的集合，我们用到的是 make 和 gcc。应该大多数发行版都是自带的把…这个 Arch 是因为是被我从 alpine bootstrap 起来的，所以当时缓存在内存里，空间比较小，就没得。</p>\n<h2>下载部分</h2>\n<p>我们希望能够做到以下事情：</p>\n<ul>\n<li>可以远程管理</li>\n<li>可以自动把下载完的文件挪动到另一个目录，这样可以避免打开服务器上还没下完的文件</li>\n<li>限制上传 Ratio</li>\n<li>死掉之后能够重启，还能够继续下</li>\n</ul>\n<p>以上除了远程管理用 WebUI 解决以外，rTorrent 都可以解决。为此 rTorrent 需要一个配置文件，<code>~/.rtorrent.rc</code>。作为示例，我的配置如下：</p>\n<ul>\n<li>假设 rTorrent 的工作路径位于 /store/rtorrent。这个路径会存放 Log 和 Session 之类的东西，以及下到一半的</li>\n<li>假设我们希望下好的文件放到 /store/ready</li>\n<li>假设使用 root(挺不安全但是我服务器上反正没啥东西)</li>\n</ul>\n<pre><code># /root/.rtorrent.rc\n\n#############################################################################\n# A minimal rTorrent configuration that provides the basic features\n# you want to have in addition to the built-in defaults.\n#\n# See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template\n# for an up-to-date version.\n#############################################################################\n\n\n## Instance layout (base paths)\nmethod.insert = cfg.basedir,  private|const|string, (cat,\"/store/rtorrent/\")\nmethod.insert = cfg.download, private|const|string, (cat,(cfg.basedir),\"download\")\nmethod.insert = cfg.logs,     private|const|string, (cat,(cfg.basedir),\"log/\")\nmethod.insert = cfg.logfile,  private|const|string, (cat,(cfg.logs),\"rtorrent-\",(system.time),\".log\")\nmethod.insert = cfg.session,  private|const|string, (cat,(cfg.basedir),\".session/\")\nmethod.insert = cfg.watch,    private|const|string, (cat,(cfg.basedir),\"watch/\")\n\n\n## Create instance directories\nexecute.throw = sh, -c, (cat,\\\n    \"mkdir -p \\\"\",(cfg.download),\"\\\" \",\\\n    \"\\\"\",(cfg.logs),\"\\\" \",\\\n    \"\\\"\",(cfg.session),\"\\\" \",\\\n    \"\\\"\",(cfg.watch),\"/load\\\" \",\\\n    \"\\\"\",(cfg.watch),\"/start\\\" \")\n\n\n## Listening port for incoming peer traffic (fixed; you can also randomize it)\nnetwork.port_range.set = 50000-50000\nnetwork.port_random.set = no\n\n\n## Tracker-less torrent and UDP tracker support\n## (conservative settings for 'private' trackers, change for 'public')\ndht.mode.set = auto\nprotocol.pex.set = no\n\ntrackers.use_udp.set = no\n\n\n# 这里是 Rtorrent 项目给出的推荐 Throttle 设置\n## Peer settings\nthrottle.max_uploads.set = 100\nthrottle.max_uploads.global.set = 250\n\nthrottle.min_peers.normal.set = 20\nthrottle.max_peers.normal.set = 60\nthrottle.min_peers.seed.set = 30\nthrottle.max_peers.seed.set = 80\ntrackers.numwant.set = 80\n\nprotocol.encryption.set = allow_incoming,try_outgoing,enable_retry\n\n\n## Limits for file handle resources, this is optimized for\n## an `ulimit` of 1024 (a common default). You MUST leave\n## a ceiling of handles reserved for rTorrent's internal needs!\nnetwork.http.max_open.set = 50\nnetwork.max_open_files.set = 600\nnetwork.max_open_sockets.set = 300\n\n\n## Memory resource usage (increase if you have a large number of items loaded,\n## and/or the available resources to spend)\npieces.memory.max.set = 1800M\nnetwork.xmlrpc.size_limit.set = 4M\n\n\n## Basic operational settings (no need to change these)\nsession.path.set = (cat, (cfg.session))\ndirectory.default.set = (cat, (cfg.download))\nlog.execute = (cat, (cfg.logs), \"execute.log\")\n#log.xmlrpc = (cat, (cfg.logs), \"xmlrpc.log\")\nexecute.nothrow = sh, -c, (cat, \"echo &gt;\",\\\n    (session.path), \"rtorrent.pid\", \" \",(system.pid))\n\n\n## Other operational settings (check &amp; adapt)\nencoding.add = utf8\nsystem.umask.set = 0027\nsystem.cwd.set = (directory.default)\nnetwork.http.dns_cache_timeout.set = 25\nschedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))\n#pieces.hash.on_completion.set = no\n#view.sort_current = seeding, greater=d.ratio=\n#keys.layout.set = qwerty\n#network.http.capath.set = \"/etc/ssl/certs\"\n#network.http.ssl_verify_peer.set = 0\n#network.http.ssl_verify_host.set = 0\n\n\n## Some additional values and commands\nmethod.insert = system.startup_time, value|const, (system.time)\nmethod.insert = d.data_path, simple,\\\n    \"if=(d.is_multi_file),\\\n        (cat, (d.directory), /),\\\n        (cat, (d.directory), /, (d.name))\"\nmethod.insert = d.session_file, simple, \"cat=(session.path), (d.hash), .torrent\"\n\n\n## Watch directories (add more as you like, but use unique schedule names)\n## Add torrent\nschedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), \"load/*.torrent\")))\n## Add &amp; download straight away\nschedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), \"start/*.torrent\")))\n\n\n## Run the rTorrent process as a daemon in the background\n## (and control via XMLRPC sockets)\n#system.daemon.set = true\n#network.scgi.open_local = (cat,(session.path),rpc.socket)\n#execute.nothrow = chmod,770,(cat,(session.path),rpc.socket)\n\n\n## Logging:\n##   Levels = critical error warn notice info debug\n##   Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*\nprint = (cat, \"Logging to \", (cfg.logfile))\nlog.open_file = \"log\", (cfg.logfile)\nlog.add_output = \"info\", \"log\"\n#log.add_output = \"tracker_debug\", \"log\"\n\n### END of rtorrent.rc ###\n\n# 这一部分控制自动移动完成的文件\nmethod.insert = d.get_finished_dir, simple, \"cat=/store/ready/,$d.custom1=\"\nmethod.insert = d.move_to_complete, simple, \"d.directory.set=$argument.1=; execute=mkdir,-p,$argument.1=; execute=mv,-u,$argument.0=,$argument.1=; d.save_full_session=\"\nmethod.set_key = event.download.finished,move_complete,\"d.move_to_complete=$d.data_path=,$d.get_finished_dir=\"\n\n# 这一行指定了 XMLRPC Socket，之后会在 SystemD 里以 Daemon 模式启动 rtorrent，flood 需要连接这个 Unix Socket\nscgi_local = /var/run/rtorrent.sock\n\n# 配置上传 Ratio，以下数字的单位都是 0.01，所以下面配置的意思是，最少上传 10 倍，最多 100 倍\nratio.enable=\n\nratio.min.set=1000\nratio.max.set=10000\n\n# 达到了 ratio 之后自动停止\nmethod.set = group.seeding.ratio.command, \"d.close=\"\n</code></pre>\n<p>rTorrent 的 wiki 位于 <a href=\"https://github.com/rakshasa/rtorrent/wiki\">https://github.com/rakshasa/rtorrent/wiki</a>，可以自行观摩。</p>\n<p>测试一下 rTorrent 配置</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">mkdir</span><span style=\"color:#268bd2;\"> -p</span><span style=\"color:#839496;\"> /store/rtorrent /store/ready\n</span><span style=\"color:#b58900;\">rtorrent\n</span></code></pre>\n</div>\n<p>应该会正常启动 rTorrent。使用 Ctrl-q 退出</p>\n<p>之后写一个 systemd 配置</p>\n<pre><code class=\"language-ini\"># /etc/systemd/system/rtorrent.service\n\n[Unit]\nDescription=rTorrent Daemon\nAfter=network.target\n\n[Service]\nKillMode=process\nUser=root\nExecStart=/usr/bin/rtorrent -o system.daemon.set=true\nWorkingDirectory=/store/rtorrent\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n</code></pre>\n<p><code>Restart=on-failure</code> 的意思是当返回值不是 0 的时候自动重启。</p>\n<p>最后把 rTorrent 启动起来</p>\n<pre><code>systemctl enable --now rtorrent\nsystemctl status rtorrent\n</code></pre>\n<p>应该会显示 <code>Active: active (running)</code></p>\n<p>注意，如果使用非 Root 用户运行的话，可能需要考虑 <code>/var/run</code> 目录的可写性。可以通过多加一层路径 <code>/var/run/rtorrent</code> 解决。</p>\n<p>接下来搞一个 Flood 作为前端。作为示例：</p>\n<ul>\n<li>暴露给 Nginx 的反代端口是 8013</li>\n</ul>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#859900;\">cd</span><span style=\"color:#839496;\"> /store\n</span><span style=\"color:#b58900;\">git</span><span style=\"color:#839496;\"> clone https://github.com/Flood-UI/flood.git\n</span><span style=\"color:#859900;\">cd</span><span style=\"color:#839496;\"> flood\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># 做一些配置，主要是监听端口和密钥。\n</span><span style=\"color:#586e75;\"># 因为我们用 Nginx 搞 TLS/SSL，所以在 Flood 这里不用启动 SSL 支持\n</span><span style=\"color:#586e75;\"># 这样生成 16 个字符的密钥：\n</span><span style=\"color:#b58900;\">head</span><span style=\"color:#839496;\"> /dev/urandom </span><span style=\"color:#859900;\">| </span><span style=\"color:#b58900;\">tr</span><span style=\"color:#268bd2;\"> -dc</span><span style=\"color:#839496;\"> A-Za-z0-9 </span><span style=\"color:#859900;\">| </span><span style=\"color:#b58900;\">head</span><span style=\"color:#268bd2;\"> -c</span><span style=\"color:#839496;\"> 16 </span><span style=\"color:#859900;\">; echo </span><span style=\"color:#839496;\">&#39;&#39;\n</span><span style=\"color:#b58900;\">cp</span><span style=\"color:#839496;\"> config.template.js config.js </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#b58900;\">editor</span><span style=\"color:#839496;\"> config.js\n</span><span style=\"color:#586e75;\"># 在你喜欢的编辑器里把 floodServerPort 和 secret 改掉。作为示例\n</span><span style=\"color:#586e75;\"># floodServerPort: 8013,\n</span><span style=\"color:#586e75;\"># secret: &#39;abcdefghijklmn&#39;,\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># 装依赖 &amp; 编译静态资源\n</span><span style=\"color:#b58900;\">npm</span><span style=\"color:#839496;\"> install </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#b58900;\">npm</span><span style=\"color:#839496;\"> run build\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># Creating an optimized production build 这一步非常慢\n</span></code></pre>\n</div>\n<p>测试能不能正常执行，就在 flood 的目录内：</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">npm</span><span style=\"color:#839496;\"> start\n</span><span style=\"color:#586e75;\"># Ctrl-C 结束\n</span></code></pre>\n</div>\n<p>一切正常的话说明 Flood 本身可以跑起来了。之后我们需要一个 Systemd 服务来控制，以及一个 Nginx site。先把 systemd 配置写了。</p>\n<ul>\n<li>上面是在 /store/flood 里安装的 flood，下面的 service unit 配置也对应</li>\n<li>ArchLinux 安装的 npm 位于 /usr/bin/npm，可能不同的发行版不一样，用 <code>which npm</code> 检查一下</li>\n</ul>\n<pre><code class=\"language-ini\"># /etc/systemd/system/flood.service\n\n[Unit]\nDescription=Flood rTorrent Web UI\nAfter=network.target rtorrent.service\n\n[Service]\nWorkingDirectory=/store/flood\nExecStart=/usr/bin/npm start\nUser=root\n\n[Install]\nWantedBy=multi-user.target\n</code></pre>\n<p>之后启动并检查状态</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">systemctl</span><span style=\"color:#839496;\"> enable</span><span style=\"color:#268bd2;\"> --now</span><span style=\"color:#839496;\"> flood\n</span><span style=\"color:#b58900;\">systemctl</span><span style=\"color:#839496;\"> status flood\n</span></code></pre>\n</div>\n<p>接下来搞 nginx。</p>\n<ul>\n<li>这里你需要一个域名，我们假设叫做 <code>rt.box.c-3.moe</code>，并且解析已经指过来了</li>\n</ul>\n<p>Ubuntu 系列 Nginx 有一个 sites-enabled 目录，用来存放所有 sites。Arch 没有，Debian 只有一个 conf.d，不完全一样。为了给这些发行版添加类似的目录，在 <code>/etc/nginx/nginx.conf</code> 内做以下修改：</p>\n<pre><code># /etc/nginx/nginx.conf\n\nhttp {\n\n  # ...\n  \n  include sites-enabled/*;\n}\n</code></pre>\n<p>建立 <code>/etc/nginx/sites-enabled</code> 目录后，进去一个文件，叫做 <code>rt</code>:</p>\n<pre><code># /etc/nginx/sites-enabled/rt\nserver {\n  listen 80;\n  server_name rt.box.c-3.moe;\n\n  location / {\n    proxy_set_header Host $host;\n    proxy_pass http://localhost:8013/;\n  }\n}\n</code></pre>\n<p>如果你的反代端口不是 8013，要作出对应修改。</p>\n<p>之后启动 nginx:</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">systemctl</span><span style=\"color:#839496;\"> enable</span><span style=\"color:#268bd2;\"> --now</span><span style=\"color:#839496;\"> nginx\n</span></code></pre>\n</div>\n<p>访问 <code>http://rt.box.c-3.moe</code>，应该就可以看到初始设置页了。在设置之前先把 SSL 证书搞了</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">certbot</span><span style=\"color:#268bd2;\"> --nginx\n</span><span style=\"color:#586e75;\"># 根据提示回答问题，redirect 那里选择自动重定向 (输入 2)\n</span></code></pre>\n</div>\n<p>浏览器刷新一下，就变成 https 了。</p>\n<p>创建账户随便写，下面的连接选项选 Unix Socket，路径写 <code>/var/run/rtorrent.sock</code> 或者改成的别的的路径。点 Create 之后就可以进到主页面了。</p>\n<p>右上角加号添加，Destination 可以不用填，因为配置了 rTorrent 的默认下载路径。对话框下方 Start Torrent 不选的话默认是不开始下的。</p>\n<p>现在其实已经开始用了…如果你对文件下载不需要很 fancy 的 UI，把 nginx 直接指过去就行：</p>\n<p>在 <code>/etc/nginx/sites-enabled/rt</code> 里面第一个 server 块里，server_name 后面直接加几行：</p>\n<pre><code>server {\n  # ...\n  server_nane rt.box.c-3.moe;\n  \n  location /dwn {\n    autoindex on;\n    alias /store/ready;\n  }\n  \n  # ...\n}\n</code></pre>\n<p>之后更新 Nginx 配置：</p>\n<pre><code>systemctl reload nginx\n</code></pre>\n<p>访问 <code>https://rt.box.c-3.moe/dwn</code> 就可以看到下好的文件了。Chrome 也可以直接放视频，一秒变成流媒体。</p>\n","plain":"百度不太行，为了用离线下载还要购买大会员。自己摸一个\n\nTL;DR\n- rTorrent: 下载后台\n- flood: 下载前台\n- filebrowser: 高端版本 Nginx autoindex\n- nginx + LE: 转发\n- systemd: dOiNg SyStEmD sTuFf\n\n假设环境\n一台独立的 Linux 主机，拥有 root 权限。\n以下以 ArchLinux 作为示例发行版\n\n安装依赖\npacman -S nginx certbot certbot-nginx rtorrent go nodejs npm git python2 base-devel\n\ngo 是用来编译一个 filebrowser 的 fork 的，主仓库的版本没有缩略图，而且已经十万年没有 Commit 了。\npython2 是用来编译 Node 的 native extensions。由于 Arch 早就把 Python2 除名了，所以需要安一个。\nbase-devel 是 Arch 的一个包的集合，我们用到的是 make 和 gcc。应该大多数发行版都是自带的把…这个 Arch 是因为是被我从 alpine bootstrap 起来的，所以当时缓存在内存里，空间比较小，就没得。\n\n下载部分\n我们希望能够做到以下事情：\n- 可以远程管理\n- 可以自动把下载完的文件挪动到另一个目录，这样可以避免打开服务器上还没下完的文件\n- 限制上传 Ratio\n- 死掉之后能够重启，还能够继续下\n以上除了远程管理用 WebUI 解决以外，rTorrent 都可以解决。为此 rTorrent 需要一个配置文件，~/.rtorrent.rc。作为示例，我的配置如下：\n- 假设 rTorrent 的工作路径位于 /store/rtorrent。这个路径会存放 Log 和 Session 之类的东西，以及下到一半的\n- 假设我们希望下好的文件放到 /store/ready\n- 假设使用 root(挺不安全但是我服务器上反正没啥东西)\n# /root/.rtorrent.rc\n\n#############################################################################\n# A minimal rTorrent configuration that provides the basic features\n# you want to have in addition to the built-in defaults.\n#\n# See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template\n# for an up-to-date version.\n#############################################################################\n\n\n## Instance layout (base paths)\nmethod.insert = cfg.basedir,  private|const|string, (cat,\"/store/rtorrent/\")\nmethod.insert = cfg.download, private|const|string, (cat,(cfg.basedir),\"download\")\nmethod.insert = cfg.logs,     private|const|string, (cat,(cfg.basedir),\"log/\")\nmethod.insert = cfg.logfile,  private|const|string, (cat,(cfg.logs),\"rtorrent-\",(system.time),\".log\")\nmethod.insert = cfg.session,  private|const|string, (cat,(cfg.basedir),\".session/\")\nmethod.insert = cfg.watch,    private|const|string, (cat,(cfg.basedir),\"watch/\")\n\n\n## Create instance directories\nexecute.throw = sh, -c, (cat,\\\n    \"mkdir -p \\\"\",(cfg.download),\"\\\" \",\\\n    \"\\\"\",(cfg.logs),\"\\\" \",\\\n    \"\\\"\",(cfg.session),\"\\\" \",\\\n    \"\\\"\",(cfg.watch),\"/load\\\" \",\\\n    \"\\\"\",(cfg.watch),\"/start\\\" \")\n\n\n## Listening port for incoming peer traffic (fixed; you can also randomize it)\nnetwork.port_range.set = 50000-50000\nnetwork.port_random.set = no\n\n\n## Tracker-less torrent and UDP tracker support\n## (conservative settings for 'private' trackers, change for 'public')\ndht.mode.set = auto\nprotocol.pex.set = no\n\ntrackers.use_udp.set = no\n\n\n# 这里是 Rtorrent 项目给出的推荐 Throttle 设置\n## Peer settings\nthrottle.max_uploads.set = 100\nthrottle.max_uploads.global.set = 250\n\nthrottle.min_peers.normal.set = 20\nthrottle.max_peers.normal.set = 60\nthrottle.min_peers.seed.set = 30\nthrottle.max_peers.seed.set = 80\ntrackers.numwant.set = 80\n\nprotocol.encryption.set = allow_incoming,try_outgoing,enable_retry\n\n\n## Limits for file handle resources, this is optimized for\n## an `ulimit` of 1024 (a common default). You MUST leave\n## a ceiling of handles reserved for rTorrent's internal needs!\nnetwork.http.max_open.set = 50\nnetwork.max_open_files.set = 600\nnetwork.max_open_sockets.set = 300\n\n\n## Memory resource usage (increase if you have a large number of items loaded,\n## and/or the available resources to spend)\npieces.memory.max.set = 1800M\nnetwork.xmlrpc.size_limit.set = 4M\n\n\n## Basic operational settings (no need to change these)\nsession.path.set = (cat, (cfg.session))\ndirectory.default.set = (cat, (cfg.download))\nlog.execute = (cat, (cfg.logs), \"execute.log\")\n#log.xmlrpc = (cat, (cfg.logs), \"xmlrpc.log\")\nexecute.nothrow = sh, -c, (cat, \"echo >\",\\\n    (session.path), \"rtorrent.pid\", \" \",(system.pid))\n\n\n## Other operational settings (check & adapt)\nencoding.add = utf8\nsystem.umask.set = 0027\nsystem.cwd.set = (directory.default)\nnetwork.http.dns_cache_timeout.set = 25\nschedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))\n#pieces.hash.on_completion.set = no\n#view.sort_current = seeding, greater=d.ratio=\n#keys.layout.set = qwerty\n#network.http.capath.set = \"/etc/ssl/certs\"\n#network.http.ssl_verify_peer.set = 0\n#network.http.ssl_verify_host.set = 0\n\n\n## Some additional values and commands\nmethod.insert = system.startup_time, value|const, (system.time)\nmethod.insert = d.data_path, simple,\\\n    \"if=(d.is_multi_file),\\\n        (cat, (d.directory), /),\\\n        (cat, (d.directory), /, (d.name))\"\nmethod.insert = d.session_file, simple, \"cat=(session.path), (d.hash), .torrent\"\n\n\n## Watch directories (add more as you like, but use unique schedule names)\n## Add torrent\nschedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), \"load/*.torrent\")))\n## Add & download straight away\nschedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), \"start/*.torrent\")))\n\n\n## Run the rTorrent process as a daemon in the background\n## (and control via XMLRPC sockets)\n#system.daemon.set = true\n#network.scgi.open_local = (cat,(session.path),rpc.socket)\n#execute.nothrow = chmod,770,(cat,(session.path),rpc.socket)\n\n\n## Logging:\n##   Levels = critical error warn notice info debug\n##   Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*\nprint = (cat, \"Logging to \", (cfg.logfile))\nlog.open_file = \"log\", (cfg.logfile)\nlog.add_output = \"info\", \"log\"\n#log.add_output = \"tracker_debug\", \"log\"\n\n### END of rtorrent.rc ###\n\n# 这一部分控制自动移动完成的文件\nmethod.insert = d.get_finished_dir, simple, \"cat=/store/ready/,$d.custom1=\"\nmethod.insert = d.move_to_complete, simple, \"d.directory.set=$argument.1=; execute=mkdir,-p,$argument.1=; execute=mv,-u,$argument.0=,$argument.1=; d.save_full_session=\"\nmethod.set_key = event.download.finished,move_complete,\"d.move_to_complete=$d.data_path=,$d.get_finished_dir=\"\n\n# 这一行指定了 XMLRPC Socket，之后会在 SystemD 里以 Daemon 模式启动 rtorrent，flood 需要连接这个 Unix Socket\nscgi_local = /var/run/rtorrent.sock\n\n# 配置上传 Ratio，以下数字的单位都是 0.01，所以下面配置的意思是，最少上传 10 倍，最多 100 倍\nratio.enable=\n\nratio.min.set=1000\nratio.max.set=10000\n\n# 达到了 ratio 之后自动停止\nmethod.set = group.seeding.ratio.command, \"d.close=\"\n\nrTorrent 的 wiki 位于 https://github.com/rakshasa/rtorrent/wiki，可以自行观摩。\n测试一下 rTorrent 配置\nmkdir -p /store/rtorrent /store/ready\nrtorrent\n\n应该会正常启动 rTorrent。使用 Ctrl-q 退出\n之后写一个 systemd 配置\n# /etc/systemd/system/rtorrent.service\n\n[Unit]\nDescription=rTorrent Daemon\nAfter=network.target\n\n[Service]\nKillMode=process\nUser=root\nExecStart=/usr/bin/rtorrent -o system.daemon.set=true\nWorkingDirectory=/store/rtorrent\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n\nRestart=on-failure 的意思是当返回值不是 0 的时候自动重启。\n最后把 rTorrent 启动起来\nsystemctl enable --now rtorrent\nsystemctl status rtorrent\n\n应该会显示 Active: active (running)\n注意，如果使用非 Root 用户运行的话，可能需要考虑 /var/run 目录的可写性。可以通过多加一层路径 /var/run/rtorrent 解决。\n接下来搞一个 Flood 作为前端。作为示例：\n- 暴露给 Nginx 的反代端口是 8013\ncd /store\ngit clone https://github.com/Flood-UI/flood.git\ncd flood\n\n# 做一些配置，主要是监听端口和密钥。\n# 因为我们用 Nginx 搞 TLS/SSL，所以在 Flood 这里不用启动 SSL 支持\n# 这样生成 16 个字符的密钥：\nhead /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 ; echo ''\ncp config.template.js config.js && editor config.js\n# 在你喜欢的编辑器里把 floodServerPort 和 secret 改掉。作为示例\n# floodServerPort: 8013,\n# secret: 'abcdefghijklmn',\n\n# 装依赖 & 编译静态资源\nnpm install && npm run build\n\n# Creating an optimized production build 这一步非常慢\n\n测试能不能正常执行，就在 flood 的目录内：\nnpm start\n# Ctrl-C 结束\n\n一切正常的话说明 Flood 本身可以跑起来了。之后我们需要一个 Systemd 服务来控制，以及一个 Nginx site。先把 systemd 配置写了。\n- 上面是在 /store/flood 里安装的 flood，下面的 service unit 配置也对应\n- ArchLinux 安装的 npm 位于 /usr/bin/npm，可能不同的发行版不一样，用 which npm 检查一下\n# /etc/systemd/system/flood.service\n\n[Unit]\nDescription=Flood rTorrent Web UI\nAfter=network.target rtorrent.service\n\n[Service]\nWorkingDirectory=/store/flood\nExecStart=/usr/bin/npm start\nUser=root\n\n[Install]\nWantedBy=multi-user.target\n\n之后启动并检查状态\nsystemctl enable --now flood\nsystemctl status flood\n\n接下来搞 nginx。\n- 这里你需要一个域名，我们假设叫做 rt.box.c-3.moe，并且解析已经指过来了\nUbuntu 系列 Nginx 有一个 sites-enabled 目录，用来存放所有 sites。Arch 没有，Debian 只有一个 conf.d，不完全一样。为了给这些发行版添加类似的目录，在 /etc/nginx/nginx.conf 内做以下修改：\n# /etc/nginx/nginx.conf\n\nhttp {\n\n  # ...\n  \n  include sites-enabled/*;\n}\n\n建立 /etc/nginx/sites-enabled 目录后，进去一个文件，叫做 rt:\n# /etc/nginx/sites-enabled/rt\nserver {\n  listen 80;\n  server_name rt.box.c-3.moe;\n\n  location / {\n    proxy_set_header Host $host;\n    proxy_pass http://localhost:8013/;\n  }\n}\n\n如果你的反代端口不是 8013，要作出对应修改。\n之后启动 nginx:\nsystemctl enable --now nginx\n\n访问 http://rt.box.c-3.moe，应该就可以看到初始设置页了。在设置之前先把 SSL 证书搞了\ncertbot --nginx\n# 根据提示回答问题，redirect 那里选择自动重定向 (输入 2)\n\n浏览器刷新一下，就变成 https 了。\n创建账户随便写，下面的连接选项选 Unix Socket，路径写 /var/run/rtorrent.sock 或者改成的别的的路径。点 Create 之后就可以进到主页面了。\n右上角加号添加，Destination 可以不用填，因为配置了 rTorrent 的默认下载路径。对话框下方 Start Torrent 不选的话默认是不开始下的。\n现在其实已经开始用了…如果你对文件下载不需要很 fancy 的 UI，把 nginx 直接指过去就行：\n在 /etc/nginx/sites-enabled/rt 里面第一个 server 块里，server_name 后面直接加几行：\nserver {\n  # ...\n  server_nane rt.box.c-3.moe;\n  \n  location /dwn {\n    autoindex on;\n    alias /store/ready;\n  }\n  \n  # ...\n}\n\n之后更新 Nginx 配置：\nsystemctl reload nginx\n\n访问 https://rt.box.c-3.moe/dwn 就可以看到下好的文件了。Chrome 也可以直接放视频，一秒变成流媒体。\n"},{"metadata":{"id":"read-砕け散るところを見せてあげる","lang":"zh-CN","title":"「砕け散るところを見せてあげる」","tags":["瞎读"],"publish_time":"2019-04-14T16:33:07.502Z","update_time":"2019-06-30T06:16:09.306Z","title_outline":{"groups":[{"chars":[{"char":"「","components":[["M 645 -855L 645 -220L 688 -220L 688 -814L 975 -814L 975 -855Z",[0.191,0.632]]],"bbox":{"top":-855,"bottom":-220,"left":645,"right":975},"hadv":1000}],"text":"「","hadv":1000,"breakAfter":false},{"chars":[{"char":"砕","components":[["M 147 -759C 132 -559 96 -343 18 -192L 30 -183C 181 -329 263 -516 293 -743L 293 -759Z",[0.228,0.739]],["M 26 -759L 34 -731L 471 -731C 485 -731 496 -736 499 -747C 453 -787 376 -846 376 -846L 309 -759Z",[0.719,0.037]],["M 228 -468L 241 -468L 170 -495L 103 -395L 103 46L 126 46C 190 46 228 18 228 9Z",[0.022,0.758]],["M 160 -468L 160 -440L 349 -440L 349 -468Z",[0.701,0.012]],["M 170 -102L 170 -74L 359 -74L 359 -102Z",[0.849,0.001]],["M 296 -468L 296 12L 318 12C 361 12 425 -13 426 -21L 426 -419C 447 -423 460 -432 466 -440L 345 -533L 286 -468Z",[0.012,0.739]],["M 419 -704L 428 -676L 784 -676L 784 -704Z",[-0.621,0.024]],["M 544 -844C 543 -636 554 -483 419 -363L 428 -351C 666 -447 672 -600 680 -804C 702 -807 711 -816 713 -830Z",[0.206,0.689]],["M 431 -259L 439 -231L 950 -231C 965 -231 976 -236 979 -247C 933 -290 854 -355 854 -355L 784 -259Z",[0.831,0.072]],["M 607 -431L 607 95L 632 95C 685 95 747 70 747 60L 747 -391C 771 -394 778 -404 779 -416Z",[0.01,0.711]],["M 727 -704L 727 -522C 727 -449 734 -425 814 -425L 855 -425C 941 -425 982 -451 982 -496C 982 -518 976 -531 950 -544L 946 -603L 936 -603C 924 -575 911 -553 904 -545C 899 -541 891 -539 886 -539C 882 -539 876 -539 872 -539L 858 -539C 849 -539 847 -542 847 -553L 847 -667C 864 -670 874 -675 880 -682L 775 -767L 716 -704Z",[-0.165,0.355]]],"bbox":{"top":-846,"bottom":95,"left":18,"right":982},"hadv":1000}],"text":"砕","hadv":1000,"breakAfter":true},{"chars":[{"char":"け","components":[["M 257 25C 301 25 323 1 323 -39C 323 -78 304 -122 304 -161C 304 -193 306 -207 310 -229C 320 -279 336 -347 354 -408L 333 -416C 309 -358 274 -281 244 -239C 235 -227 224 -228 217 -241C 209 -256 206 -282 206 -300C 206 -375 238 -445 281 -516C 305 -555 318 -577 318 -608C 318 -669 258 -729 222 -751C 194 -768 168 -778 129 -785L 122 -775C 143 -750 171 -703 171 -651C 171 -526 116 -416 116 -270C 116 -168 142 -93 168 -46C 194 -0 225 25 257 25Z",[-0.017,0.764]],["M 581 -435C 684 -435 841 -472 895 -498C 933 -516 944 -536 944 -559C 944 -597 900 -624 853 -624C 848 -624 839 -619 808 -605C 747 -577 621 -545 548 -545C 499 -545 453 -560 397 -593L 389 -586C 433 -449 517 -435 581 -435Z",[0.75,0.079]],["M 450 70L 456 83C 609 50 726 -4 772 -143C 802 -232 788 -385 783 -497C 781 -533 778 -599 782 -640C 785 -674 796 -689 796 -707C 796 -748 712 -785 659 -785C 628 -785 589 -764 554 -739L 556 -727C 586 -717 607 -710 629 -694C 640 -686 646 -675 649 -652C 655 -604 660 -533 662 -472C 665 -375 669 -285 654 -205C 628 -66 560 10 450 70Z",[0.067,0.765]]],"bbox":{"top":-785,"bottom":83,"left":116,"right":944},"hadv":1000}],"text":"け","hadv":1000,"breakAfter":true},{"chars":[{"char":"散","components":[["M 25 -542L 33 -514L 552 -514C 565 -514 575 -519 578 -530C 546 -565 489 -617 489 -617L 439 -542Z",[0.865,0.043]],["M 39 -713L 47 -685L 546 -685C 560 -685 570 -690 572 -701C 541 -735 487 -785 487 -785L 439 -713Z",[0.798,0.039]],["M 92 -436L 92 93L 116 93C 182 93 222 64 222 55L 222 -436L 236 -436L 92 -489Z",[-0.003,0.765]],["M 129 -856L 129 -523L 254 -523L 254 -820C 275 -823 281 -831 282 -843Z",[0.007,0.616]],["M 137 -436L 137 -408L 431 -408L 431 -436Z",[-0.892,0.002]],["M 137 -320L 137 -292L 431 -292L 431 -320Z",[-0.963,0.005]],["M 137 -201L 137 -173L 431 -173L 431 -201Z",[-0.903,0.0]],["M 365 -436L 365 -77C 365 -66 362 -60 348 -60C 331 -60 264 -64 264 -64L 264 -51C 303 -43 318 -30 329 -11C 340 7 344 38 346 79C 479 68 496 21 496 -64L 496 -393C 512 -396 522 -403 527 -410L 410 -497L 356 -436Z",[0.051,0.72]],["M 316 -856L 316 -523L 444 -523L 444 -820C 464 -823 470 -831 472 -843Z",[0.002,0.602]],["M 762 -626C 758 -355 698 -94 459 84L 466 92C 810 -43 896 -319 919 -626Z",[0.304,0.714]],["M 604 -853C 596 -679 560 -490 514 -361L 526 -354C 635 -455 708 -599 755 -786C 778 -787 790 -796 794 -810Z",[0.233,0.682]],["M 621 -610L 610 -589C 633 -283 692 -41 868 95C 885 31 923 -8 991 -23L 995 -33C 775 -138 659 -325 621 -610Z",[-0.35,0.63]],["M 618 -626L 618 -598L 960 -598C 974 -598 985 -603 988 -614C 942 -656 863 -719 863 -719L 793 -626Z",[-0.451,0.077]]],"bbox":{"top":-856,"bottom":95,"left":25,"right":995},"hadv":1000}],"text":"散","hadv":1000,"breakAfter":true},{"chars":[{"char":"る","components":[["M 510 55C 725 55 848 -54 848 -193C 848 -349 735 -432 597 -432C 514 -432 459 -407 432 -400C 421 -397 414 -404 427 -417C 461 -451 579 -545 653 -589C 685 -608 727 -620 727 -653C 727 -703 635 -777 579 -777C 554 -777 556 -760 508 -744C 450 -725 356 -703 321 -703C 295 -703 265 -732 246 -766L 234 -765C 226 -738 222 -722 222 -696C 222 -657 272 -576 341 -576C 365 -576 383 -592 402 -605C 438 -630 486 -665 526 -672C 544 -675 557 -666 536 -640C 478 -568 253 -356 186 -295C 147 -259 128 -232 126 -200C 123 -156 149 -124 176 -123C 205 -122 217 -132 246 -170C 331 -281 424 -386 557 -386C 668 -386 723 -329 723 -240C 723 -140 657 -50 462 -50C 396 -50 349 -70 349 -109C 349 -139 372 -158 411 -158C 468 -158 506 -106 515 -39L 628 -61C 606 -171 513 -210 443 -210C 364 -210 299 -166 299 -93C 299 1 391 55 510 55Z",[-0.052,0.28]]],"bbox":{"top":-777,"bottom":55,"left":123,"right":848},"hadv":1000}],"text":"る","hadv":1000,"breakAfter":true},{"chars":[{"char":"と","components":[["M 414 -408L 505 -466C 475 -476 451 -492 437 -523C 424 -551 420 -596 420 -636C 420 -663 426 -691 426 -713C 426 -750 361 -805 282 -805C 248 -805 216 -793 189 -781L 189 -769C 212 -759 233 -747 248 -735C 268 -719 278 -706 282 -680C 290 -624 303 -522 327 -478C 345 -444 373 -421 414 -408Z",[-0.23,0.615]],["M 511 48C 620 48 725 36 770 18C 801 5 823 -24 823 -49C 823 -107 759 -123 687 -123C 670 -123 588 -90 452 -90C 348 -90 289 -113 289 -174C 289 -238 350 -301 444 -357C 533 -409 650 -456 734 -481C 786 -497 801 -510 801 -536C 801 -576 753 -625 710 -644C 682 -658 647 -659 607 -659L 602 -650C 614 -637 631 -622 637 -604C 641 -591 639 -582 629 -575C 604 -556 475 -484 400 -430C 308 -363 206 -256 206 -139C 206 -11 339 48 511 48Z",[0.108,0.281]]],"bbox":{"top":-805,"bottom":48,"left":189,"right":823},"hadv":1000}],"text":"と","hadv":1000,"breakAfter":true},{"chars":[{"char":"こ","components":[["M 507 30C 610 30 716 19 775 -2C 826 -21 838 -35 838 -74C 838 -127 761 -153 718 -153C 690 -153 606 -106 463 -106C 283 -106 233 -174 218 -322L 202 -322C 136 -120 195 30 507 30Z",[-0.691,0.099]],["M 331 -484L 339 -471C 438 -513 526 -541 591 -555C 621 -561 663 -568 697 -574C 739 -582 758 -601 758 -634C 758 -680 668 -718 615 -718C 562 -718 535 -688 396 -688C 314 -688 279 -698 229 -733L 219 -727C 241 -609 333 -594 430 -587C 441 -586 442 -583 434 -575C 409 -552 364 -510 331 -484Z",[-0.664,0.012]]],"bbox":{"top":-733,"bottom":30,"left":136,"right":838},"hadv":1000}],"text":"こ","hadv":1000,"breakAfter":true},{"chars":[{"char":"ろ","components":[["M 322 35L 325 54C 731 84 881 -36 881 -204C 881 -343 766 -428 614 -428C 554 -428 480 -411 428 -386C 421 -383 416 -388 422 -395C 449 -424 638 -584 683 -605C 707 -616 746 -620 746 -653C 746 -701 656 -782 601 -782C 587 -782 580 -772 556 -759C 529 -745 364 -706 328 -706C 302 -706 275 -739 258 -773L 247 -773C 237 -752 227 -723 227 -696C 227 -653 291 -579 337 -579C 364 -579 380 -598 394 -607C 437 -635 495 -668 532 -677C 556 -683 562 -673 543 -646C 514 -602 327 -408 268 -355C 174 -271 122 -240 122 -193C 122 -137 159 -110 185 -110C 217 -110 235 -132 254 -158C 340 -274 463 -389 590 -389C 679 -389 739 -351 739 -265C 739 -128 615 -6 322 35Z",[-0.08,0.222]]],"bbox":{"top":-782,"bottom":84,"left":122,"right":881},"hadv":1000}],"text":"ろ","hadv":1000,"breakAfter":true},{"chars":[{"char":"を","components":[["M 218 -541C 413 -541 589 -604 633 -628C 664 -644 672 -663 672 -679C 672 -722 637 -735 594 -735C 582 -735 571 -719 542 -707C 484 -683 344 -646 251 -642C 184 -640 141 -670 109 -692L 98 -686C 119 -607 141 -541 218 -541Z",[0.826,0.118]],["M 530 -104C 572 -104 594 -135 594 -175C 594 -228 593 -315 576 -387C 563 -449 521 -486 456 -486C 417 -486 386 -471 349 -445C 341 -439 337 -444 342 -451C 416 -558 448 -632 459 -651C 472 -676 489 -707 504 -734C 513 -751 520 -760 520 -774C 520 -814 432 -826 384 -826C 362 -826 327 -813 302 -800L 301 -789C 328 -777 347 -768 363 -756C 380 -743 379 -728 375 -713C 367 -677 305 -506 173 -374C 137 -337 105 -320 106 -282C 107 -234 123 -197 165 -199C 210 -202 242 -271 279 -320C 310 -363 370 -442 419 -442C 463 -442 470 -414 470 -338C 470 -270 463 -211 463 -169C 463 -123 494 -104 530 -104Z",[-0.001,0.335]],["M 525 70C 609 70 699 60 752 43C 790 31 806 12 806 -23C 806 -77 748 -88 692 -88C 657 -88 598 -54 448 -54C 350 -54 325 -86 325 -118C 325 -172 399 -228 484 -270C 566 -310 724 -364 821 -389C 876 -404 915 -401 915 -437C 915 -481 865 -539 825 -560C 796 -575 768 -580 711 -580L 705 -564C 722 -554 744 -538 754 -526C 767 -511 764 -499 746 -488C 691 -453 567 -396 497 -355C 398 -296 262 -196 262 -98C 262 -6 324 70 525 70Z",[0.265,0.355]]],"bbox":{"top":-826,"bottom":70,"left":98,"right":915},"hadv":1000}],"text":"を","hadv":1000,"breakAfter":true},{"chars":[{"char":"見","components":[["M 304 -291C 299 -117 237 1 30 81L 33 92C 326 45 447 -77 462 -291Z",[0.427,0.529]],["M 180 -784L 180 -221L 202 -221C 262 -221 323 -253 323 -269L 323 -756L 749 -756L 749 -784L 331 -784L 180 -843Z",[0.155,0.446]],["M 261 -307L 261 -279L 731 -279L 731 -307Z",[-0.952,0.004]],["M 261 -468L 261 -440L 731 -440L 731 -468Z",[-0.832,0.013]],["M 261 -627L 261 -599L 731 -599L 731 -627Z",[-0.809,0.009]],["M 517 -307L 517 -41C 517 50 542 73 655 73L 755 73C 928 73 975 45 975 -10C 975 -37 967 -53 931 -67L 928 -205L 918 -205C 893 -139 876 -92 863 -73C 855 -62 850 -59 836 -58C 822 -57 797 -57 772 -57L 688 -57C 661 -57 657 -62 657 -75L 657 -272C 657 -281 657 -296 657 -307Z",[-0.358,0.195]],["M 672 -784L 672 -229L 696 -229C 746 -229 816 -257 817 -265L 817 -733C 838 -738 850 -746 857 -755L 727 -856L 662 -784Z",[0.022,0.746]]],"bbox":{"top":-856,"bottom":92,"left":30,"right":975},"hadv":1000}],"text":"見","hadv":1000,"breakAfter":true},{"chars":[{"char":"せ","components":[["M 124 -283C 159 -283 219 -323 333 -372C 445 -420 611 -454 729 -464C 829 -472 856 -453 908 -453C 951 -453 977 -465 977 -504C 977 -564 900 -594 844 -594C 834 -594 806 -589 685 -559C 604 -539 432 -500 330 -472C 245 -449 127 -420 102 -420C 76 -420 56 -430 32 -457L 19 -452C 17 -419 18 -389 28 -368C 49 -324 88 -283 124 -283Z",[0.863,0.182]],["M 571 37C 660 37 730 31 776 19C 823 7 845 -16 845 -44C 845 -95 789 -118 740 -118C 724 -118 619 -82 493 -82C 397 -82 382 -102 381 -176C 380 -223 386 -340 392 -432C 395 -480 398 -522 403 -543C 412 -582 434 -592 434 -616C 434 -652 356 -720 281 -720C 252 -720 212 -699 184 -680L 186 -669C 207 -664 228 -661 245 -650C 259 -641 264 -631 267 -603C 272 -548 274 -473 275 -402C 277 -298 276 -201 279 -135C 286 10 389 37 571 37Z",[-0.281,0.506]],["M 599 -176C 658 -176 700 -219 714 -270C 729 -323 734 -442 738 -503C 741 -553 747 -600 752 -635C 757 -672 780 -690 780 -712C 780 -750 701 -811 631 -811C 604 -811 569 -791 540 -767L 542 -756C 563 -752 579 -750 599 -743C 620 -736 631 -725 632 -706C 636 -647 632 -543 631 -497C 630 -462 626 -370 619 -340C 611 -307 599 -306 574 -306C 554 -306 498 -316 445 -328L 441 -317C 483 -289 528 -259 541 -220C 552 -188 568 -176 599 -176Z",[0.095,0.716]]],"bbox":{"top":-811,"bottom":37,"left":17,"right":977},"hadv":1000}],"text":"せ","hadv":1000,"breakAfter":true},{"chars":[{"char":"て","components":[["M 712 34C 758 34 820 22 820 -36C 820 -80 772 -120 733 -120C 710 -120 632 -116 580 -141C 547 -157 493 -191 493 -311C 493 -465 569 -542 600 -566C 655 -608 712 -610 756 -610C 780 -610 815 -606 845 -606C 883 -606 908 -630 908 -661C 908 -694 882 -716 853 -729C 822 -743 792 -748 760 -748C 730 -748 611 -717 510 -692C 329 -647 207 -619 143 -619C 115 -619 96 -645 76 -670L 67 -667C 61 -651 53 -624 53 -596C 53 -540 132 -463 183 -463C 215 -463 236 -489 258 -503C 318 -542 454 -593 575 -620C 585 -622 586 -616 577 -610C 463 -539 382 -418 382 -262C 382 -128 433 -55 505 -13C 565 22 625 34 712 34Z",[-0.073,0.229]]],"bbox":{"top":-748,"bottom":34,"left":53,"right":908},"hadv":1000}],"text":"て","hadv":1000,"breakAfter":true},{"chars":[{"char":"あ","components":[["M 422 44L 425 62C 721 63 920 -21 920 -237C 920 -376 797 -494 612 -494C 536 -494 462 -478 390 -448C 224 -379 92 -243 92 -101C 92 -37 128 -4 181 -4C 256 -4 349 -46 429 -122C 528 -214 634 -361 662 -472C 667 -492 665 -509 651 -523C 631 -543 601 -554 561 -559L 553 -549C 587 -524 594 -497 584 -465C 562 -393 472 -273 404 -217C 345 -169 267 -124 218 -124C 204 -124 198 -131 198 -146C 198 -214 269 -325 382 -388C 466 -435 532 -454 594 -454C 712 -454 787 -380 787 -271C 787 -146 693 -14 422 44Z",[0.375,0.064]],["M 270 -538C 323 -538 382 -544 436 -553C 550 -572 654 -598 709 -619C 738 -630 755 -647 755 -675C 755 -711 722 -729 659 -729C 647 -729 567 -677 438 -652C 395 -644 344 -637 292 -637C 233 -637 191 -656 142 -684L 133 -677C 146 -596 179 -538 270 -538Z",[0.83,0.112]],["M 454 -61C 488 -61 511 -77 511 -114C 511 -189 440 -234 440 -365C 440 -457 466 -565 492 -673C 501 -711 531 -728 531 -757C 531 -787 450 -820 391 -820C 367 -820 332 -802 310 -787L 311 -777C 331 -772 353 -766 367 -760C 384 -753 388 -747 388 -728C 388 -649 342 -454 342 -325C 342 -194 376 -61 454 -61Z",[0.007,0.824]]],"bbox":{"top":-820,"bottom":63,"left":92,"right":920},"hadv":1000}],"text":"あ","hadv":1000,"breakAfter":true},{"chars":[{"char":"げ","components":[["M 243 35C 287 35 309 11 309 -29C 309 -68 290 -112 290 -151C 290 -183 292 -197 296 -219C 306 -269 322 -337 340 -398L 319 -406C 295 -348 260 -271 230 -229C 221 -217 210 -218 203 -231C 195 -246 192 -272 192 -290C 192 -365 224 -435 267 -506C 291 -545 304 -567 304 -598C 304 -659 244 -719 208 -741C 180 -758 154 -768 115 -775L 108 -765C 129 -740 157 -693 157 -641C 157 -516 102 -406 102 -260C 102 -158 128 -83 154 -36C 180 10 211 35 243 35Z",[-0.017,0.764]],["M 567 -425C 670 -425 827 -462 881 -488C 919 -506 930 -526 930 -549C 930 -587 886 -614 839 -614C 834 -614 825 -609 794 -595C 733 -567 607 -535 534 -535C 485 -535 439 -550 383 -583L 375 -576C 419 -439 503 -425 567 -425Z",[0.749,0.079]],["M 436 80L 442 93C 595 60 712 6 758 -133C 788 -222 774 -375 769 -487C 767 -523 764 -589 768 -630C 771 -664 782 -679 782 -697C 782 -738 698 -775 645 -775C 614 -775 575 -754 540 -729L 542 -717C 572 -707 593 -700 615 -684C 626 -676 632 -665 635 -642C 641 -594 646 -523 648 -462C 651 -365 655 -275 640 -195C 614 -56 546 20 436 80Z",[0.066,0.766]],["M 872 -640C 895 -640 909 -656 909 -676C 909 -695 906 -705 890 -725C 861 -761 816 -780 765 -796L 756 -785C 798 -741 818 -699 833 -672C 845 -651 855 -640 872 -640Z",[-0.34,0.395]],["M 951 -707C 976 -707 987 -726 987 -744C 987 -767 981 -781 960 -800C 932 -826 893 -840 837 -853L 829 -842C 877 -799 895 -764 909 -742C 923 -720 933 -707 951 -707Z",[-0.329,0.148]]],"bbox":{"top":-853,"bottom":93,"left":102,"right":987},"hadv":1000}],"text":"げ","hadv":1000,"breakAfter":true},{"chars":[{"char":"る","components":[["M 510 55C 725 55 848 -54 848 -193C 848 -349 735 -432 597 -432C 514 -432 459 -407 432 -400C 421 -397 414 -404 427 -417C 461 -451 579 -545 653 -589C 685 -608 727 -620 727 -653C 727 -703 635 -777 579 -777C 554 -777 556 -760 508 -744C 450 -725 356 -703 321 -703C 295 -703 265 -732 246 -766L 234 -765C 226 -738 222 -722 222 -696C 222 -657 272 -576 341 -576C 365 -576 383 -592 402 -605C 438 -630 486 -665 526 -672C 544 -675 557 -666 536 -640C 478 -568 253 -356 186 -295C 147 -259 128 -232 126 -200C 123 -156 149 -124 176 -123C 205 -122 217 -132 246 -170C 331 -281 424 -386 557 -386C 668 -386 723 -329 723 -240C 723 -140 657 -50 462 -50C 396 -50 349 -70 349 -109C 349 -139 372 -158 411 -158C 468 -158 506 -106 515 -39L 628 -61C 606 -171 513 -210 443 -210C 364 -210 299 -166 299 -93C 299 1 391 55 510 55Z",[-0.052,0.28]]],"bbox":{"top":-777,"bottom":55,"left":123,"right":848},"hadv":1000}],"text":"る","hadv":1000,"breakAfter":false},{"chars":[{"char":"」","components":[["M 355 95L 355 -540L 312 -540L 312 54L 25 54L 25 95Z",[0.178,0.64]]],"bbox":{"top":-540,"bottom":95,"left":25,"right":355},"hadv":1000}],"text":"」","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>进入中二末期，认识到了自己没有初中时候那样写读后感的水平，因此以后这种 Post 都打标签“瞎读”。因为确实是瞎读，而且是瞎写，并且带剧透。</p>\n<p>「砕け散るところを見せてあげる」by 竹宮ゆゆこ 刷新了我的大脑。可能是我最近看那种皱皱巴巴的厕纸看多了。</p>\n<p>讲的故事好像是关乎英雄主义，读得过程中不断想起鸭志田鸭哥哥，和竹宮一个是優しい的大叔，一个是優しい的大妈。</p>\n<p>个人感觉实在是和青ブタ有点像，关于一个人的英雄，认知与成长，偶然但不唐突的 Boy meets girl，是彻头彻尾的浪漫主义。区别是减去了大格局，在一个简单的小故事上加上细腻的情感。我认为咲太很有趣，我想和他当 Friend 打嘴砲，但是我觉得清澄是我的一部分，摆脱不了。个人觉得这是来自渴望的代入感。所有人都会希望英雄在自己的身体里面，当作为英雄的人物也在想：“我是普通人而已”，希望则变成确信，一个分身就造出来了。</p>\n<p>看自己的一部分化身成一个独立的人，跑着跳着，和某个女孩子 Fall in love，是一种很奇妙的体验。同时会有“这要是我就好了”的颓废感，和“我也有这样的可能性”的错觉，实在是有大剂量毒品的感觉。要说小说的意义在于给予读者想象，真的非常正确，但是我忘记了这个说法的来源，只好打个马虎眼。</p>\n<p>在渴望成为英雄的另一面，英雄也是稀有资源。</p>\n<p>女主角玻璃的存在是一个理想。勇敢，善良，<strong>纯粹</strong>。在黑色的环境里展示为黑色，但是照上光以后就会折射出彩虹。虽然这个名字还带有易碎的意思，以及一个“针”的同音字，但是终于，玻璃在保护之下没有碎掉的时候，硬度还是不可小觑的。</p>\n<p>这个性格简直是我 Best girl. 看到她和男主逐渐靠近，最初获得了英雄，之后成为了自己的英雄，再之后成为了别人的英雄，这是令人热泪盈眶的。哪个人不是希望自己善良的呢？于是我想，啊，这是她应得的，于是又想，英雄也是我应得的，它能够把所有的不好都消去，就是这样简单而又孩子气的幻想，在脊髓里灌入了某种奇异的幸福感。</p>\n<p>于是就更加相信，人和人之间的碰撞会产生信仰、决心和勇气，并且可以再度传递下去。就像读这部作品所产生的这个信念一样。</p>\n<p>愈发能感受到文字的力量，什么时候我也能借用一点这样的力量呢？</p>\n<hr />\n<p>附 Bangumi 厕纸个人评分规矩， BGM Permalink 见 <a href=\"https://c-3.moe\">个人主页</a></p>\n<ul>\n<li>10 - 看哭了的，或者能让我念念不忘一个星期以上的，或者让我激动到写50个字以上的。</li>\n<li>9 - 让我自认为产生了新的认识的</li>\n<li>8 - 很爽的，或者让我认为会激发别人什么新的认识的</li>\n<li>7 - 一般的</li>\n</ul>\n<p>不给以下的，因为再低的分，要不就是我没看懂，要不就是我标上丢人，就不污染大家 TL 了。</p>\n","plain":"进入中二末期，认识到了自己没有初中时候那样写读后感的水平，因此以后这种 Post 都打标签“瞎读”。因为确实是瞎读，而且是瞎写，并且带剧透。\n「砕け散るところを見せてあげる」by 竹宮ゆゆこ 刷新了我的大脑。可能是我最近看那种皱皱巴巴的厕纸看多了。\n讲的故事好像是关乎英雄主义，读得过程中不断想起鸭志田鸭哥哥，和竹宮一个是優しい的大叔，一个是優しい的大妈。\n个人感觉实在是和青ブタ有点像，关于一个人的英雄，认知与成长，偶然但不唐突的 Boy meets girl，是彻头彻尾的浪漫主义。区别是减去了大格局，在一个简单的小故事上加上细腻的情感。我认为咲太很有趣，我想和他当 Friend 打嘴砲，但是我觉得清澄是我的一部分，摆脱不了。个人觉得这是来自渴望的代入感。所有人都会希望英雄在自己的身体里面，当作为英雄的人物也在想：“我是普通人而已”，希望则变成确信，一个分身就造出来了。\n看自己的一部分化身成一个独立的人，跑着跳着，和某个女孩子 Fall in love，是一种很奇妙的体验。同时会有“这要是我就好了”的颓废感，和“我也有这样的可能性”的错觉，实在是有大剂量毒品的感觉。要说小说的意义在于给予读者想象，真的非常正确，但是我忘记了这个说法的来源，只好打个马虎眼。\n在渴望成为英雄的另一面，英雄也是稀有资源。\n女主角玻璃的存在是一个理想。勇敢，善良，纯粹。在黑色的环境里展示为黑色，但是照上光以后就会折射出彩虹。虽然这个名字还带有易碎的意思，以及一个“针”的同音字，但是终于，玻璃在保护之下没有碎掉的时候，硬度还是不可小觑的。\n这个性格简直是我 Best girl. 看到她和男主逐渐靠近，最初获得了英雄，之后成为了自己的英雄，再之后成为了别人的英雄，这是令人热泪盈眶的。哪个人不是希望自己善良的呢？于是我想，啊，这是她应得的，于是又想，英雄也是我应得的，它能够把所有的不好都消去，就是这样简单而又孩子气的幻想，在脊髓里灌入了某种奇异的幸福感。\n于是就更加相信，人和人之间的碰撞会产生信仰、决心和勇气，并且可以再度传递下去。就像读这部作品所产生的这个信念一样。\n愈发能感受到文字的力量，什么时候我也能借用一点这样的力量呢？\n---\n附 Bangumi 厕纸个人评分规矩， BGM Permalink 见 个人主页\n- 10 - 看哭了的，或者能让我念念不忘一个星期以上的，或者让我激动到写50个字以上的。\n- 9 - 让我自认为产生了新的认识的\n- 8 - 很爽的，或者让我认为会激发别人什么新的认识的\n- 7 - 一般的\n不给以下的，因为再低的分，要不就是我没看懂，要不就是我标上丢人，就不污染大家 TL 了。\n"},{"metadata":{"id":"vhdl-on-linux","lang":"zh-CN","title":"掐灭数字人生","tags":["认真学习"],"publish_time":"2019-03-28T18:28:58.287Z","update_time":"2019-07-15T08:31:53.473Z","title_outline":{"groups":[{"chars":[{"char":"掐","components":[["M 310 -839L 138 -855L 138 -85C 138 -75 134 -70 119 -70C 99 -70 13 -75 13 -75L 13 -61C 58 -52 77 -37 91 -13C 104 10 109 44 112 93C 255 79 273 25 273 -72L 273 -811C 298 -814 308 -824 310 -839Z",[0.033,0.836]],["M 18 -378L 75 -223C 88 -228 98 -241 101 -254C 226 -347 313 -425 365 -475L 362 -484C 222 -437 74 -392 18 -378Z",[0.562,0.322]],["M 341 -703L 287 -615L 28 -615L 36 -587L 408 -587C 422 -587 432 -592 435 -603C 402 -642 341 -703 341 -703Z",[0.727,0.084]],["M 711 -789L 533 -856C 493 -701 419 -540 351 -441L 361 -433C 483 -508 588 -619 669 -771C 693 -769 706 -777 711 -789Z",[0.372,0.596]],["M 562 -430L 395 -461L 395 93L 415 93C 492 93 526 68 527 60L 527 -408C 549 -412 559 -419 562 -430Z",[0.008,0.743]],["M 686 -427L 577 -542C 550 -503 495 -431 457 -391L 464 -381C 518 -394 608 -411 651 -427C 670 -418 680 -420 686 -427Z",[-0.468,0.048]],["M 598 -312L 552 -242L 489 -242L 489 -214L 654 -214C 667 -214 677 -219 679 -230C 650 -263 598 -312 598 -312Z",[-0.685,0.117]],["M 857 -45L 506 -45L 506 -17L 857 -17Z",[0.92,0.003]],["M 817 -691L 580 -691L 573 -663L 817 -663Z",[-0.326,0.029]],["M 862 -426L 688 -426L 697 -398L 862 -398Z",[0.825,0.03]],["M 862 -242L 692 -242L 701 -214L 862 -214Z",[0.806,0.036]],["M 759 -691L 762 -691C 749 -631 720 -528 696 -464L 704 -458C 768 -503 851 -579 899 -633C 921 -635 931 -638 939 -646L 829 -760Z",[0.296,0.45]],["M 787 -426L 797 -426L 797 83L 820 83C 865 83 931 57 932 49L 932 -380C 950 -384 961 -391 967 -398L 847 -490Z",[0.012,0.722]]],"bbox":{"top":-856,"bottom":93,"left":13,"right":967},"hadv":1000}],"text":"掐","hadv":1000,"breakAfter":true},{"chars":[{"char":"灭","components":[["M 559 -648C 583 -651 593 -661 595 -676L 403 -693C 401 -354 422 -111 12 82L 19 95C 556 -50 549 -306 559 -648Z",[0.289,0.673]],["M 846 -863L 771 -755L 30 -755L 38 -727L 952 -727C 967 -727 978 -732 981 -743C 932 -790 846 -863 846 -863Z",[0.819,0.046]],["M 254 -603L 243 -603C 238 -515 186 -430 151 -397C 117 -369 105 -328 129 -290C 158 -246 228 -243 259 -291C 302 -355 311 -460 254 -603Z",[0.182,0.538]],["M 549 -580L 535 -578C 552 -304 605 -35 849 96C 862 8 907 -45 985 -61L 985 -74C 688 -162 575 -336 549 -580Z",[-0.396,0.533]],["M 908 -500L 737 -615C 697 -505 639 -382 596 -309L 604 -302C 701 -350 785 -414 861 -491C 884 -484 900 -490 908 -500Z",[0.396,0.453]]],"bbox":{"top":-863,"bottom":96,"left":12,"right":985},"hadv":1000}],"text":"灭","hadv":1000,"breakAfter":true},{"chars":[{"char":"数","components":[["M 325 -617L 325 -633L 185 -633C 155 -544 99 -451 22 -388L 31 -375C 162 -430 270 -510 325 -617Z",[0.455,0.499]],["M 372 -298L 384 -298C 342 -125 227 6 27 79L 33 92C 290 45 441 -73 513 -250C 536 -253 545 -256 552 -266L 440 -363Z",[0.509,0.552]],["M 475 -715L 420 -638L 30 -638L 38 -610L 547 -610C 561 -610 571 -615 573 -626C 537 -662 475 -715 475 -715Z",[0.723,0.062]],["M 430 -298L 36 -298L 45 -270L 430 -270Z",[-0.899,0.002]],["M 68 -820L 59 -815C 78 -779 97 -724 98 -675C 189 -594 306 -767 68 -820Z",[-0.152,0.335]],["M 83 -156L 69 -134C 179 -113 331 -49 400 21C 517 60 612 -200 83 -156Z",[-0.666,0.235]],["M 69 -134L 188 -120C 231 -187 288 -298 315 -352L 286 -340C 334 -330 346 -341 352 -353L 202 -406C 181 -346 111 -198 69 -134Z",[0.318,0.507]],["M 386 -841L 223 -856L 223 -391L 246 -391C 295 -391 353 -414 353 -423L 353 -816C 377 -820 384 -829 386 -841Z",[0.015,0.71]],["M 341 -596L 333 -591C 364 -552 400 -493 413 -439C 527 -366 622 -578 341 -596Z",[-0.192,0.264]],["M 544 -780L 403 -824C 394 -767 383 -702 374 -662L 388 -655C 426 -681 470 -721 506 -759C 527 -759 540 -768 544 -780Z",[0.353,0.34]],["M 919 -626L 762 -626C 755 -335 676 -79 377 85L 382 94C 788 -23 893 -295 919 -626Z",[0.354,0.687]],["M 793 -811L 602 -853C 594 -670 557 -469 508 -332L 520 -325C 634 -434 707 -588 754 -787C 777 -788 789 -798 793 -811Z",[0.223,0.697]],["M 598 -610L 587 -589C 613 -280 676 -39 861 95C 879 30 917 -9 985 -24L 988 -34C 761 -137 639 -324 598 -610Z",[-0.372,0.638]],["M 868 -719L 798 -626L 618 -626L 618 -598L 964 -598C 979 -598 990 -603 993 -614C 946 -656 868 -719 868 -719Z",[0.635,0.121]]],"bbox":{"top":-856,"bottom":95,"left":22,"right":993},"hadv":1000}],"text":"数","hadv":1000,"breakAfter":true},{"chars":[{"char":"字","components":[["M 171 -743L 160 -743C 161 -700 116 -659 85 -643C 43 -624 14 -587 28 -537C 44 -484 110 -466 148 -491C 202 -525 226 -617 171 -743Z",[0.178,0.341]],["M 843 -376L 772 -282L 40 -282L 48 -254L 943 -254C 957 -254 968 -259 971 -270C 923 -313 843 -376 843 -376Z",[0.915,0.037]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 682 -532L 216 -532L 225 -504L 682 -504Z",[0.874,0.001]],["M 607 -391L 423 -406L 423 -72C 423 -60 418 -54 403 -54C 377 -54 234 -63 234 -63L 234 -51C 300 -39 324 -24 346 -2C 368 21 374 53 379 99C 548 85 573 33 573 -65L 573 -365C 595 -368 605 -376 607 -391Z",[0.111,0.582]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 621 -532L 633 -532C 609 -488 554 -406 508 -364L 521 -364C 609 -390 705 -439 779 -484C 800 -486 811 -489 819 -498L 694 -605Z",[0.446,0.334]],["M 780 -680L 791 -680C 788 -639 779 -569 769 -524L 776 -518C 829 -543 897 -588 937 -622C 958 -623 968 -626 976 -635L 852 -752Z",[0.117,0.149]]],"bbox":{"top":-871,"bottom":99,"left":14,"right":976},"hadv":1000}],"text":"字","hadv":1000,"breakAfter":true},{"chars":[{"char":"人","components":[["M 523 -795C 549 -799 558 -808 560 -823L 366 -841C 365 -517 378 -196 28 81L 38 94C 515 -125 514 -468 523 -795Z",[0.248,0.745]],["M 523 -795L 507 -794C 518 -363 559 -61 845 86C 861 7 906 -48 979 -63L 980 -75C 641 -184 544 -402 523 -795Z",[-0.363,0.634]]],"bbox":{"top":-841,"bottom":94,"left":28,"right":980},"hadv":1000}],"text":"人","hadv":1000,"breakAfter":true},{"chars":[{"char":"生","components":[["M 181 -820C 154 -639 85 -453 14 -334L 24 -327C 162 -416 268 -547 342 -740C 366 -740 379 -749 383 -762Z",[0.32,0.621]],["M 25 13L 33 41L 944 41C 960 41 971 36 974 25C 918 -22 825 -92 825 -92L 742 13Z",[0.912,0.042]],["M 147 -321L 155 -293L 865 -293C 880 -293 891 -298 894 -309C 839 -354 748 -421 748 -421L 668 -321Z",[0.893,0.051]],["M 210 -606L 196 -578L 890 -578C 906 -578 917 -583 920 -594C 864 -641 777 -703 777 -703L 698 -606Z",[0.86,0.032]],["M 416 -848L 416 30L 576 30L 576 -801C 604 -805 611 -815 613 -830Z",[0.004,0.813]]],"bbox":{"top":-848,"bottom":41,"left":14,"right":974},"hadv":1000}],"text":"生","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<h3>勘误 @ 2019-4-26</h3>\n<p>模拟时的参数值用等号连接</p>\n<hr />\n<p>我们终于有了认真学习这个 Tag。</p>\n<p>事情的起因是我不想在台式机上装 Quartus。SO 和 Google 告诉我：GHDL</p>\n<h2>安装</h2>\n<p>The wrong way:</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> aruman</span><span style=\"color:#268bd2;\"> -S</span><span style=\"color:#839496;\"> ghdl\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#d33682;\">~~</span><span style=\"color:#839496;\"> calculating solutions...\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">::</span><span style=\"color:#839496;\"> The following 2 package(s) </span><span style=\"color:#b58900;\">are</span><span style=\"color:#839496;\"> getting installed:\n</span><span style=\"color:#839496;\">   </span><span style=\"color:#b58900;\">core/gcc-ada</span><span style=\"color:#839496;\">  /            -</span><span style=\"color:#657b83;\">&gt;  </span><span style=\"color:#6c71c4;\">8</span><span style=\"color:#839496;\">.2.1+20181127-1\n</span><span style=\"color:#839496;\">   </span><span style=\"color:#b58900;\">aur/ghdl</span><span style=\"color:#839496;\">      /            -</span><span style=\"color:#657b83;\">&gt;  </span><span style=\"color:#6c71c4;\">0</span><span style=\"color:#839496;\">.36-1\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">??</span><span style=\"color:#839496;\"> Do you want to continue</span><span style=\"color:#859900;\">?</span><span style=\"color:#839496;\"> Y/n: y\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#b58900;\">...</span><span style=\"color:#839496;\"> one hours later ...\n</span><span style=\"color:#859900;\">[</span><span style=\"color:#839496;\"> Something about compiling GCC </span><span style=\"color:#859900;\">]\n</span><span style=\"color:#b58900;\">^C^C^C^C^C^C\n</span></code></pre>\n</div>\n<p>研究了一下发现 GHDL 有两个版本，一个用 GCC 做后端，一个用 mcode，ghdl 这个包是用 GCC 的，编译 GCC 十万年，直接从源码编译默认用 mcode，也不需要 GCC source，快很多：</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> git clone https://github.com/ghdl/ghdl.git\n</span><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> cd ghdl </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#b58900;\">./configure</span><span style=\"color:#268bd2;\"> --prefix</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">/usr/local </span><span style=\"color:#859900;\">&amp;&amp; </span><span style=\"color:#b58900;\">make\n</span><span style=\"color:#b58900;\">$</span><span style=\"color:#839496;\"> make install\n</span></code></pre>\n</div>\n<h2>Simulation</h2>\n<p>先得写一个顶级 entity</p>\n<pre><code>ghdl -a *.vhdl\nghdl -e main\nghdl -r main --stop-time=100ns --vcd=wave.vcd\ngtkwave wave.vcd\n</code></pre>\n","plain":"\n勘误 @ 2019-4-26\n模拟时的参数值用等号连接\n---\n我们终于有了认真学习这个 Tag。\n事情的起因是我不想在台式机上装 Quartus。SO 和 Google 告诉我：GHDL\n\n安装\nThe wrong way:\n$ aruman -S ghdl\n\n~~ calculating solutions...\n\n:: The following 2 package(s) are getting installed:\n   core/gcc-ada  /            ->  8.2.1+20181127-1\n   aur/ghdl      /            ->  0.36-1\n\n?? Do you want to continue? Y/n: y\n\n... one hours later ...\n[ Something about compiling GCC ]\n^C^C^C^C^C^C\n\n研究了一下发现 GHDL 有两个版本，一个用 GCC 做后端，一个用 mcode，ghdl 这个包是用 GCC 的，编译 GCC 十万年，直接从源码编译默认用 mcode，也不需要 GCC source，快很多：\n$ git clone https://github.com/ghdl/ghdl.git\n$ cd ghdl && ./configure --prefix=/usr/local && make\n$ make install\n\n\nSimulation\n先得写一个顶级 entity\nghdl -a *.vhdl\nghdl -e main\nghdl -r main --stop-time=100ns --vcd=wave.vcd\ngtkwave wave.vcd\n\n"},{"metadata":{"id":"setting-up-wechatircd","lang":"zh-CN","title":"设置 wechatircd","tags":["搭积木"],"publish_time":"2019-03-17T09:39:46.063Z","update_time":"2019-05-18T08:53:58.702Z","title_outline":{"groups":[{"chars":[{"char":"设","components":[["M 245 -584L 32 -584L 41 -556L 245 -556Z",[-0.806,0.008]],["M 72 -844L 65 -838C 113 -791 171 -719 199 -652C 337 -583 415 -841 72 -844Z",[-0.345,0.313]],["M 250 -559L 150 -559L 150 -153C 150 -129 142 -118 91 -89L 192 57C 221 36 253 -19 225 -104L 160 -50L 283 -103L 283 -539Z",[0.046,0.76]],["M 112 -89L 189 41C 299 -68 381 -171 421 -224L 417 -232C 293 -170 165 -110 112 -89Z",[0.497,0.386]],["M 152 -584L 150 -584L 150 -504L 283 -504L 283 -542L 274 -533C 307 -535 320 -544 326 -552L 214 -645Z",[0.075,0.019]],["M 714 -392L 728 -392C 668 -176 507 -6 254 86L 259 97C 593 42 785 -112 883 -335C 908 -338 918 -341 925 -353L 795 -469Z",[0.528,0.551]],["M 426 -790L 426 -701C 426 -610 414 -490 304 -397L 310 -389C 537 -464 562 -614 562 -702L 562 -780L 582 -780L 426 -833Z",[0.187,0.622]],["M 768 -392L 355 -392L 364 -364L 768 -364Z",[-0.938,0.012]],["M 442 -386L 431 -380C 490 -87 634 24 857 98C 876 24 919 -25 984 -41L 985 -53C 745 -85 520 -153 442 -386Z",[-0.573,0.363]],["M 735 -780L 499 -780L 499 -752L 735 -752Z",[-0.601,0.071]],["M 657 -780L 668 -780L 668 -570C 668 -487 678 -461 770 -461L 823 -461C 929 -461 975 -489 975 -541C 975 -566 966 -580 936 -595L 930 -597L 921 -597C 913 -595 901 -593 894 -592C 888 -591 874 -590 867 -590C 861 -590 851 -590 843 -590L 818 -590C 806 -590 804 -594 804 -605L 804 -744C 821 -746 833 -752 839 -759L 722 -851Z",[-0.173,0.341]]],"bbox":{"top":-851,"bottom":98,"left":32,"right":985},"hadv":1000}],"text":"设","hadv":1000,"breakAfter":true},{"chars":[{"char":"置","components":[["M 834 -619L 764 -536L 37 -536L 45 -508L 933 -508C 947 -508 958 -513 961 -524C 912 -564 834 -619 834 -619Z",[0.888,0.032]],["M 853 -66L 780 21L 39 21L 47 49L 958 49C 972 49 984 44 986 33C 935 -8 853 -66 853 -66Z",[0.929,0.033]],["M 259 -597L 259 -760L 787 -760L 787 -788L 269 -788L 122 -843L 122 -556L 141 -556C 196 -556 259 -585 259 -597Z",[0.68,0.135]],["M 801 -646L 187 -646L 187 -618L 801 -618Z",[0.763,0.01]],["M 203 -486L 203 31L 346 31L 346 -402L 649 -402L 649 31L 799 31L 799 -388C 826 -393 837 -399 844 -410L 700 -507L 640 -430L 354 -430ZM 719 -96L 268 -96L 268 -68L 719 -68ZM 720 -205L 269 -205L 269 -177L 720 -177ZM 720 -315L 269 -315L 269 -287L 720 -287Z",[0.334,0.012]],["M 464 -788L 339 -788L 339 -635L 464 -635Z",[-0.019,0.165]],["M 617 -598L 425 -620C 424 -553 419 -459 415 -406L 504 -406C 524 -447 558 -521 577 -567C 600 -571 614 -580 617 -598Z",[0.17,0.34]],["M 674 -788L 548 -788L 548 -635L 674 -635Z",[-0.043,0.162]],["M 748 -788L 758 -788L 758 -573L 783 -573C 829 -573 897 -599 898 -607L 898 -739C 918 -743 930 -752 935 -759L 809 -853Z",[-0.075,0.416]]],"bbox":{"top":-853,"bottom":49,"left":37,"right":986},"hadv":1000}],"text":"置","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"wechatircd","hadv":5893,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>终于受不了 Windows Insider 隔三差五推更新了。Fast Ring 也不能一周三个更新啊…然后晚上一睡觉起来一看微信没了，服了。</p>\n<p>wechatircd 放在服务器上</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">yay</span><span style=\"color:#268bd2;\"> -S</span><span style=\"color:#839496;\"> wechatircd-git\n</span><span style=\"color:#b58900;\">systemctl</span><span style=\"color:#839496;\"> start wechatircd\n</span></code></pre>\n</div>\n<p>然后用 Chromium</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">tmux\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># Within tmux\n</span><span style=\"color:#b58900;\">xvfb-run</span><span style=\"color:#268bd2;\"> -n</span><span style=\"color:#839496;\"> 99 chromium</span><span style=\"color:#268bd2;\"> --user-data-dir</span><span style=\"color:#657b83;\">=</span><span style=\"color:#859900;\">$</span><span style=\"color:#268bd2;\">HOME</span><span style=\"color:#839496;\">/.config/chromium-wechatircd</span><span style=\"color:#268bd2;\"> --no-sandbox\n</span></code></pre>\n</div>\n<p>no-sandbox 当然是因为我懒得设置隔离用户了，直接 root 跑的</p>\n<p>跑一个 vnc 到本地</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#b58900;\">pacman</span><span style=\"color:#268bd2;\"> -S</span><span style=\"color:#839496;\"> x11vnc\n</span><span style=\"color:#b58900;\">x11vnc</span><span style=\"color:#268bd2;\"> -display</span><span style=\"color:#839496;\"> :99</span><span style=\"color:#268bd2;\"> -localhost\n</span></code></pre>\n</div>\n<p>在 Local，WSL 外面跑 vcxsrv，WSL 里面：</p>\n<div class=\"highlighted highlighted-bash\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-bash\"><span style=\"color:#93a1a1;\">export </span><span style=\"color:#268bd2;\">DISPLAY</span><span style=\"color:#657b83;\">=</span><span style=\"color:#2aa198;\">:0\n</span><span style=\"color:#93a1a1;\">export </span><span style=\"color:#268bd2;\">LIBGL_ALWAYS_INDIRECT</span><span style=\"color:#657b83;\">=</span><span style=\"color:#2aa198;\">1\n</span><span style=\"color:#b58900;\">ssh </span><span style=\"color:#859900;\">[</span><span style=\"color:#839496;\">YOUR_IP_HERE</span><span style=\"color:#859900;\">]</span><span style=\"color:#268bd2;\"> -L</span><span style=\"color:#839496;\"> 5900:localhost:5900\n</span><span style=\"color:#839496;\">\n</span><span style=\"color:#586e75;\"># On another tab\n</span><span style=\"color:#b58900;\">pacman</span><span style=\"color:#268bd2;\"> -S</span><span style=\"color:#839496;\"> tigervnc\n</span><span style=\"color:#b58900;\">vncviewer</span><span style=\"color:#839496;\"> localhost:5900\n</span></code></pre>\n</div>\n<p>然后就可以看到 Chromium 了</p>\n<p>安装一个 tampermonkey，装上 wechatircd 的脚本，信任一下证书，之后额外装一个 Extension: EditThisCookie，用来导出服务器 Chromium 上的 Cookie 扔到本地的 Chrome 里。 <code>document.cookie=\"...\"</code> 不太管用，可能是因为 HTTPOnly 之类的设置。</p>\n<p>然后打开 https://wx2.qq.com，照常登陆，用 EditThisCookie 把曲奇复制出来，服务器上的操作就可以结束了。我还在服务器上用 tmux 跑了个 WeeChat，因为服务器上碰巧有 LE 的证书，然后有的时候懒得再 Windows 上装 IRC 客户端，直接用 Glowing bear 就可以了。</p>\n<p>wechatircd 的 IRC 监听端口是 6667，额外反代一个用来 DCC 的端口，映射方向是反着的</p>\n<pre><code>ssh [YOUR_IP_HERE] -L 6667:localhost:6667 -R 5000:localhost:5000\n\n# On another tab\npacman -S weechat\nweechat\n\n# Within WeeChat\n/server add wechat 127.1/6667 -autoconnect\n/set xfer.network.own_ip 127.0.0.1\n/set xfer.network.port_range 5000\n</code></pre>\n<p>然后如果用 Glowing bear:</p>\n<pre><code>/relay add wechat 9001\n/set relay.network.password [PASSWORD]\n</code></pre>\n<p>Chrome 导入一下 Cookie，访问 https://www.glowing-bear.org ，连接一下就好了，发图片文件、收图片文件都可以。</p>\n<hr />\n<p>最后为了使用自动爬图，换成了 thelounge，魔改了一下 crawler 把自己的 Cookie 放进去了，就可以看到微信的图片。</p>\n<p>下一步希望能把 thelounge 自带的文件上传改成 DCC，这样可以直接发送微信图片/文件。现在发出去是一个链接，其他微信用户非常挠头</p>\n<p>到现在为止接近一个月的时间，没有需要我重新扫码，稳定性非常靠谱。</p>\n","plain":"终于受不了 Windows Insider 隔三差五推更新了。Fast Ring 也不能一周三个更新啊…然后晚上一睡觉起来一看微信没了，服了。\nwechatircd 放在服务器上\nyay -S wechatircd-git\nsystemctl start wechatircd\n\n然后用 Chromium\ntmux\n\n# Within tmux\nxvfb-run -n 99 chromium --user-data-dir=$HOME/.config/chromium-wechatircd --no-sandbox\n\nno-sandbox 当然是因为我懒得设置隔离用户了，直接 root 跑的\n跑一个 vnc 到本地\npacman -S x11vnc\nx11vnc -display :99 -localhost\n\n在 Local，WSL 外面跑 vcxsrv，WSL 里面：\nexport DISPLAY=:0\nexport LIBGL_ALWAYS_INDIRECT=1\nssh [YOUR_IP_HERE] -L 5900:localhost:5900\n\n# On another tab\npacman -S tigervnc\nvncviewer localhost:5900\n\n然后就可以看到 Chromium 了\n安装一个 tampermonkey，装上 wechatircd 的脚本，信任一下证书，之后额外装一个 Extension: EditThisCookie，用来导出服务器 Chromium 上的 Cookie 扔到本地的 Chrome 里。 document.cookie=\"...\" 不太管用，可能是因为 HTTPOnly 之类的设置。\n然后打开 https://wx2.qq.com，照常登陆，用 EditThisCookie 把曲奇复制出来，服务器上的操作就可以结束了。我还在服务器上用 tmux 跑了个 WeeChat，因为服务器上碰巧有 LE 的证书，然后有的时候懒得再 Windows 上装 IRC 客户端，直接用 Glowing bear 就可以了。\nwechatircd 的 IRC 监听端口是 6667，额外反代一个用来 DCC 的端口，映射方向是反着的\nssh [YOUR_IP_HERE] -L 6667:localhost:6667 -R 5000:localhost:5000\n\n# On another tab\npacman -S weechat\nweechat\n\n# Within WeeChat\n/server add wechat 127.1/6667 -autoconnect\n/set xfer.network.own_ip 127.0.0.1\n/set xfer.network.port_range 5000\n\n然后如果用 Glowing bear:\n/relay add wechat 9001\n/set relay.network.password [PASSWORD]\n\nChrome 导入一下 Cookie，访问 https://www.glowing-bear.org ，连接一下就好了，发图片文件、收图片文件都可以。\n---\n最后为了使用自动爬图，换成了 thelounge，魔改了一下 crawler 把自己的 Cookie 放进去了，就可以看到微信的图片。\n下一步希望能把 thelounge 自带的文件上传改成 DCC，这样可以直接发送微信图片/文件。现在发出去是一个链接，其他微信用户非常挠头\n到现在为止接近一个月的时间，没有需要我重新扫码，稳定性非常靠谱。\n"},{"metadata":{"id":"implementing-open-graph","lang":"zh-CN","title":"Open Graph on C3Meow","tags":["Meta"],"publish_time":"2019-03-15T09:31:46.411Z","update_time":"2019-03-15T13:38:13.136Z","title_outline":{"groups":[{"chars":[{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"Open","hadv":2767,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"G","components":[["M 441 20C 536 20 607 -0 685 -46L 685 -95C 685 -193 687 -280 689 -367L 521 -367C 523 -275 525 -190 525 -100L 525 -9L 581 -40C 542 -26 503 -18 460 -18C 326 -18 221 -151 221 -374C 221 -614 330 -729 470 -729C 527 -729 567 -713 622 -670L 622 -712L 539 -743L 599 -530L 661 -530L 665 -713C 603 -747 534 -767 448 -767C 207 -767 43 -617 43 -376C 43 -128 204 20 441 20Z",[-0.048,0.116]],["M 416 -333L 555 -316L 624 -316L 750 -333L 750 -367L 416 -367Z",[0.82,0.005]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":750},"hadv":766},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"Graph","hadv":3274,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"on","hadv":1334,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"3","components":[["M 283 17C 454 17 559 -67 559 -189C 559 -307 488 -389 279 -400L 279 -384C 468 -401 536 -482 536 -587C 536 -690 461 -764 303 -764C 181 -764 76 -713 73 -593C 84 -574 104 -562 129 -562C 164 -562 195 -579 204 -630L 224 -733L 161 -708C 198 -723 229 -730 256 -730C 332 -730 377 -680 377 -581C 377 -462 318 -408 230 -408L 196 -408L 196 -369L 235 -369C 337 -369 391 -306 391 -188C 391 -76 334 -18 231 -18C 196 -18 174 -26 145 -41L 196 -12L 178 -120C 169 -187 144 -207 104 -207C 78 -207 52 -193 41 -161C 50 -49 131 17 283 17Z",[0.011,0.423]]],"bbox":{"top":-764,"bottom":17,"left":41,"right":559},"hadv":612},{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893}],"text":"C3Meow","hadv":4450,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>为了顺利在 Telegram 上传教，决定打开一年没动的 Repo，重新挑战了一下 <code>Vue 1</code> 和 <code>Webpack 1</code></p>\n<p>It was a tough one.</p>\n<h2>What is <a href=\"https://ogp.me/\">Open Graph</a></h2>\n<p>是 Facebook 搞得一套用来展示链接内容的协议，方式是在 HTML head 里写一堆 namespace 是 <code>og</code> 的 meta tag。</p>\n<div class=\"highlighted highlighted-HTML\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-HTML\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">meta </span><span style=\"color:#b58900;\">property</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">og:title</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">content</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">标题</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\"> /&gt;\n</span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">meta </span><span style=\"color:#b58900;\">property</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">og:description</span><span style=\"color:#839496;\">&quot; </span><span style=\"color:#b58900;\">content</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">摘要</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\"> /&gt;\n</span><span style=\"color:#586e75;\">&lt;!-- And friends... --&gt;\n</span></code></pre>\n</div>\n<p>显然是非常原创的想法，拥有非常多的新功能，在设计上完全碾压了 HTML 原先标准里 keywords，title，author 之类的 meta tag。</p>\n<p>同时，仅仅牺牲了少量前端渲染的网页，就得到了可以使用 Vim 直接编辑的诱人特性，充分体现了 Facebook 大厂在工程上的取舍能力。</p>\n<p>这一协议甚至考虑了 HTML 并不从 HTTP 传输的情况，并没有用到显然更适合做这件事情的 HTTP headers，看来是深刻领悟了 W3C 的高屋建瓴，已经预料到了 HTTP/114514 可能删去 headers 这一点，实在是高瞻远瞩。</p>\n<blockquote>\n<p>SITUATION: There are 15 competing standards – <a href=\"https://xkcd.com/927/\">xkcd 927. Standards</a></p>\n</blockquote>\n<p>然后 Facebook 显然让 OG 成为了事实标准，连这一点也从 JS 之类的前辈借鉴了前端社区的一贯经验：强扭的瓜真香。</p>\n<p>故事的结尾是 Telegram 也用了这个标准。巧妙的一件事是，Telegram 也尊重了 Facebook 资深前端大厂的身份，遵从了前端行业的一贯行事标准——那就是看着没写清楚的标准，然后根本不根据它实现协议。</p>\n<h2>Open Graph @ Telegram</h2>\n<p>相比于标准，Telegram只需要以下三个 meta 即可工作:</p>\n<ul>\n<li>og:title</li>\n<li>og:description</li>\n<li>og:url (这个我没测试可不可以删)</li>\n</ul>\n<p>至于 <code>og:image</code>，如果加上了的话会有个小 Icon，但是如果宽高比离 1 有点远，可能会傲娇。</p>\n<p>另一点是，作为事实标准的 Facebook，在解析 Description 的时候有上限，据 <a href=\"https://stackoverflow.com/a/35817780\">SO 上的无名高手</a>所说，大概有 100~300 char 不等的限制，而且我们也不知道这个 char 是 C 他们家的还是 Rust 他们家的。Telegram 显然没管这件事，因为我传了个几千字的长文进来，Telegram 还是顺利吃下。</p>\n<p>有一个坑是 <code>og:image</code> 虽然号称自己接受 URL，显然在暗中对 Data URL 进行了种族歧视。为了解决这个问题花了两个小时折腾 Webpack，只为了让他吐一个图片出来。</p>\n<h2>SSR</h2>\n<p>为了在 HTML head 里插入/修改标签，所以需要在之前给爬虫做的 SSR 上进行一点更改。因为之前就需要动态生成 title，所以事实上不太难。</p>\n<p>一点吃惊的是，Vue SSR 传给内部进程的 Context，可以用来传东西给 Node 主进程。大概这两个东西虽然被 Node vm 隔了出去，但是其实还是躺在一个 V8 里，甚至共享了 Heap，看来 Node 对 vm 这个词也有领先业界的理解。备受感动，以后一定称呼 Docker 叫 vm。</p>\n<p>相比之下，之前是通过在 HTML 里渲染一个不显示的 Tag，然后在主进程的接受字节流的地方写了个小状态机，把这个 Tag 提出来。现在看起来跟弱智一样。</p>\n<h2>Next Up</h2>\n<p>既然可以在 Telegram 生成小卡片了，以后可能魔改一下 <a href=\"https://github.com/iovxw/rssbot\">rssbot</a>，加一个修改功能，然后自动转发到我的频道里。少点好几次鼠标，真实节约能源。</p>\n","plain":"为了顺利在 Telegram 上传教，决定打开一年没动的 Repo，重新挑战了一下 Vue 1 和 Webpack 1\nIt was a tough one.\n\nWhat is Open Graph\n是 Facebook 搞得一套用来展示链接内容的协议，方式是在 HTML head 里写一堆 namespace 是 og 的 meta tag。\n<meta property=\"og:title\" content=\"标题\" />\n<meta property=\"og:description\" content=\"摘要\" />\n<!-- And friends... -->\n\n显然是非常原创的想法，拥有非常多的新功能，在设计上完全碾压了 HTML 原先标准里 keywords，title，author 之类的 meta tag。\n同时，仅仅牺牲了少量前端渲染的网页，就得到了可以使用 Vim 直接编辑的诱人特性，充分体现了 Facebook 大厂在工程上的取舍能力。\n这一协议甚至考虑了 HTML 并不从 HTTP 传输的情况，并没有用到显然更适合做这件事情的 HTTP headers，看来是深刻领悟了 W3C 的高屋建瓴，已经预料到了 HTTP/114514 可能删去 headers 这一点，实在是高瞻远瞩。\nSITUATION: There are 15 competing standards – xkcd 927. Standards\n\n然后 Facebook 显然让 OG 成为了事实标准，连这一点也从 JS 之类的前辈借鉴了前端社区的一贯经验：强扭的瓜真香。\n故事的结尾是 Telegram 也用了这个标准。巧妙的一件事是，Telegram 也尊重了 Facebook 资深前端大厂的身份，遵从了前端行业的一贯行事标准——那就是看着没写清楚的标准，然后根本不根据它实现协议。\n\nOpen Graph @ Telegram\n相比于标准，Telegram只需要以下三个 meta 即可工作:\n- og:title\n- og:description\n- og:url (这个我没测试可不可以删)\n至于 og:image，如果加上了的话会有个小 Icon，但是如果宽高比离 1 有点远，可能会傲娇。\n另一点是，作为事实标准的 Facebook，在解析 Description 的时候有上限，据 SO 上的无名高手所说，大概有 100~300 char 不等的限制，而且我们也不知道这个 char 是 C 他们家的还是 Rust 他们家的。Telegram 显然没管这件事，因为我传了个几千字的长文进来，Telegram 还是顺利吃下。\n有一个坑是 og:image 虽然号称自己接受 URL，显然在暗中对 Data URL 进行了种族歧视。为了解决这个问题花了两个小时折腾 Webpack，只为了让他吐一个图片出来。\n\nSSR\n为了在 HTML head 里插入/修改标签，所以需要在之前给爬虫做的 SSR 上进行一点更改。因为之前就需要动态生成 title，所以事实上不太难。\n一点吃惊的是，Vue SSR 传给内部进程的 Context，可以用来传东西给 Node 主进程。大概这两个东西虽然被 Node vm 隔了出去，但是其实还是躺在一个 V8 里，甚至共享了 Heap，看来 Node 对 vm 这个词也有领先业界的理解。备受感动，以后一定称呼 Docker 叫 vm。\n相比之下，之前是通过在 HTML 里渲染一个不显示的 Tag，然后在主进程的接受字节流的地方写了个小状态机，把这个 Tag 提出来。现在看起来跟弱智一样。\n\nNext Up\n既然可以在 Telegram 生成小卡片了，以后可能魔改一下 rssbot，加一个修改功能，然后自动转发到我的频道里。少点好几次鼠标，真实节约能源。\n"},{"metadata":{"id":"dnspod-with-acme","lang":"zh-CN","title":"使用 DNSPod 与 ACME","tags":["踩坑"],"publish_time":"2019-02-10T14:36:12.129Z","update_time":"2019-03-15T08:26:24.148Z","title_outline":{"groups":[{"chars":[{"char":"使","components":[["M 198 -856C 163 -661 84 -460 5 -332L 16 -325C 159 -426 270 -572 349 -778C 372 -777 385 -786 390 -799Z",[0.328,0.655]],["M 127 -524L 127 95L 153 95C 208 95 265 65 266 55L 266 -528C 286 -532 294 -538 298 -548L 178 -592Z",[0.011,0.79]],["M 559 -852L 559 -326C 559 -123 471 -1 261 85L 266 95C 578 38 698 -94 701 -326L 701 -807C 727 -811 735 -821 737 -835Z",[0.134,0.765]],["M 324 -697L 332 -669L 948 -669C 962 -669 974 -674 977 -685C 925 -731 838 -798 838 -798L 761 -697Z",[0.901,0.068]],["M 335 -568L 335 -256L 354 -256C 411 -256 472 -285 472 -297L 472 -540L 799 -540L 799 -568L 478 -568L 335 -623Z",[0.248,0.231]],["M 431 -259L 421 -254C 490 -42 627 51 880 92C 890 19 935 -34 990 -52L 991 -64C 751 -61 519 -115 431 -259Z",[-0.643,0.24]],["M 437 -348L 437 -320L 821 -320L 821 -348Z",[-0.929,0.009]],["M 787 -568L 787 -269L 811 -269C 858 -269 927 -296 927 -304L 927 -517C 948 -522 961 -531 967 -539L 839 -636L 777 -568Z",[0.001,0.585]]],"bbox":{"top":-856,"bottom":95,"left":5,"right":991},"hadv":1000}],"text":"使","hadv":1000,"breakAfter":true},{"chars":[{"char":"用","components":[["M 136 -773L 136 -461C 136 -273 129 -77 25 76L 34 83C 266 -58 278 -276 278 -462L 278 -773L 299 -773L 136 -828L 136 -783Z",[0.078,0.811]],["M 217 -540L 217 -512L 792 -512L 792 -540Z",[-0.834,0.008]],["M 217 -773L 217 -745L 792 -745L 792 -773Z",[-0.626,0.018]],["M 217 -297L 217 -269L 792 -269L 792 -297Z",[-0.951,0.003]],["M 427 -763L 427 80L 453 80C 527 80 569 51 569 42L 569 -763Z",[0.004,0.824]],["M 740 -773L 740 -90C 740 -78 736 -70 720 -70C 700 -70 607 -76 607 -76L 607 -63C 657 -54 675 -39 690 -18C 704 2 709 35 712 80C 864 67 885 17 885 -76L 885 -719C 908 -724 921 -734 929 -743L 795 -849L 729 -773Z",[0.041,0.817]]],"bbox":{"top":-849,"bottom":83,"left":25,"right":929},"hadv":1000}],"text":"用","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673}],"text":"DNSPod","hadv":4236,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"与","components":[["M 553 -351L 478 -255L 32 -255L 40 -227L 658 -227C 673 -227 684 -232 687 -243C 637 -287 553 -351 553 -351Z",[0.865,0.059]],["M 420 -823L 239 -857C 235 -773 202 -541 177 -443L 214 -482C 192 -473 166 -455 152 -440L 283 -369L 331 -431L 324 -431C 344 -530 374 -741 384 -821L 375 -798C 405 -797 417 -810 420 -823Z",[0.116,0.669]],["M 840 -459L 260 -459L 260 -431L 840 -431Z",[0.853,0.012]],["M 813 -756L 737 -661L 267 -661L 267 -633L 923 -633C 938 -633 950 -638 953 -649C 900 -693 813 -756 813 -756Z",[0.95,0.048]],["M 717 -459L 729 -459C 711 -245 679 -99 639 -70C 627 -61 617 -58 599 -58C 572 -58 487 -63 429 -68L 428 -57C 484 -46 527 -26 548 -3C 568 18 574 54 574 97C 655 97 701 84 744 51C 814 -1 853 -146 876 -404C 900 -407 913 -414 922 -424L 795 -533Z",[0.241,0.618]]],"bbox":{"top":-857,"bottom":97,"left":32,"right":953},"hadv":1000}],"text":"与","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"A","components":[["M 14 -0L 242 -0L 242 -34L 133 -49L 114 -49L 14 -34Z",[-0.799,0.001]],["M 82 -0L 135 -0L 332 -633L 335 -647L 314 -647L 520 -0L 693 -0L 437 -750L 333 -750ZM 194 -237L 536 -237L 527 -272L 203 -272Z",[-0.089,0.362]],["M 408 -0L 749 -0L 749 -35L 606 -50L 544 -50L 408 -35Z",[-0.859,0.002]]],"bbox":{"top":-750,"bottom":0,"left":14,"right":749},"hadv":761},{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"E","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 634 -0L 632 -207L 576 -207L 519 -1L 605 -39L 218 -39Z",[0.604,0.185]],["M 218 -363L 467 -363L 467 -399L 218 -399Z",[-0.86,0.001]],["M 554 -548L 612 -548L 613 -747L 218 -747L 218 -708L 583 -708L 499 -747Z",[-0.58,0.193]],["M 454 -263L 504 -263L 504 -505L 454 -505L 438 -395L 438 -374Z",[0.007,0.742]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":634},"hadv":674}],"text":"ACME","hadv":3157,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>其实是因为 CNAME 和别的记录不兼容。是我肤浅了，伤害了大家的感情，对不起</p>\n<hr />\n<p>如果使用 DNSPod 或者腾讯云解析的时候，ACME 遇到了</p>\n<pre><code>DNS problem: SERVFAIL looking up CAA for [DOMAIN HERE]\n</code></pre>\n<p>请检查你的 @ 解析是不是 CNAME 到了其他域名上。据经验，如果有 @ 解析 CNAME 的话，CAA 查询会爆炸。</p>\n<p>截止到目前，ACME 还没有要求强制 CAA，但是会检查 CAA。如果这个检查得到的来自 DNS 回应是非法的，这个签发请求会被拒绝。</p>\n<blockquote>\n<p>CAA 记录在做了 —— 腾讯云 @ 2017</p>\n</blockquote>\n","plain":"其实是因为 CNAME 和别的记录不兼容。是我肤浅了，伤害了大家的感情，对不起\n---\n如果使用 DNSPod 或者腾讯云解析的时候，ACME 遇到了\nDNS problem: SERVFAIL looking up CAA for [DOMAIN HERE]\n\n请检查你的 @ 解析是不是 CNAME 到了其他域名上。据经验，如果有 @ 解析 CNAME 的话，CAA 查询会爆炸。\n截止到目前，ACME 还没有要求强制 CAA，但是会检查 CAA。如果这个检查得到的来自 DNS 回应是非法的，这个签发请求会被拒绝。\nCAA 记录在做了 —— 腾讯云 @ 2017\n\n"},{"metadata":{"id":"hide-navigator-webdriver","lang":"zh-CN","title":"隐藏 navigator.webdriver","tags":["踩坑"],"publish_time":"2019-01-26T16:28:33.956Z","update_time":"2019-01-26T16:30:18.362Z","title_outline":{"groups":[{"chars":[{"char":"隐","components":[["M 70 -830L 70 96L 94 96C 160 96 200 64 200 55L 200 -777L 214 -777Z",[-0.001,0.855]],["M 310 -777L 136 -777L 136 -749L 310 -749Z",[-0.638,0.027]],["M 241 -777L 253 -777C 251 -708 238 -580 226 -510C 261 -455 274 -387 274 -323C 274 -299 269 -286 260 -279C 255 -276 251 -275 243 -275C 234 -275 212 -275 199 -275L 199 -264C 218 -258 229 -248 236 -235C 244 -218 248 -164 248 -131C 361 -132 398 -192 398 -285C 398 -361 355 -456 251 -513C 301 -570 354 -658 387 -713C 410 -714 423 -717 431 -727L 308 -841Z",[-0.001,0.802]],["M 420 -212L 407 -212C 406 -165 364 -117 333 -99C 300 -81 279 -49 292 -11C 308 31 364 40 395 15C 439 -18 461 -100 420 -212Z",[0.229,0.412]],["M 689 -822L 503 -853C 473 -734 405 -588 333 -506L 341 -499C 467 -565 581 -689 651 -804C 679 -804 686 -810 689 -822Z",[0.407,0.574]],["M 803 -305L 414 -305L 423 -277L 803 -277Z",[-0.976,0.017]],["M 818 -571L 438 -571L 447 -543L 818 -543Z",[-0.982,0.03]],["M 819 -439L 449 -439L 458 -411L 819 -411Z",[0.727,0.062]],["M 618 -215L 465 -227L 465 -31C 465 47 482 68 581 68L 665 68C 808 68 853 44 853 -5C 853 -27 847 -41 815 -54L 812 -154L 802 -154C 783 -106 769 -71 759 -57C 752 -49 746 -47 735 -46C 724 -46 703 -45 680 -45L 613 -45C 590 -45 587 -49 587 -60L 587 -190C 607 -193 616 -202 618 -215Z",[-0.394,0.168]],["M 781 -730L 544 -730L 526 -702L 781 -702Z",[-0.33,0.067]],["M 610 -265L 601 -260C 627 -220 643 -159 636 -105C 733 -10 866 -204 610 -265Z",[-0.151,0.293]],["M 690 -730L 702 -730C 691 -687 665 -600 641 -553L 653 -553C 716 -584 788 -641 837 -683C 858 -685 868 -687 877 -696L 758 -798Z",[0.335,0.334]],["M 789 -571L 781 -571L 781 -244L 806 -244C 858 -244 910 -264 912 -268L 912 -521C 928 -524 941 -531 948 -539L 846 -630Z",[0.042,0.568]],["M 816 -215L 806 -210C 841 -155 867 -74 861 -4C 963 95 1087 -123 816 -215Z",[-0.178,0.367]]],"bbox":{"top":-853,"bottom":96,"left":70,"right":1087},"hadv":1000}],"text":"隐","hadv":1000,"breakAfter":true},{"chars":[{"char":"藏","components":[["M 181 -294L 78 -294C 77 -192 78 -74 21 30L 34 43C 151 -46 177 -178 181 -294Z",[0.182,0.698]],["M 258 -294L 26 -294L 35 -266L 258 -266Z",[-0.92,0.005]],["M 140 -562L 64 -562L 64 -401L 83 -436C 67 -430 44 -412 33 -399L 139 -333L 172 -387L 164 -387L 164 -547Z",[-0.004,0.488]],["M 858 -826L 799 -744L 34 -744L 42 -716L 938 -716C 952 -716 963 -721 966 -732C 926 -770 858 -826 858 -826Z",[0.91,0.027]],["M 203 -597L 64 -610L 64 -490C 144 -490 160 -490 164 -490L 164 -572C 192 -577 201 -585 203 -597Z",[0.11,0.048]],["M 203 -596L 203 -374C 203 -222 198 -49 115 87L 125 95C 308 -31 321 -228 321 -374L 321 -586L 339 -586L 203 -634Z",[0.088,0.806]],["M 263 -415L 117 -415L 117 -387L 263 -387Z",[-0.885,0.021]],["M 446 -840L 279 -854L 279 -622L 302 -622C 354 -622 413 -640 413 -648L 413 -815C 438 -819 444 -828 446 -840Z",[0.042,0.357]],["M 888 -656L 838 -586L 289 -586L 289 -558L 951 -558C 965 -558 975 -563 978 -574C 945 -607 888 -656 888 -656Z",[0.796,0.052]],["M 407 -439L 338 -439L 338 -63L 357 -98C 341 -92 318 -75 307 -62L 405 -0L 436 -51L 428 -51L 428 -426Z",[0.008,0.776]],["M 338 -516L 338 -406C 400 -406 428 -406 428 -406L 428 -466L 441 -466Z",[-0.148,0.202]],["M 578 -135L 536 -78L 389 -78L 389 -50L 629 -50C 642 -50 652 -55 654 -66C 626 -95 578 -135 578 -135Z",[0.761,0.071]],["M 555 -524L 513 -466L 389 -466L 389 -438L 608 -438C 621 -438 631 -443 633 -454C 604 -483 555 -524 555 -524Z",[0.673,0.097]],["M 589 -214L 391 -214L 391 -186L 589 -186Z",[-0.935,0.04]],["M 589 -345L 391 -345L 391 -317L 589 -317Z",[-0.765,0.051]],["M 534 -214L 457 -214L 457 -69L 534 -69Z",[-0.018,0.529]],["M 534 -466L 457 -466L 457 -335L 534 -335Z",[-0.073,0.458]],["M 958 -466L 809 -517C 778 -242 660 -42 499 84L 509 95C 718 -1 849 -160 918 -447C 941 -445 953 -453 958 -466Z",[0.391,0.708]],["M 533 -345L 540 -345L 540 -172L 555 -172C 582 -172 625 -189 626 -196L 626 -310C 639 -313 649 -319 653 -324L 572 -384Z",[-0.017,0.581]],["M 739 -841L 571 -854L 571 -645L 592 -645C 644 -645 706 -666 706 -675L 706 -816C 731 -819 737 -829 739 -841Z",[0.085,0.316]],["M 772 -643L 611 -658C 613 -367 634 -116 806 43C 845 77 921 114 965 67C 981 48 976 18 944 -37L 962 -185L 952 -187C 936 -149 914 -102 900 -79C 892 -64 885 -64 873 -75C 752 -182 735 -392 738 -615C 762 -619 771 -631 772 -643Z",[-0.255,0.707]],["M 736 -707L 728 -701C 747 -683 766 -647 769 -615C 856 -557 942 -717 736 -707Z",[0.222,0.312]]],"bbox":{"top":-854,"bottom":114,"left":21,"right":981},"hadv":1000}],"text":"藏","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340},{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"navigator.webdriver","hadv":10779,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p><strong>Source</strong>:  <a href=\"https://intoli.com/blog/not-possible-to-block-chrome-headless/\">https://intoli.com/blog/not-possible-to-block-chrome-headless/</a></p>\n<h2>TL;DR</h2>\n<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#859900;\">Object</span><span style=\"color:#839496;\">.</span><span style=\"color:#b58900;\">defineProperty</span><span style=\"color:#657b83;\">(</span><span style=\"color:#859900;\">navigator</span><span style=\"color:#839496;\">, &#39;</span><span style=\"color:#2aa198;\">webdriver</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#b58900;\">get</span><span style=\"color:#839496;\">: </span><span style=\"color:#657b83;\">() </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#b58900;\">false</span><span style=\"color:#839496;\">,\n</span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span></code></pre>\n</div>\n<h2>Motivation</h2>\n<p><del>N/A</del></p>\n<p>要用 Puppeteer 爬淘宝。然而只要有一点自动化测试的意思，Chrome 就会把 <code>navigator.webdriver</code> 设置成 <code>true</code>。淘宝的登陆页面会判断这个属性。</p>\n","plain":"Source:  https://intoli.com/blog/not-possible-to-block-chrome-headless/\n\nTL;DR\nObject.defineProperty(navigator, 'webdriver', {\n  get: () => false,\n});\n\n\nMotivation\nN/A\n要用 Puppeteer 爬淘宝。然而只要有一点自动化测试的意思，Chrome 就会把 navigator.webdriver 设置成 true。淘宝的登陆页面会判断这个属性。\n"},{"metadata":{"id":"blob-to-datauri","lang":"zh-CN","title":"Blob -> Data URI","tags":["踩坑"],"publish_time":"2019-01-24T17:16:22.192Z","update_time":"2019-01-24T17:16:22.192Z","title_outline":{"groups":[{"chars":[{"char":"B","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -120 300 -242 300 -376L 300 -398C 300 -518 300 -633 304 -747L 130 -747C 133 -631 133 -516 133 -400L 133 -364C 133 -241 133 -119 130 -0Z",[0.0,0.776]],["M 218 -0L 358 -0C 628 -0 699 -110 699 -208C 699 -320 614 -391 401 -403L 399 -393C 596 -415 655 -489 655 -572C 655 -673 585 -747 393 -747L 218 -747L 218 -709L 349 -709C 450 -709 492 -657 492 -567C 492 -466 441 -409 339 -409L 218 -409L 218 -373L 347 -373C 468 -373 525 -321 525 -205C 525 -95 460 -37 353 -37L 218 -37Z",[-0.03,0.521]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":699},"hadv":727},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689}],"text":"Blob","hadv":2419,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":">","components":[["M 569 -387L 90 -640L 63 -591L 523 -358L 523 -377L 63 -144L 90 -96L 569 -348Z",[-0.006,0.063]]],"bbox":{"top":-640,"bottom":-96,"left":63,"right":569},"hadv":615}],"text":">","hadv":615,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599}],"text":"Data","hadv":2403,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"U","components":[["M 36 -713L 198 -698L 228 -698L 392 -713L 392 -747L 36 -747Z",[-0.815,0.01]],["M 417 20C 595 20 692 -84 695 -314L 699 -747L 647 -747L 651 -316C 653 -135 586 -62 470 -62C 355 -62 295 -129 295 -312L 295 -406C 295 -520 295 -634 297 -747L 121 -747C 125 -633 125 -518 125 -406L 125 -297C 125 -61 245 20 417 20Z",[-0.062,0.22]],["M 533 -713L 657 -697L 689 -697L 802 -713L 802 -747L 533 -747Z",[-0.295,0.048]]],"bbox":{"top":-747,"bottom":20,"left":36,"right":802},"hadv":829},{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437}],"text":"URI","hadv":2036,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<blockquote>\n<p>你知道吗，blob 有四种读法</p>\n</blockquote>\n<h1>TL;DR</h1>\n<div class=\"highlighted highlighted-javascript\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-javascript\"><span style=\"color:#268bd2;\">async function </span><span style=\"color:#b58900;\">blobToDataURI</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">blob</span><span style=\"color:#657b83;\">) {\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">reader </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">new </span><span style=\"color:#268bd2;\">FileReader</span><span style=\"color:#657b83;\">()</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">const </span><span style=\"color:#839496;\">result </span><span style=\"color:#657b83;\">= </span><span style=\"color:#859900;\">new Promise</span><span style=\"color:#657b83;\">(</span><span style=\"color:#268bd2;\">resolve =&gt; </span><span style=\"color:#657b83;\">{\n</span><span style=\"color:#839496;\">    reader.</span><span style=\"color:#b58900;\">addEventListener</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&#39;</span><span style=\"color:#2aa198;\">load</span><span style=\"color:#839496;\">&#39;, </span><span style=\"color:#657b83;\">() </span><span style=\"color:#268bd2;\">=&gt; </span><span style=\"color:#b58900;\">resolve</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">reader.result</span><span style=\"color:#657b83;\">))</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#657b83;\">})</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  \n</span><span style=\"color:#839496;\">  reader.</span><span style=\"color:#b58900;\">readAsDataURL</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">blob</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#859900;\">return </span><span style=\"color:#839496;\">result;\n</span><span style=\"color:#657b83;\">}\n</span></code></pre>\n</div>\n<h1>四种读法</h1>\n<p>Literally…</p>\n<ul>\n<li>CreateObjectURL + XHR</li>\n<li>new Response(blob).text() -&gt; Promise</li>\n<li>全新的 FileReader</li>\n<li>转 ArrayBuffer 然后 atob</li>\n</ul>\n<p>FileReader 是全新 ES5 功能，简直是 JS 集大成者。短短五行代码，竟然包含了 Async/Await 全家桶，Event Emitter 全家桶，甚至还有一点 XHR 的味道，佩服佩服。</p>\n","plain":"你知道吗，blob 有四种读法\n\n\nTL;DR\nasync function blobToDataURI(blob) {\n  const reader = new FileReader();\n  const result = new Promise(resolve => {\n    reader.addEventListener('load', () => resolve(reader.result));\n  });\n  \n  reader.readAsDataURL(blob);\n  return result;\n}\n\n\n四种读法\nLiterally…\n- CreateObjectURL + XHR\n- new Response(blob).text() -> Promise\n- 全新的 FileReader\n- 转 ArrayBuffer 然后 atob\nFileReader 是全新 ES5 功能，简直是 JS 集大成者。短短五行代码，竟然包含了 Async/Await 全家桶，Event Emitter 全家桶，甚至还有一点 XHR 的味道，佩服佩服。\n"},{"metadata":{"id":"nginx-json-autoindex","lang":"zh-CN","title":"Nginx 输出 json 格式目录","tags":["踩坑"],"publish_time":"2019-01-16T16:12:02.576Z","update_time":"2019-01-16T16:13:32.907Z","title_outline":{"groups":[{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617}],"text":"Nginx","hadv":3109,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"输","components":[["M 311 -817L 158 -854C 140 -750 72 -492 28 -381L 65 -418C 43 -411 15 -396 -1 -383L 112 -312L 156 -364L 149 -364C 186 -480 251 -718 275 -816L 264 -795C 294 -792 307 -803 311 -817Z",[0.22,0.741]],["M 22 -190L 96 -43C 108 -46 119 -56 124 -69C 253 -145 338 -203 392 -244L 390 -254C 238 -225 86 -198 22 -190Z",[0.597,0.222]],["M 321 -738L 263 -667L 27 -667L 35 -639L 400 -639C 415 -639 425 -644 428 -655C 387 -690 321 -738 321 -738Z",[0.736,0.057]],["M 340 -446L 299 -392L 86 -392L 94 -364L 392 -364C 405 -364 414 -369 417 -380C 388 -408 340 -446 340 -446Z",[0.982,0.062]],["M 298 57L 298 -376L 178 -376L 178 89L 200 89C 262 89 298 64 298 57Z",[0.005,0.74]],["M 335 -564L 203 -578L 203 -374L 227 -374C 264 -374 298 -374 298 -374L 298 -536C 324 -540 332 -550 335 -564Z",[0.045,0.522]],["M 743 -789L 588 -862C 539 -715 444 -589 349 -517L 358 -507C 493 -554 613 -632 700 -774C 723 -770 737 -777 743 -789Z",[0.463,0.535]],["M 496 56L 496 -431L 604 -431L 604 -459L 500 -459L 390 -505L 390 92L 407 92C 453 92 496 67 496 56Z",[0.031,0.78]],["M 601 -322L 465 -322L 465 -294L 601 -294Z",[-0.749,0.089]],["M 621 -181L 485 -181L 485 -153L 621 -153Z",[-0.892,0.068]],["M 704 -635L 650 -568L 498 -568L 506 -540L 776 -540C 790 -540 800 -545 803 -556C 765 -589 704 -635 704 -635Z",[-0.455,0.066]],["M 550 -459L 558 -459L 558 -33C 558 -23 556 -18 545 -18C 535 -18 508 -20 508 -20L 508 -6C 530 -1 539 9 544 21C 550 35 552 58 552 85C 645 77 657 43 657 -25L 657 -420C 672 -423 683 -430 688 -436L 592 -508Z",[0.026,0.797]],["M 676 -807L 661 -795C 712 -681 801 -569 907 -510C 912 -558 938 -596 982 -628L 984 -642C 876 -664 735 -718 676 -807Z",[-0.738,0.521]],["M 802 -450L 691 -461L 691 -68L 707 -68C 738 -68 776 -85 776 -93L 776 -429C 794 -432 800 -440 802 -450Z",[0.035,0.713]],["M 970 -475L 830 -488L 830 -35C 830 -24 826 -20 813 -20C 796 -20 721 -25 721 -25L 721 -11C 759 -4 776 8 788 24C 800 40 804 66 806 99C 920 88 934 47 934 -29L 934 -449C 957 -452 967 -460 970 -475Z",[0.058,0.735]]],"bbox":{"top":-862,"bottom":99,"left":-1,"right":984},"hadv":1000}],"text":"输","hadv":1000,"breakAfter":true},{"chars":[{"char":"出","components":[["M 199 -274L 95 -274L 95 -21L 118 -59C 100 -52 76 -29 62 -12L 201 66L 241 -2L 234 -2L 234 -253Z",[-0.006,0.547]],["M 269 -324L 95 -341L 95 -221C 210 -221 229 -221 234 -221L 234 -301C 258 -305 267 -313 269 -324Z",[0.215,0.018]],["M 246 -693L 144 -693L 144 -449L 166 -487C 149 -480 124 -458 111 -441L 247 -364L 287 -431L 280 -431L 280 -673Z",[-0.003,0.542]],["M 315 -735L 144 -752L 144 -632C 256 -632 275 -632 280 -632L 280 -712C 304 -716 313 -724 315 -735Z",[0.05,0.1]],["M 841 -30L 165 -30L 165 -2L 841 -2Z",[-0.959,0.0]],["M 785 -459L 210 -459L 210 -431L 785 -431Z",[0.857,0.01]],["M 603 -830L 420 -847L 420 -21L 567 -21L 567 -801C 594 -805 601 -815 603 -830Z",[0.004,0.821]],["M 887 -736L 715 -751L 715 -372L 740 -372C 793 -372 855 -394 855 -402L 855 -711C 879 -715 886 -724 887 -736Z",[0.066,0.585]],["M 935 -325L 763 -340L 763 85L 788 85C 841 85 903 62 903 53L 903 -300C 927 -304 934 -313 935 -325Z",[0.024,0.6]]],"bbox":{"top":-847,"bottom":85,"left":62,"right":935},"hadv":1000}],"text":"出","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"j","components":[["M 15 271C 68 271 133 255 188 199C 245 142 262 78 262 -68L 262 -392L 265 -551L 247 -562L 23 -502L 23 -478L 97 -470C 100 -423 101 -378 101 -313L 101 -111C 101 17 109 133 92 191C 85 216 75 228 62 242L 62 250L 80 250L 80 244L 53 187C 34 146 10 127 -24 127C -67 127 -95 151 -104 198C -92 244 -54 271 15 271Z",[0.12,0.706]],["M 177 -655C 224 -655 263 -689 263 -738C 263 -784 224 -819 177 -819C 129 -819 90 -784 90 -738C 90 -689 129 -655 177 -655Z",[0.006,0.007]]],"bbox":{"top":-819,"bottom":271,"left":-104,"right":265},"hadv":347},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"json","hadv":2193,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"格","components":[["M 288 -589L 288 -605L 153 -605C 133 -446 91 -273 17 -152L 28 -142C 164 -257 251 -407 288 -589Z",[0.283,0.699]],["M 358 -690L 302 -605L 29 -605L 37 -577L 429 -577C 443 -577 453 -582 456 -593C 421 -631 358 -690 358 -690Z",[0.826,0.076]],["M 331 -841L 162 -857L 162 95L 188 95C 238 95 294 66 294 53L 294 -812C 322 -816 329 -826 331 -841Z",[0.004,0.859]],["M 293 -509L 283 -504C 304 -463 321 -401 317 -347C 405 -260 526 -435 293 -509Z",[-0.158,0.374]],["M 751 -719L 764 -719C 702 -535 549 -372 341 -277L 347 -265C 622 -331 804 -476 900 -667C 925 -670 935 -673 942 -684L 825 -788Z",[0.551,0.581]],["M 709 -791L 536 -851C 507 -710 445 -573 381 -486L 392 -478C 504 -539 599 -633 668 -772C 691 -770 704 -778 709 -791Z",[0.358,0.578]],["M 461 -333L 461 93L 485 93C 554 93 595 71 595 63L 595 -251L 744 -251L 744 82L 769 82C 841 82 885 59 885 54L 885 -241C 908 -246 917 -252 924 -261L 804 -352L 739 -279L 606 -279ZM 809 -5L 539 -5L 539 23L 809 23Z",[0.193,0.028]],["M 541 -680L 532 -665C 596 -486 692 -354 902 -285C 909 -352 934 -394 991 -417L 993 -428C 767 -460 610 -542 541 -680Z",[-0.521,0.322]],["M 830 -719L 565 -719L 554 -691L 830 -691Z",[-0.488,0.074]]],"bbox":{"top":-857,"bottom":95,"left":17,"right":993},"hadv":1000}],"text":"格","hadv":1000,"breakAfter":true},{"chars":[{"char":"式","components":[["M 31 -623L 39 -595L 944 -595C 959 -595 971 -600 974 -611C 920 -655 831 -720 831 -720L 753 -623Z",[0.984,0.039]],["M 35 -79L 127 72C 139 69 149 60 155 46C 366 -41 497 -104 583 -154L 581 -165C 349 -125 130 -91 35 -79Z",[0.723,0.202]],["M 61 -425L 69 -397L 529 -397C 543 -397 554 -402 557 -413C 509 -455 429 -517 429 -517L 358 -425Z",[0.849,0.07]],["M 231 -425L 231 -50L 376 -67L 376 -425Z",[0.009,0.605]],["M 530 -848C 531 -492 548 -181 762 27C 807 70 901 120 960 67C 981 48 975 7 937 -64L 963 -243L 953 -246C 932 -201 900 -144 882 -117C 871 -101 863 -101 850 -114C 686 -255 673 -521 679 -801C 705 -805 713 -817 715 -830Z",[-0.261,0.727]],["M 715 -816L 708 -810C 739 -782 776 -733 790 -687C 911 -626 991 -849 715 -816Z",[0.01,0.093]]],"bbox":{"top":-849,"bottom":120,"left":31,"right":991},"hadv":1000}],"text":"式","hadv":1000,"breakAfter":true},{"chars":[{"char":"目","components":[["M 165 -769L 165 93L 190 93C 257 93 318 56 318 37L 318 -741L 773 -741L 773 -769L 327 -769L 165 -833Z",[0.096,0.64]],["M 236 -529L 236 -501L 769 -501L 769 -529Z",[-0.874,0.005]],["M 236 -285L 236 -257L 769 -257L 769 -285Z",[-0.945,0.004]],["M 236 -35L 236 -7L 769 -7L 769 -35Z",[0.947,0.0]],["M 685 -769L 685 80L 709 80C 768 80 841 45 843 34L 843 -714C 865 -719 878 -728 886 -738L 747 -850L 674 -769Z",[0.009,0.82]]],"bbox":{"top":-850,"bottom":93,"left":165,"right":886},"hadv":1000}],"text":"目","hadv":1000,"breakAfter":true},{"chars":[{"char":"录","components":[["M 834 -592L 753 -492L 36 -492L 44 -464L 951 -464C 966 -464 978 -469 981 -480C 925 -526 834 -592 834 -592Z",[0.88,0.042]],["M 39 -118L 144 20C 156 14 164 2 166 -12C 331 -135 436 -228 502 -294L 498 -304C 308 -221 118 -145 39 -118Z",[0.624,0.363]],["M 705 -791L 139 -791L 148 -763L 705 -763Z",[0.633,0.024]],["M 153 -437L 146 -432C 182 -390 217 -324 226 -263C 354 -174 469 -419 153 -437Z",[-0.265,0.301]],["M 698 -637L 170 -637L 179 -609L 698 -609Z",[0.715,0.02]],["M 569 -74L 569 -492L 424 -492L 424 -77C 424 -67 419 -60 404 -60C 381 -60 270 -66 270 -66L 270 -54C 327 -44 349 -28 365 -8C 382 13 388 47 390 93C 546 82 569 19 569 -74Z",[0.072,0.691]],["M 563 -475L 557 -472C 605 -195 700 -71 857 25C 872 -42 911 -95 967 -110L 970 -120C 809 -160 627 -245 563 -475Z",[-0.471,0.476]],["M 618 -791L 628 -791L 612 -478L 763 -478L 776 -741C 798 -744 806 -748 814 -758L 674 -859Z",[0.04,0.56]],["M 917 -348L 773 -448C 749 -398 695 -309 650 -252L 659 -243C 736 -269 820 -307 878 -338C 902 -333 912 -339 917 -348Z",[0.418,0.291]]],"bbox":{"top":-859,"bottom":93,"left":36,"right":981},"hadv":1000}],"text":"录","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<h2>TL;DR</h2>\n<pre><code class=\"language-nginx\">autoindex on;\nautoindex_format json;\n</code></pre>\n<p>Who needs a backend?</p>\n<h2>Motivation</h2>\n<p>在写白嫖文库，希望能够完全静态也不需要有 build，所以需要能够拿到后端目录的内容。</p>\n<p>原来以为要解析 autoindex 的 html 输出，但是不同版本的 nginx 会给出不一样的格式。用 json 就没问题了。</p>\n","plain":"\nTL;DR\nautoindex on;\nautoindex_format json;\n\nWho needs a backend?\n\nMotivation\n在写白嫖文库，希望能够完全静态也不需要有 build，所以需要能够拿到后端目录的内容。\n原来以为要解析 autoindex 的 html 输出，但是不同版本的 nginx 会给出不一样的格式。用 json 就没问题了。\n"},{"metadata":{"id":"introducing-bilicast","lang":"zh-CN","title":"在线听鸽，或者离线听鸽","tags":["开发"],"publish_time":"2019-01-02T14:44:23.913Z","update_time":"2019-06-30T13:04:12.870Z","title_outline":{"groups":[{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":true},{"chars":[{"char":"线","components":[["M 352 -779L 182 -848C 165 -766 98 -615 50 -572C 39 -564 14 -558 14 -558L 76 -409C 106 -422 127 -468 131 -541L 65 -541L 66 -529C 153 -580 270 -692 327 -773L 294 -766C 328 -756 347 -765 352 -779Z",[0.385,0.613]],["M 459 -584L 305 -677C 268 -572 144 -385 62 -328C 49 -320 20 -313 20 -313L 82 -165C 111 -178 133 -221 138 -296L 75 -296L 75 -284C 198 -350 363 -492 431 -584L 398 -579C 432 -564 452 -572 459 -584Z",[0.497,0.605]],["M 26 -110L 88 55C 101 51 112 40 117 26C 273 -60 375 -134 444 -189L 442 -198C 283 -156 104 -121 26 -110Z",[0.616,0.256]],["M 34 -549L 78 -424C 187 -468 281 -515 328 -540L 328 -552C 207 -549 86 -548 34 -549Z",[0.688,0.112]],["M 42 -308L 86 -174C 234 -231 353 -288 416 -321L 416 -332C 261 -320 106 -310 42 -308Z",[0.653,0.15]],["M 949 -305L 785 -398C 656 -165 482 -34 272 58L 277 71C 529 17 727 -82 903 -294C 928 -290 941 -293 949 -305Z",[0.629,0.493]],["M 841 -519L 776 -418L 365 -374L 375 -347L 962 -410C 975 -411 987 -419 988 -430C 932 -468 841 -519 841 -519Z",[0.827,0.157]],["M 797 -684L 731 -585L 404 -554L 414 -527L 914 -575C 928 -576 939 -583 941 -595C 885 -633 797 -684 797 -684Z",[0.738,0.157]],["M 685 -837L 508 -854C 509 -497 540 -176 777 35C 827 78 923 125 977 72C 996 53 991 17 951 -51L 977 -229L 968 -232C 945 -187 912 -129 894 -102C 883 -85 874 -85 859 -99C 668 -248 644 -528 650 -808C 676 -812 684 -824 685 -837Z",[-0.299,0.726]],["M 661 -820L 654 -815C 686 -780 721 -723 731 -671C 853 -594 954 -822 661 -820Z",[-0.136,0.161]]],"bbox":{"top":-854,"bottom":125,"left":14,"right":996},"hadv":1000}],"text":"线","hadv":1000,"breakAfter":true},{"chars":[{"char":"听","components":[["M 59 -725L 59 -97L 80 -97C 139 -97 194 -129 194 -144L 194 -697L 306 -697L 306 -725L 197 -725L 59 -781Z",[0.024,0.766]],["M 147 -304L 147 -276L 312 -276L 312 -304Z",[0.772,0.006]],["M 259 -725L 259 -170L 282 -170C 328 -170 394 -196 396 -205L 396 -675C 416 -679 429 -688 436 -696L 311 -793L 249 -725Z",[0.012,0.763]],["M 463 -733L 463 -458C 463 -263 439 -73 256 78L 263 86C 578 -41 605 -267 605 -459L 605 -733L 626 -733L 463 -788L 463 -743Z",[0.139,0.771]],["M 809 -859C 742 -810 607 -735 504 -690L 506 -680C 636 -687 790 -704 884 -722C 919 -709 945 -711 959 -722Z",[0.589,0.164]],["M 532 -489L 532 -461L 959 -461C 973 -461 985 -466 987 -477C 941 -521 862 -586 862 -586L 791 -489Z",[0.82,0.007]],["M 711 -482L 711 94L 739 94C 814 94 858 68 859 62L 859 -482Z",[0.012,0.698]]],"bbox":{"top":-859,"bottom":94,"left":59,"right":987},"hadv":1000}],"text":"听","hadv":1000,"breakAfter":true},{"chars":[{"char":"鸽","components":[["M 363 -812L 178 -857C 148 -701 83 -543 17 -444L 27 -436C 147 -510 249 -624 323 -789C 347 -790 359 -799 363 -812Z",[0.342,0.602]],["M 78 -415L 78 70L 103 70C 172 70 214 40 214 31L 214 -360L 227 -360Z",[-0.005,0.702]],["M 341 -589L 283 -508L 117 -508L 125 -480L 418 -480C 432 -480 443 -485 445 -496C 407 -534 341 -589 341 -589Z",[0.626,0.095]],["M 334 -75L 155 -75L 155 -47L 334 -47Z",[-0.849,0.003]],["M 334 -360L 155 -360L 155 -332L 334 -332Z",[-0.801,0.023]],["M 284 -804L 273 -803C 325 -722 359 -625 370 -567C 455 -474 638 -648 284 -804Z",[-0.239,0.445]],["M 287 -360L 297 -360L 297 36L 320 36C 365 36 433 12 434 4L 434 -310C 455 -314 468 -323 474 -331L 348 -427Z",[0.013,0.676]],["M 727 -234L 672 -162L 450 -162L 458 -134L 799 -134C 813 -134 824 -139 826 -150C 789 -185 727 -234 727 -234Z",[0.798,0.079]],["M 602 -693L 509 -693L 509 -309L 530 -346C 513 -340 490 -319 477 -303L 603 -230L 640 -293L 632 -293L 632 -675Z",[0.01,0.71]],["M 509 -782L 509 -670C 595 -670 632 -670 632 -670L 632 -730L 649 -730Z",[-0.238,0.147]],["M 886 -321L 602 -321L 602 -293L 886 -293Z",[0.896,0.006]],["M 832 -730L 605 -730L 605 -702L 832 -702Z",[-0.415,0.077]],["M 625 -658L 617 -653C 639 -622 661 -572 663 -525C 767 -443 887 -638 625 -658Z",[0.036,0.237]],["M 818 -823L 638 -855C 638 -814 636 -752 633 -717L 678 -717C 706 -739 751 -773 778 -796C 800 -797 814 -805 818 -823Z",[0.314,0.37]],["M 816 -321L 827 -321C 822 -146 814 -53 793 -35C 787 -29 779 -27 764 -27C 745 -27 684 -30 645 -33L 645 -21C 686 -12 718 1 735 19C 751 36 755 61 755 95C 817 95 856 87 887 63C 934 26 948 -59 954 -272C 975 -275 987 -281 994 -290L 882 -383Z",[0.17,0.591]],["M 780 -730L 790 -730C 789 -563 788 -499 776 -486C 772 -481 766 -479 753 -479C 739 -479 706 -480 687 -482L 687 -470C 715 -462 731 -451 742 -435C 754 -418 755 -390 755 -354C 805 -354 838 -364 864 -384C 905 -416 911 -475 912 -682C 932 -686 943 -692 950 -700L 842 -789Z",[0.144,0.61]]],"bbox":{"top":-857,"bottom":95,"left":17,"right":994},"hadv":1000}],"text":"鸽","hadv":1000,"breakAfter":false},{"chars":[{"char":"，","components":[["M 163 54C 118 38 39 11 39 -64C 39 -113 78 -157 135 -157C 190 -157 237 -117 237 -41C 237 60 187 180 56 236L 39 203C 122 162 155 101 163 54Z",[0.017,0.495]]],"bbox":{"top":-157,"bottom":236,"left":39,"right":237},"hadv":1000}],"text":"，","hadv":1000,"breakAfter":true},{"chars":[{"char":"或","components":[["M 26 -112L 108 34C 120 31 130 21 135 8C 334 -77 460 -140 544 -188L 542 -200C 325 -159 115 -124 26 -112Z",[0.719,0.214]],["M 842 -755L 764 -659L 28 -659L 36 -631L 953 -631C 968 -631 979 -636 982 -647C 929 -691 842 -755 842 -755Z",[0.839,0.039]],["M 244 -235L 244 -488L 404 -488L 404 -516L 248 -516L 114 -568L 114 -195L 132 -195C 187 -195 244 -224 244 -235Z",[0.095,0.453]],["M 404 -303L 182 -303L 182 -275L 404 -275Z",[-0.846,0.02]],["M 945 -498L 765 -557C 710 -312 574 -61 279 81L 286 91C 651 -5 818 -239 905 -479C 931 -479 940 -487 945 -498Z",[0.494,0.629]],["M 327 -516L 336 -516L 336 -221L 359 -221C 404 -221 468 -248 469 -257L 469 -471C 486 -475 497 -482 502 -489L 384 -577Z",[0.015,0.581]],["M 705 -833L 521 -852C 521 -446 531 -122 777 47C 834 82 920 119 968 59C 985 38 979 3 939 -58L 961 -231L 952 -234C 931 -189 900 -129 882 -101C 872 -85 864 -85 848 -96C 669 -211 662 -469 669 -804C 695 -808 704 -820 705 -833Z",[-0.263,0.721]],["M 724 -831L 717 -825C 748 -798 783 -748 794 -702C 915 -637 1001 -860 724 -831Z",[0.063,0.179]]],"bbox":{"top":-860,"bottom":119,"left":26,"right":1001},"hadv":1000}],"text":"或","hadv":1000,"breakAfter":true},{"chars":[{"char":"者","components":[["M 781 -832C 643 -619 353 -349 17 -198L 23 -185C 412 -290 715 -515 888 -717C 912 -710 924 -715 932 -724Z",[0.673,0.52]],["M 36 -501L 44 -473L 941 -473C 956 -473 967 -478 970 -489C 922 -531 842 -592 842 -592L 772 -501Z",[0.922,0.03]],["M 121 -688L 129 -660L 685 -660C 699 -660 710 -665 713 -676C 667 -717 589 -776 589 -776L 521 -688Z",[0.791,0.038]],["M 245 -355L 245 95L 266 95C 326 95 387 63 387 49L 387 -327L 747 -327L 747 -355L 395 -355L 245 -413Z",[0.164,0.377]],["M 329 -190L 329 -162L 761 -162L 761 -190Z",[-0.953,0.002]],["M 329 -16L 329 12L 761 12L 761 -16Z",[0.935,0.0]],["M 357 -855L 357 -485L 502 -485L 502 -815C 526 -819 532 -828 534 -841Z",[0.015,0.595]],["M 668 -355L 668 91L 692 91C 740 91 811 65 813 57L 813 -304C 834 -308 846 -318 852 -326L 722 -425L 658 -355Z",[0.017,0.667]]],"bbox":{"top":-855,"bottom":95,"left":17,"right":970},"hadv":1000}],"text":"者","hadv":1000,"breakAfter":true},{"chars":[{"char":"离","components":[["M 840 -815L 769 -716L 37 -716L 45 -688L 940 -688C 954 -688 965 -693 968 -704C 921 -748 840 -815 840 -815Z",[0.933,0.042]],["M 265 47L 265 -273L 847 -273L 847 -301L 276 -301L 121 -360L 121 92L 142 92C 201 92 265 61 265 47Z",[0.398,0.203]],["M 294 -633L 189 -633L 189 -411L 213 -451C 197 -444 177 -422 165 -405L 300 -335L 335 -394L 328 -394L 328 -612Z",[-0.013,0.489]],["M 363 -657L 189 -674L 189 -554C 304 -554 323 -554 328 -554L 328 -634C 352 -638 361 -646 363 -657Z",[0.135,0.028]],["M 779 -422L 275 -422L 275 -394L 779 -394Z",[0.837,0.007]],["M 616 -411L 616 -422L 443 -422C 431 -353 379 -224 340 -185C 330 -178 306 -173 306 -173L 366 -27C 395 -40 416 -86 420 -158L 357 -158L 357 -145C 440 -201 555 -318 616 -411Z",[0.377,0.624]],["M 323 -164L 368 -45C 498 -94 606 -144 662 -171L 661 -184C 522 -173 382 -165 323 -164Z",[0.671,0.141]],["M 699 -626L 566 -700C 525 -615 435 -508 332 -445L 340 -433C 474 -468 592 -541 662 -615C 685 -611 694 -617 699 -626Z",[0.531,0.461]],["M 352 -637L 347 -624C 463 -568 555 -489 591 -443C 696 -399 754 -617 352 -637Z",[-0.561,0.326]],["M 402 -853L 396 -848C 422 -823 449 -777 455 -732C 582 -655 693 -889 402 -853Z",[0.002,0.118]],["M 556 -256L 547 -251C 580 -205 610 -136 615 -75C 723 13 836 -200 556 -256Z",[-0.235,0.348]],["M 745 -301L 755 -301L 755 -57C 755 -46 751 -39 738 -39C 716 -39 641 -44 641 -44L 641 -32C 686 -24 701 -9 714 9C 727 27 730 57 732 97C 879 86 900 39 900 -44L 900 -250C 921 -254 933 -263 939 -271L 807 -371Z",[0.082,0.559]],["M 870 -652L 688 -667L 688 -352L 712 -352C 770 -352 833 -372 833 -380L 833 -624C 861 -628 868 -639 870 -652Z",[0.06,0.496]]],"bbox":{"top":-889,"bottom":97,"left":37,"right":968},"hadv":1000}],"text":"离","hadv":1000,"breakAfter":true},{"chars":[{"char":"线","components":[["M 352 -779L 182 -848C 165 -766 98 -615 50 -572C 39 -564 14 -558 14 -558L 76 -409C 106 -422 127 -468 131 -541L 65 -541L 66 -529C 153 -580 270 -692 327 -773L 294 -766C 328 -756 347 -765 352 -779Z",[0.385,0.613]],["M 459 -584L 305 -677C 268 -572 144 -385 62 -328C 49 -320 20 -313 20 -313L 82 -165C 111 -178 133 -221 138 -296L 75 -296L 75 -284C 198 -350 363 -492 431 -584L 398 -579C 432 -564 452 -572 459 -584Z",[0.497,0.605]],["M 26 -110L 88 55C 101 51 112 40 117 26C 273 -60 375 -134 444 -189L 442 -198C 283 -156 104 -121 26 -110Z",[0.616,0.256]],["M 34 -549L 78 -424C 187 -468 281 -515 328 -540L 328 -552C 207 -549 86 -548 34 -549Z",[0.688,0.112]],["M 42 -308L 86 -174C 234 -231 353 -288 416 -321L 416 -332C 261 -320 106 -310 42 -308Z",[0.653,0.15]],["M 949 -305L 785 -398C 656 -165 482 -34 272 58L 277 71C 529 17 727 -82 903 -294C 928 -290 941 -293 949 -305Z",[0.629,0.493]],["M 841 -519L 776 -418L 365 -374L 375 -347L 962 -410C 975 -411 987 -419 988 -430C 932 -468 841 -519 841 -519Z",[0.827,0.157]],["M 797 -684L 731 -585L 404 -554L 414 -527L 914 -575C 928 -576 939 -583 941 -595C 885 -633 797 -684 797 -684Z",[0.738,0.157]],["M 685 -837L 508 -854C 509 -497 540 -176 777 35C 827 78 923 125 977 72C 996 53 991 17 951 -51L 977 -229L 968 -232C 945 -187 912 -129 894 -102C 883 -85 874 -85 859 -99C 668 -248 644 -528 650 -808C 676 -812 684 -824 685 -837Z",[-0.299,0.726]],["M 661 -820L 654 -815C 686 -780 721 -723 731 -671C 853 -594 954 -822 661 -820Z",[-0.136,0.161]]],"bbox":{"top":-854,"bottom":125,"left":14,"right":996},"hadv":1000}],"text":"线","hadv":1000,"breakAfter":true},{"chars":[{"char":"听","components":[["M 59 -725L 59 -97L 80 -97C 139 -97 194 -129 194 -144L 194 -697L 306 -697L 306 -725L 197 -725L 59 -781Z",[0.024,0.766]],["M 147 -304L 147 -276L 312 -276L 312 -304Z",[0.772,0.006]],["M 259 -725L 259 -170L 282 -170C 328 -170 394 -196 396 -205L 396 -675C 416 -679 429 -688 436 -696L 311 -793L 249 -725Z",[0.012,0.763]],["M 463 -733L 463 -458C 463 -263 439 -73 256 78L 263 86C 578 -41 605 -267 605 -459L 605 -733L 626 -733L 463 -788L 463 -743Z",[0.139,0.771]],["M 809 -859C 742 -810 607 -735 504 -690L 506 -680C 636 -687 790 -704 884 -722C 919 -709 945 -711 959 -722Z",[0.589,0.164]],["M 532 -489L 532 -461L 959 -461C 973 -461 985 -466 987 -477C 941 -521 862 -586 862 -586L 791 -489Z",[0.82,0.007]],["M 711 -482L 711 94L 739 94C 814 94 858 68 859 62L 859 -482Z",[0.012,0.698]]],"bbox":{"top":-859,"bottom":94,"left":59,"right":987},"hadv":1000}],"text":"听","hadv":1000,"breakAfter":true},{"chars":[{"char":"鸽","components":[["M 363 -812L 178 -857C 148 -701 83 -543 17 -444L 27 -436C 147 -510 249 -624 323 -789C 347 -790 359 -799 363 -812Z",[0.342,0.602]],["M 78 -415L 78 70L 103 70C 172 70 214 40 214 31L 214 -360L 227 -360Z",[-0.005,0.702]],["M 341 -589L 283 -508L 117 -508L 125 -480L 418 -480C 432 -480 443 -485 445 -496C 407 -534 341 -589 341 -589Z",[0.626,0.095]],["M 334 -75L 155 -75L 155 -47L 334 -47Z",[-0.849,0.003]],["M 334 -360L 155 -360L 155 -332L 334 -332Z",[-0.801,0.023]],["M 284 -804L 273 -803C 325 -722 359 -625 370 -567C 455 -474 638 -648 284 -804Z",[-0.239,0.445]],["M 287 -360L 297 -360L 297 36L 320 36C 365 36 433 12 434 4L 434 -310C 455 -314 468 -323 474 -331L 348 -427Z",[0.013,0.676]],["M 727 -234L 672 -162L 450 -162L 458 -134L 799 -134C 813 -134 824 -139 826 -150C 789 -185 727 -234 727 -234Z",[0.798,0.079]],["M 602 -693L 509 -693L 509 -309L 530 -346C 513 -340 490 -319 477 -303L 603 -230L 640 -293L 632 -293L 632 -675Z",[0.01,0.71]],["M 509 -782L 509 -670C 595 -670 632 -670 632 -670L 632 -730L 649 -730Z",[-0.238,0.147]],["M 886 -321L 602 -321L 602 -293L 886 -293Z",[0.896,0.006]],["M 832 -730L 605 -730L 605 -702L 832 -702Z",[-0.415,0.077]],["M 625 -658L 617 -653C 639 -622 661 -572 663 -525C 767 -443 887 -638 625 -658Z",[0.036,0.237]],["M 818 -823L 638 -855C 638 -814 636 -752 633 -717L 678 -717C 706 -739 751 -773 778 -796C 800 -797 814 -805 818 -823Z",[0.314,0.37]],["M 816 -321L 827 -321C 822 -146 814 -53 793 -35C 787 -29 779 -27 764 -27C 745 -27 684 -30 645 -33L 645 -21C 686 -12 718 1 735 19C 751 36 755 61 755 95C 817 95 856 87 887 63C 934 26 948 -59 954 -272C 975 -275 987 -281 994 -290L 882 -383Z",[0.17,0.591]],["M 780 -730L 790 -730C 789 -563 788 -499 776 -486C 772 -481 766 -479 753 -479C 739 -479 706 -480 687 -482L 687 -470C 715 -462 731 -451 742 -435C 754 -418 755 -390 755 -354C 805 -354 838 -364 864 -384C 905 -416 911 -475 912 -682C 932 -686 943 -692 950 -700L 842 -789Z",[0.144,0.61]]],"bbox":{"top":-857,"bottom":95,"left":17,"right":994},"hadv":1000}],"text":"鸽","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p><a href=\"https://playlist.meow.plus/meow\">https://playlist.meow.plus/meow</a></p>\n<p>是一个从 B 站上扒歌然后提供各种播放器功能的东西。</p>\n<h2>Motivation</h2>\n<p>因为 B 站没有 mylist 类似物，虽然很久之前有过，但是就和我手边的零食一样，之后莫名其妙就没有了。</p>\n<p>现在唯一能完成列表顺序播放的，要不然自己投个稿，要不然用只有一个的稍后再看。只能顺序播放，据说稍后再看还会自动帮你清理。看来 B 站已经成熟了，学会自己看视频了，简直是产品鬼才。</p>\n<p>所以搞了个管歌单的东西，主要自己用。要不 B 站一纸律师函就不好了。</p>\n<h2>Features</h2>\n<ul>\n<li>离线播放：歌单右上角有下载按钮，会同步到浏览器的缓存里，然后断网也可以提供服务</li>\n<li>P W A: Add to Desktop</li>\n<li>简单的认证</li>\n<li>直接同步 B 站一个公开收藏夹</li>\n<li>可以前后端分离，但是大多数的静态资源会活在后端。可以利用这个把前端扔到国外，就不用备案了</li>\n</ul>\n<h2>源码和搭建</h2>\n<p>GitHub: CircuitCoder/bilicast</p>\n<p>依赖 MongoDB，需要进行配置：</p>\n<ul>\n<li>frontend/src/config.example.js -&gt; frontend/src/config.js</li>\n</ul>\n<p>然后</p>\n<pre><code>yarn install --frozen-lockfile\ncd frontend\nyarn install --frozen-lockfile\nyarn build\ncd ..\nPASSPHRASE=密码 DBURI=数据库 yarn start\n</code></pre>\n<p>不带密码的话任何人都可以修改歌单。不加数据库地址的话会直接用 localhost/bilicast</p>\n<h2>Rambling</h2>\n<p>一年前我说我不要写前端了。现在来看估计前面那篇前端踩坑清单还能更新。</p>\n","plain":"https://playlist.meow.plus/meow\n是一个从 B 站上扒歌然后提供各种播放器功能的东西。\n\nMotivation\n因为 B 站没有 mylist 类似物，虽然很久之前有过，但是就和我手边的零食一样，之后莫名其妙就没有了。\n现在唯一能完成列表顺序播放的，要不然自己投个稿，要不然用只有一个的稍后再看。只能顺序播放，据说稍后再看还会自动帮你清理。看来 B 站已经成熟了，学会自己看视频了，简直是产品鬼才。\n所以搞了个管歌单的东西，主要自己用。要不 B 站一纸律师函就不好了。\n\nFeatures\n- 离线播放：歌单右上角有下载按钮，会同步到浏览器的缓存里，然后断网也可以提供服务\n- P W A: Add to Desktop\n- 简单的认证\n- 直接同步 B 站一个公开收藏夹\n- 可以前后端分离，但是大多数的静态资源会活在后端。可以利用这个把前端扔到国外，就不用备案了\n\n源码和搭建\nGitHub: CircuitCoder/bilicast\n依赖 MongoDB，需要进行配置：\n- frontend/src/config.example.js -> frontend/src/config.js\n然后\nyarn install --frozen-lockfile\ncd frontend\nyarn install --frozen-lockfile\nyarn build\ncd ..\nPASSPHRASE=密码 DBURI=数据库 yarn start\n\n不带密码的话任何人都可以修改歌单。不加数据库地址的话会直接用 localhost/bilicast\n\nRambling\n一年前我说我不要写前端了。现在来看估计前面那篇前端踩坑清单还能更新。\n"},{"metadata":{"id":"hello-2019","lang":"zh-CN","title":"2019","tags":["扯淡"],"publish_time":"2019-01-01T17:19:47.161Z","update_time":"2019-01-01T17:19:47.161Z","title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463},{"char":"9","components":[["M 107 20C 385 -31 572 -206 572 -445C 572 -645 474 -764 299 -764C 159 -764 39 -679 39 -511C 39 -370 133 -290 263 -290C 349 -290 410 -326 437 -372L 448 -372L 425 -380C 395 -350 367 -337 326 -337C 247 -337 198 -410 198 -533C 198 -671 246 -730 303 -730C 365 -730 409 -665 409 -467C 409 -218 321 -84 101 -9Z",[-0.042,0.21]]],"bbox":{"top":-764,"bottom":20,"left":39,"right":572},"hadv":614}],"text":"2019","hadv":2302,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>又到了每年一度的 Year in review / New year resolution 时间了，虽然之前只有两次？总之新习惯是好习惯。</p>\n<p>这垃圾网站我也是写了两年半没改过，现在来看还 Decent，真是不可思议，按照前端的进化速度，应该在早就出现各种问题才对，毕竟当时 Chrome 的版本号还是 2 字开头。但是很幸运，这个网站一直没有坏掉，就算它也一直没有完工，总之就苟且着，说不定就这么一直苟且下去了呢？</p>\n<p>不知道能不能说是健康状态。类比到人体身上，新陈代谢才健康，只进不出是会变胖的。但总感觉有一点是确乎的，那就是苟且也可以授予意义。如果钟摆终于停下不动，就算依靠崭新的物理事实，它或许还可以继续指示时间，但是对于钟摆自己而言，恐怕是每日都会无聊的多吧！</p>\n<p>所以我可以信誓旦旦地说，过去的一年里，我过的很充实，在弯路上看到了很多漂亮的风景，沿途也遇到了许多的人。现在我回到了原点，在接下来的一年里，我要开辟新的道路，获得全新的视角，将发自内心的呐喊不断向别人倾诉。我要制造出我自己的希望的光。</p>\n<p>这是我的自大，2019 年度的膨胀。</p>\n","plain":"又到了每年一度的 Year in review / New year resolution 时间了，虽然之前只有两次？总之新习惯是好习惯。\n这垃圾网站我也是写了两年半没改过，现在来看还 Decent，真是不可思议，按照前端的进化速度，应该在早就出现各种问题才对，毕竟当时 Chrome 的版本号还是 2 字开头。但是很幸运，这个网站一直没有坏掉，就算它也一直没有完工，总之就苟且着，说不定就这么一直苟且下去了呢？\n不知道能不能说是健康状态。类比到人体身上，新陈代谢才健康，只进不出是会变胖的。但总感觉有一点是确乎的，那就是苟且也可以授予意义。如果钟摆终于停下不动，就算依靠崭新的物理事实，它或许还可以继续指示时间，但是对于钟摆自己而言，恐怕是每日都会无聊的多吧！\n所以我可以信誓旦旦地说，过去的一年里，我过的很充实，在弯路上看到了很多漂亮的风景，沿途也遇到了许多的人。现在我回到了原点，在接下来的一年里，我要开辟新的道路，获得全新的视角，将发自内心的呐喊不断向别人倾诉。我要制造出我自己的希望的光。\n这是我的自大，2019 年度的膨胀。\n"},{"metadata":{"id":"compiling-aur-mingw-w64-bzip2","lang":"zh-CN","title":"编译 aur/mingw-w64-bzip2","tags":["技术","踩坑"],"publish_time":"2018-11-10T16:52:33.500Z","update_time":"2018-11-10T16:54:10.204Z","title_outline":{"groups":[{"chars":[{"char":"编","components":[["M 332 -784L 169 -845C 155 -761 96 -606 52 -558C 43 -550 19 -544 19 -544L 77 -404C 106 -416 126 -459 130 -528L 68 -528L 68 -516C 148 -573 253 -692 305 -778L 273 -770C 308 -760 326 -770 332 -784Z",[0.346,0.646]],["M 406 -578L 258 -664C 230 -562 132 -380 64 -321C 54 -313 27 -307 27 -307L 85 -166C 114 -178 134 -220 139 -290L 78 -290L 79 -277C 183 -345 318 -487 377 -578L 346 -572C 379 -558 399 -566 406 -578Z",[0.437,0.649]],["M 36 -106L 100 51C 113 47 124 35 128 22C 228 -59 296 -125 339 -170L 337 -179C 219 -145 92 -115 36 -106Z",[0.481,0.274]],["M 45 -537L 86 -420C 178 -460 262 -503 301 -526L 301 -538C 197 -536 91 -535 45 -537Z",[0.574,0.099]],["M 54 -302L 97 -175C 209 -228 305 -283 352 -313L 351 -324C 229 -312 106 -304 54 -302Z",[0.604,0.159]],["M 377 -722L 377 -507C 377 -320 367 -98 260 79L 270 87C 482 -74 497 -331 497 -508L 497 -712L 515 -712L 377 -761Z",[0.104,0.822]],["M 571 57L 571 -398L 584 -398L 467 -443L 467 89L 485 89C 538 89 571 65 571 57Z",[-0.006,0.831]],["M 872 -539L 468 -539L 468 -511L 872 -511Z",[-0.845,0.035]],["M 872 -712L 468 -712L 468 -684L 872 -684Z",[-0.752,0.021]],["M 884 -230L 552 -230L 552 -202L 884 -202Z",[0.869,0.023]],["M 887 -398L 555 -398L 555 -370L 887 -370Z",[0.8,0.04]],["M 578 -854L 571 -849C 594 -818 615 -768 617 -721C 726 -635 851 -840 578 -854Z",[0.027,0.234]],["M 686 12L 686 -388L 611 -388L 611 32L 624 32C 661 32 685 17 686 12Z",[-0.001,0.79]],["M 798 -41L 798 -388L 724 -388L 724 -21L 736 -21C 774 -21 798 -36 798 -41Z",[0.001,0.877]],["M 829 -398L 838 -398L 838 -39C 838 -28 835 -22 823 -22C 808 -22 756 -25 756 -25L 756 -12C 788 -5 801 6 810 20C 819 35 822 60 823 92C 933 83 947 44 947 -29L 947 -357C 963 -360 974 -367 979 -374L 876 -451Z",[0.051,0.703]],["M 797 -712L 806 -712L 806 -468L 827 -468C 865 -468 926 -489 927 -496L 927 -670C 943 -673 954 -680 959 -686L 850 -767Z",[0.054,0.513]]],"bbox":{"top":-854,"bottom":92,"left":19,"right":979},"hadv":1000}],"text":"编","hadv":1000,"breakAfter":true},{"chars":[{"char":"译","components":[["M 230 -569L 17 -569L 26 -541L 230 -541Z",[-0.888,0.008]],["M 233 -542L 133 -542L 133 -150C 133 -127 125 -116 74 -87L 175 59C 204 39 236 -17 208 -102L 143 -48L 266 -100L 266 -522Z",[0.048,0.755]],["M 90 -842L 83 -837C 121 -790 166 -720 184 -656C 313 -576 411 -818 90 -842Z",[-0.282,0.322]],["M 95 -87L 181 38C 274 -77 342 -185 374 -239L 369 -247C 258 -178 143 -111 95 -87Z",[0.438,0.425]],["M 135 -567L 133 -567L 133 -487L 266 -487L 266 -525L 257 -516C 290 -518 303 -527 309 -535L 197 -628Z",[0.092,0.013]],["M 717 -780L 730 -780C 663 -608 499 -471 284 -394L 289 -382C 568 -427 767 -546 873 -727C 898 -729 908 -732 915 -743L 794 -851Z",[0.582,0.506]],["M 837 -246L 764 -145L 327 -145L 335 -117L 939 -117C 954 -117 965 -122 968 -133C 920 -178 837 -246 837 -246Z",[0.857,0.064]],["M 754 -780L 331 -780L 340 -752L 754 -752Z",[0.639,0.019]],["M 785 -390L 722 -303L 369 -303L 377 -275L 872 -275C 886 -275 897 -280 899 -291C 857 -331 785 -390 785 -390Z",[0.817,0.076]],["M 429 -779L 417 -771C 493 -542 655 -453 887 -404C 900 -467 933 -511 986 -526L 986 -538C 746 -552 519 -603 429 -779Z",[-0.674,0.296]],["M 715 -426L 541 -441L 541 94L 567 94C 620 94 683 69 683 59L 683 -400C 707 -404 713 -413 715 -426Z",[0.013,0.713]]],"bbox":{"top":-851,"bottom":94,"left":17,"right":986},"hadv":1000}],"text":"译","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"aur","hadv":1810,"breakAfter":false},{"chars":[{"char":"/","components":[["M 26 181L 96 181L 399 -804L 330 -804Z",[0.277,0.894]]],"bbox":{"top":-804,"bottom":181,"left":26,"right":399},"hadv":425}],"text":"/","hadv":425,"breakAfter":true},{"chars":[{"char":"m","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -444L 255 -553L 242 -562L 24 -499L 24 -476L 97 -468C 101 -419 101 -387 101 -322L 101 -238C 101 -168 100 -51 97 -0Z",[-0.018,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 438 -0L 604 -0C 602 -51 600 -165 600 -238L 600 -370C 600 -501 544 -563 442 -563C 358 -563 296 -516 240 -436L 221 -436L 224 -384C 269 -443 324 -487 373 -487C 421 -487 442 -455 442 -373L 442 -238C 442 -165 441 -51 438 -0Z",[-0.125,0.594]],["M 376 -0L 661 -0L 661 -31L 556 -41L 476 -41L 376 -31Z",[0.861,0.001]],["M 775 -0L 940 -0C 938 -51 937 -165 937 -238L 937 -364C 937 -500 886 -563 774 -563C 698 -563 636 -529 578 -445L 554 -445L 559 -386C 611 -451 659 -487 708 -487C 756 -487 778 -461 778 -373L 778 -238C 778 -165 777 -51 775 -0Z",[-0.14,0.604]],["M 716 -0L 999 -0L 999 -31L 893 -41L 810 -41L 716 -31Z",[-0.857,0.002]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":999},"hadv":1025},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893}],"text":"mingw","hadv":3585,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"w","components":[["M -9 -516L 97 -504L 152 -504L 286 -516L 286 -546L -9 -546Z",[0.95,0.002]],["M 223 2L 291 2L 443 -419L 451 -441L 419 -441L 570 2L 639 2L 828 -546L 780 -546L 658 -136L 654 -125L 671 -125L 527 -546L 445 -546L 312 -137L 308 -125L 322 -126L 193 -546L 27 -546Z",[-0.299,0.058]],["M 361 -516L 470 -504L 513 -504L 621 -516L 621 -546L 361 -546Z",[-0.677,0.041]],["M 682 -516L 785 -504L 802 -504L 889 -516L 889 -546L 682 -546Z",[-0.694,0.057]]],"bbox":{"top":-546,"bottom":2,"left":-9,"right":889},"hadv":893},{"char":"6","components":[["M 317 17C 477 17 573 -90 573 -231C 573 -364 501 -457 370 -457C 290 -457 224 -424 179 -361L 170 -361L 190 -347C 225 -387 266 -400 307 -400C 378 -400 415 -337 415 -216C 415 -76 373 -18 318 -18C 250 -18 204 -109 204 -323C 204 -529 318 -689 533 -739L 528 -764C 238 -738 40 -535 40 -289C 40 -96 148 17 317 17Z",[-0.032,0.21]]],"bbox":{"top":-764,"bottom":17,"left":40,"right":573},"hadv":613},{"char":"4","components":[["M 333 15L 476 15L 476 -760L 364 -760L 33 -253L 33 -169L 585 -169L 585 -273L 82 -273L 82 -292L 71 -248L 220 -478L 350 -679L 315 -670L 333 -670L 333 -203Z",[0.026,0.399]]],"bbox":{"top":-760,"bottom":15,"left":33,"right":585},"hadv":612}],"text":"w64","hadv":2118,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"z","components":[["M 27 -0L 495 -0L 505 -184L 449 -184L 395 -19L 425 -35L 196 -35L 193 -53L 189 -15L 493 -514L 493 -546L 41 -546L 33 -378L 88 -375L 140 -530L 101 -511L 331 -511L 339 -500L 339 -530L 27 -31Z",[0.032,0.299]]],"bbox":{"top":-546,"bottom":0,"left":27,"right":505},"hadv":526},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613}],"text":"bzip2","hadv":2875,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>最新版的 <code>mingw-w64-configure</code> 不知道出了什么锅，不会自动设置 CC，所以要改一下 PKGBUILD. 对于 1.0.6-8 版本:</p>\n<div class=\"highlighted highlighted-diff\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-diff\"><span style=\"color:#586e75;\">--- PKGBUILD.old        2018-11-11 00:47:26.751880500 +0800\n</span><span style=\"color:#586e75;\">+++ PKGBUILD    2018-11-11 00:52:52.561756100 +0800\n</span><span style=\"color:#268bd2;\">@@ -33,7 +33,7 @@\n</span><span style=\"color:#839496;\">   cd &quot;$srcdir/bzip2-$pkgver&quot;\n</span><span style=\"color:#839496;\">   for _arch in ${_architectures}; do\n</span><span style=\"color:#839496;\">     mkdir -p build-${_arch} &amp;&amp; pushd build-${_arch}\n</span><span style=\"color:#dc322f;\">-    ${_arch}-configure\n</span><span style=\"color:#859900;\">+    CC=${_arch}-gcc CXX=${_arch}-g++ ${_arch}-configure\n</span><span style=\"color:#839496;\">     make\n</span><span style=\"color:#839496;\">     popd\n</span><span style=\"color:#839496;\">   done\n</span></code></pre>\n</div>\n<p>啊，我死了.jpg</p>\n","plain":"最新版的 mingw-w64-configure 不知道出了什么锅，不会自动设置 CC，所以要改一下 PKGBUILD. 对于 1.0.6-8 版本:\n--- PKGBUILD.old        2018-11-11 00:47:26.751880500 +0800\n+++ PKGBUILD    2018-11-11 00:52:52.561756100 +0800\n@@ -33,7 +33,7 @@\n   cd \"$srcdir/bzip2-$pkgver\"\n   for _arch in ${_architectures}; do\n     mkdir -p build-${_arch} && pushd build-${_arch}\n-    ${_arch}-configure\n+    CC=${_arch}-gcc CXX=${_arch}-g++ ${_arch}-configure\n     make\n     popd\n   done\n\n啊，我死了.jpg\n"},{"metadata":{"id":"migrate-minio-server","lang":"zh-CN","title":"搭建/迁移 Minio 服务器","tags":["技术"],"publish_time":"2018-10-07T09:52:28.759Z","update_time":"2018-10-07T10:07:11.811Z","title_outline":{"groups":[{"chars":[{"char":"搭","components":[["M 13 -379L 66 -220C 79 -224 90 -235 94 -249C 230 -336 324 -408 381 -455L 379 -464C 230 -426 72 -390 13 -379Z",[0.602,0.278]],["M 26 -614L 34 -586L 380 -586C 393 -586 403 -591 406 -602C 378 -643 318 -711 318 -711L 267 -614Z",[0.725,0.064]],["M 139 -856L 139 -62C 139 -52 135 -47 121 -47C 103 -47 28 -52 28 -52L 28 -39C 69 -31 86 -17 98 3C 110 23 114 54 116 96C 251 84 269 36 269 -54L 269 -812C 294 -815 304 -825 306 -840Z",[0.027,0.847]],["M 673 -564C 709 -445 794 -348 893 -291C 899 -346 932 -404 987 -423L 987 -436C 888 -454 747 -494 685 -574C 716 -577 726 -583 729 -596L 543 -639C 521 -531 407 -366 292 -273L 298 -264C 446 -325 605 -441 673 -564Z",[-0.513,0.025]],["M 335 -721L 343 -693L 953 -693C 967 -693 977 -698 980 -709C 943 -748 877 -806 877 -806L 819 -721Z",[0.893,0.058]],["M 410 -214L 410 94L 429 94C 485 94 545 65 545 53L 545 -186L 773 -186L 773 -214L 550 -214L 410 -268Z",[0.151,0.317]],["M 443 -848L 443 -593L 459 -593C 510 -593 573 -622 573 -634L 573 -811C 597 -815 603 -824 605 -836Z",[0.022,0.422]],["M 484 -342L 492 -314L 777 -314C 791 -314 801 -319 804 -330C 766 -367 702 -420 702 -420L 645 -342Z",[0.756,0.061]],["M 490 -3L 490 25L 793 25L 793 -3Z",[0.908,0.001]],["M 687 -848L 687 -602L 707 -602C 757 -602 817 -624 817 -633L 817 -810C 841 -814 847 -823 849 -835Z",[-0.018,0.307]],["M 739 -214L 739 85L 763 85C 809 85 875 58 876 50L 876 -164C 897 -168 910 -177 916 -185L 790 -280L 729 -214Z",[0.02,0.572]]],"bbox":{"top":-856,"bottom":96,"left":13,"right":987},"hadv":1000}],"text":"搭","hadv":1000,"breakAfter":true},{"chars":[{"char":"建","components":[["M 231 -447L 242 -447C 229 -240 183 -39 19 84L 26 95C 268 -8 343 -196 372 -400C 394 -403 403 -407 409 -418L 294 -514Z",[0.286,0.711]],["M 269 -747L 28 -747L 37 -719L 269 -719Z",[-0.938,0.008]],["M 332 -704L 206 -747C 184 -679 114 -518 73 -447L 114 -480C 92 -475 65 -460 50 -447L 168 -377L 207 -419L 201 -419C 236 -489 305 -641 332 -704Z",[0.275,0.575]],["M 71 -376L 62 -372C 152 -5 335 64 736 64C 772 64 854 64 890 64C 893 8 919 -44 973 -56L 973 -67C 912 -66 795 -66 746 -66C 362 -66 173 -107 71 -376Z",[-0.754,0.173]],["M 302 -447L 136 -447L 122 -419L 302 -419Z",[-0.982,0.0]],["M 193 -747L 206 -747L 219 -690C 274 -681 342 -680 362 -702L 250 -804Z",[-0.559,0.207]],["M 902 -701L 851 -614L 316 -614L 324 -586L 964 -586C 978 -586 988 -591 991 -602C 961 -640 902 -701 902 -701Z",[0.818,0.054]],["M 818 -314L 747 -223L 333 -223L 341 -195L 920 -195C 934 -195 946 -200 949 -211C 900 -253 818 -314 818 -314Z",[0.857,0.062]],["M 777 -741L 369 -741L 378 -713L 777 -713Z",[-0.832,0.02]],["M 796 -440L 733 -355L 375 -355L 383 -327L 883 -327C 898 -327 908 -332 911 -343C 869 -382 796 -440 796 -440Z",[0.853,0.063]],["M 773 -485L 384 -485L 393 -457L 773 -457Z",[-0.829,0.008]],["M 697 -838L 523 -854L 523 -75L 550 -75C 603 -75 660 -99 660 -109L 660 -809C 688 -813 695 -823 697 -838Z",[0.009,0.815]],["M 709 -741L 719 -741L 719 -421L 741 -421C 784 -421 849 -443 850 -451L 850 -693C 869 -697 882 -706 888 -713L 767 -804Z",[0.055,0.578]]],"bbox":{"top":-854,"bottom":95,"left":19,"right":991},"hadv":1000}],"text":"建","hadv":1000,"breakAfter":false},{"chars":[{"char":"/","components":[["M 26 181L 96 181L 399 -804L 330 -804Z",[0.277,0.894]]],"bbox":{"top":-804,"bottom":181,"left":26,"right":399},"hadv":425}],"text":"/","hadv":425,"breakAfter":true},{"chars":[{"char":"迁","components":[["M 244 -156C 219 -156 103 -95 26 -63L 119 88C 128 83 134 75 132 65C 166 5 214 -67 232 -100C 245 -120 257 -123 271 -100C 347 17 427 72 637 72C 712 72 831 72 885 72C 892 11 924 -44 980 -58L 980 -69C 876 -62 789 -60 685 -60C 467 -60 357 -79 285 -141C 271 -152 264 -156 244 -156Z",[-0.821,0.068]],["M 294 -131L 294 -439C 323 -444 338 -452 347 -462L 209 -572L 143 -485L 39 -485L 45 -457L 160 -457L 160 -97Z",[-0.024,0.606]],["M 94 -832L 86 -827C 127 -768 170 -686 184 -611C 310 -518 420 -764 94 -832Z",[-0.238,0.4]],["M 852 -599L 780 -499L 320 -499L 328 -471L 952 -471C 967 -471 978 -476 981 -487C 934 -532 852 -599 852 -599Z",[0.846,0.068]],["M 920 -718L 781 -853C 686 -801 497 -731 347 -695L 349 -683C 518 -682 719 -697 846 -720C 881 -707 906 -708 920 -718Z",[0.633,0.146]],["M 703 -145L 703 -743L 563 -701L 563 -108L 589 -108C 659 -108 702 -137 703 -145Z",[0.007,0.768]]],"bbox":{"top":-853,"bottom":88,"left":26,"right":981},"hadv":1000}],"text":"迁","hadv":1000,"breakAfter":true},{"chars":[{"char":"移","components":[["M 156 -534C 134 -381 88 -204 16 -85L 27 -75C 164 -188 261 -338 302 -518L 302 -534Z",[0.298,0.676]],["M 303 -847C 244 -793 123 -715 22 -671L 24 -662C 153 -667 296 -686 386 -711C 422 -700 446 -703 459 -714Z",[0.637,0.157]],["M 30 -534L 38 -506L 433 -506C 447 -506 457 -511 460 -522C 422 -562 354 -622 354 -622L 294 -534Z",[0.904,0.08]],["M 165 -702L 165 96L 191 96C 259 96 303 66 303 57L 303 -757Z",[0.008,0.832]],["M 299 -438L 290 -433C 315 -387 335 -320 332 -260C 429 -167 556 -362 299 -438Z",[-0.167,0.378]],["M 813 -336C 754 -135 597 7 347 82L 352 94C 668 53 858 -75 954 -282C 979 -285 988 -288 995 -299L 875 -407L 800 -336Z",[0.555,0.521]],["M 644 -486C 603 -377 499 -225 385 -140L 391 -129C 546 -183 694 -299 763 -401C 782 -399 793 -402 797 -411Z",[0.521,0.526]],["M 790 -734C 736 -563 596 -427 393 -351L 398 -339C 665 -385 842 -504 933 -683C 956 -685 966 -688 973 -699L 852 -805L 777 -734Z",[0.548,0.538]],["M 596 -856C 566 -750 494 -630 417 -564L 424 -556C 550 -605 663 -699 730 -796C 757 -793 765 -798 769 -809Z",[0.466,0.505]],["M 548 -640L 542 -634C 570 -613 594 -569 595 -529C 708 -455 809 -670 548 -640Z",[-0.054,0.02]],["M 565 -253L 558 -248C 586 -219 609 -169 609 -123C 722 -40 839 -254 565 -253Z",[-0.19,0.169]],["M 623 -336L 608 -308L 879 -308L 879 -336Z",[-0.795,0.071]],["M 623 -734L 609 -706L 850 -706L 850 -734Z",[0.606,0.063]]],"bbox":{"top":-856,"bottom":96,"left":16,"right":995},"hadv":1000}],"text":"移","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637}],"text":"Minio","hadv":3064,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"服","components":[["M 83 -786L 83 -498C 83 -307 85 -85 23 89L 33 95C 210 -70 213 -315 213 -498L 213 -786L 233 -786L 83 -838L 83 -796Z",[0.053,0.842]],["M 147 -786L 147 -758L 331 -758L 331 -786Z",[0.331,0.028]],["M 147 -551L 147 -523L 331 -523L 331 -551Z",[0.665,0.008]],["M 147 -312L 147 -284L 331 -284L 331 -312Z",[0.769,0.008]],["M 274 -786L 274 -75C 274 -64 271 -57 256 -57C 240 -57 174 -61 174 -61L 174 -48C 213 -40 228 -25 239 -5C 249 13 253 47 255 90C 391 79 409 30 409 -61L 409 -740C 427 -743 438 -751 444 -758L 324 -853L 264 -786Z",[0.026,0.838]],["M 464 -786L 464 95L 489 95C 558 95 599 63 599 53L 599 -786L 613 -786L 464 -841Z",[0.0,0.847]],["M 531 -786L 531 -758L 834 -758L 834 -786Z",[-0.817,0.011]],["M 535 -453L 544 -425L 857 -425L 857 -453Z",[0.889,0.011]],["M 801 -453C 784 -269 729 -67 601 62L 609 72C 816 -37 905 -222 942 -405C 964 -408 973 -412 979 -423L 858 -524L 790 -453Z",[0.29,0.686]],["M 646 -450L 633 -445C 659 -149 725 -20 864 91C 888 23 933 -20 992 -30L 994 -42C 829 -108 689 -206 646 -450Z",[-0.379,0.535]],["M 788 -786C 786 -695 783 -648 774 -639C 769 -635 764 -633 750 -633C 734 -633 680 -636 649 -638L 649 -627C 686 -618 713 -607 728 -589C 744 -571 747 -549 747 -513C 808 -513 842 -519 871 -538C 912 -564 920 -613 923 -736C 942 -739 953 -746 960 -754L 845 -847L 778 -786Z",[0.182,0.41]]],"bbox":{"top":-853,"bottom":95,"left":23,"right":994},"hadv":1000}],"text":"服","hadv":1000,"breakAfter":true},{"chars":[{"char":"务","components":[["M 641 -733L 656 -733C 552 -549 306 -424 23 -360L 27 -348C 371 -367 650 -468 811 -670C 838 -672 849 -675 857 -687L 730 -809Z",[0.679,0.415]],["M 595 -390L 395 -413C 397 -227 345 -34 44 84L 49 95C 431 20 530 -150 557 -363C 582 -364 593 -374 595 -390Z",[0.422,0.574]],["M 524 -814L 325 -860C 280 -723 177 -568 70 -485L 77 -478C 242 -539 394 -665 484 -799C 512 -798 520 -803 524 -814Z",[0.471,0.515]],["M 751 -277L 109 -277L 118 -249L 751 -249Z",[0.922,0.002]],["M 700 -733L 322 -733L 297 -705L 700 -705Z",[0.518,0.044]],["M 318 -717L 308 -709C 408 -481 613 -395 880 -354C 893 -425 927 -474 988 -493L 988 -506C 718 -508 434 -551 318 -717Z",[-0.723,0.235]],["M 692 -277L 702 -277C 693 -160 677 -81 655 -65C 647 -59 639 -57 623 -57C 601 -57 516 -62 460 -66L 460 -56C 513 -45 556 -27 579 -6C 600 15 605 48 604 87C 679 87 719 76 754 54C 808 19 833 -70 846 -224C 867 -227 879 -234 887 -242L 764 -344Z",[0.23,0.455]]],"bbox":{"top":-860,"bottom":95,"left":23,"right":988},"hadv":1000}],"text":"务","hadv":1000,"breakAfter":true},{"chars":[{"char":"器","components":[["M 572 -491L 405 -546C 359 -423 254 -282 27 -188L 32 -177C 311 -238 461 -352 531 -473C 554 -471 568 -478 572 -491Z",[0.596,0.48]],["M 851 -508L 783 -422L 28 -422L 36 -394L 947 -394C 962 -394 973 -399 976 -410C 929 -450 851 -508 851 -508Z",[0.909,0.033]],["M 254 -514L 254 -748L 390 -748L 390 -776L 258 -776L 127 -827L 127 -476L 145 -476C 198 -476 254 -503 254 -514Z",[0.081,0.453]],["M 264 56L 264 -201L 400 -201L 400 -229L 268 -229L 186 -261L 137 -229L 137 96L 155 96C 208 96 264 68 264 56Z",[0.101,0.51]],["M 403 -586L 186 -586L 186 -558L 403 -558Z",[-0.674,0.032]],["M 412 -9L 195 -9L 195 19L 412 19Z",[0.87,0.001]],["M 328 -776L 338 -776L 338 -519L 361 -519C 404 -519 467 -545 468 -553L 468 -730C 486 -734 498 -742 503 -749L 385 -837Z",[0.019,0.526]],["M 336 -229L 346 -229L 346 78L 369 78C 412 78 475 52 476 43L 476 -183C 494 -187 506 -195 511 -202L 394 -290Z",[0.018,0.599]],["M 660 48L 660 -201L 805 -201L 805 -229L 664 -229L 530 -281L 530 88L 548 88C 603 88 660 59 660 48Z",[0.085,0.483]],["M 672 -547L 672 -748L 817 -748L 817 -776L 676 -776L 542 -827L 542 -508L 560 -508C 614 -508 672 -536 672 -547Z",[0.068,0.341]],["M 575 -422L 565 -418C 638 -301 729 -220 930 -163C 934 -230 953 -281 982 -300L 983 -311C 794 -318 654 -350 575 -422Z",[-0.619,0.232]],["M 594 -540L 586 -534C 611 -512 636 -470 640 -433C 737 -371 823 -553 594 -540Z",[-0.189,0.137]],["M 807 -9L 590 -9L 590 19L 807 19Z",[0.864,0.004]],["M 820 -586L 603 -586L 603 -558L 820 -558Z",[-0.462,0.089]],["M 738 -229L 748 -229L 748 83L 771 83C 813 83 880 61 881 54L 881 -179C 902 -184 915 -193 921 -201L 797 -294Z",[0.021,0.566]],["M 752 -776L 762 -776L 762 -506L 785 -506C 827 -506 894 -528 895 -534L 895 -726C 916 -730 929 -740 935 -748L 811 -841Z",[0.055,0.513]]],"bbox":{"top":-841,"bottom":96,"left":27,"right":983},"hadv":1000}],"text":"器","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>今天要迁移服务器，重新搭了个 Minio 的服务器，记一下踩的坑。</p>\n<h2>Nginx 代理配置</h2>\n<p>一定要写上 Host Header 的代理，否则请求签名两边对不上。</p>\n<pre><code class=\"language-nginx\">proxy_set_header Host $http_host;\n</code></pre>\n<p>最大 Body 限制也要增加，5MB 是最小的，因为 minio-js 会把大文件切分成 5M Chunk</p>\n<h2>迁移数据</h2>\n<p>直接把 store 复制过去是不行的，需要用 mc mirror</p>\n<p>因为听了文档的鬼话用了 Client 的 Docker Image，所以需要做额外的 host config。然后因为要直接用外面的端口，需要加个 <code>--net=host</code></p>\n<pre><code>$ docker run -it --net=host --entrypoint=/bin/sh minio/mc\n&gt; mc config host add local http://localhost:9000 xxx xxxxx\n</code></pre>\n<h2>升级 minio-js</h2>\n<p>鬼知道哪个大版本内部搞了个 Breaking change，fPutObject的第四个参数变成对象了。换了 yarn.lock 毫不知情，结果调了一下午。升级到 ^7.0.0 之后改了调用签名，之后写死在 lock 里了，希望以后不要爆炸。</p>\n","plain":"今天要迁移服务器，重新搭了个 Minio 的服务器，记一下踩的坑。\n\nNginx 代理配置\n一定要写上 Host Header 的代理，否则请求签名两边对不上。\nproxy_set_header Host $http_host;\n\n最大 Body 限制也要增加，5MB 是最小的，因为 minio-js 会把大文件切分成 5M Chunk\n\n迁移数据\n直接把 store 复制过去是不行的，需要用 mc mirror\n因为听了文档的鬼话用了 Client 的 Docker Image，所以需要做额外的 host config。然后因为要直接用外面的端口，需要加个 --net=host\n$ docker run -it --net=host --entrypoint=/bin/sh minio/mc\n> mc config host add local http://localhost:9000 xxx xxxxx\n\n\n升级 minio-js\n鬼知道哪个大版本内部搞了个 Breaking change，fPutObject的第四个参数变成对象了。换了 yarn.lock 毫不知情，结果调了一下午。升级到 ^7.0.0 之后改了调用签名，之后写死在 lock 里了，希望以后不要爆炸。\n"},{"metadata":{"id":"gugu-forecast","lang":"zh-CN","title":"近期开发计划","tags":["Meta"],"publish_time":"2018-09-08T08:59:23.594Z","update_time":"2018-09-08T08:59:35.106Z","title_outline":{"groups":[{"chars":[{"char":"近","components":[["M 231 -162C 205 -162 89 -87 14 -49L 105 94C 114 89 119 81 117 70C 151 8 200 -70 220 -106C 232 -126 243 -129 257 -106C 333 20 419 77 631 77C 710 77 830 77 889 77C 895 19 926 -31 980 -45L 980 -56C 872 -49 783 -48 676 -48C 454 -47 347 -70 271 -146C 258 -158 251 -162 231 -162Z",[-0.822,0.075]],["M 278 -137L 278 -442C 307 -447 322 -455 330 -465L 196 -572L 133 -488L 25 -488L 31 -460L 148 -460L 148 -105Z",[-0.026,0.605]],["M 89 -835L 81 -830C 129 -770 181 -684 201 -606C 335 -516 437 -776 89 -835Z",[-0.269,0.39]],["M 572 -722L 404 -771L 404 -525C 404 -387 400 -225 323 -99L 331 -89C 528 -200 544 -386 544 -522L 544 -707C 559 -709 569 -714 572 -722Z",[0.095,0.758]],["M 924 -721L 791 -857C 718 -815 571 -752 460 -717L 462 -705C 593 -704 752 -713 851 -725C 885 -711 910 -711 924 -721Z",[0.614,0.098]],["M 847 -607L 776 -513L 474 -513L 474 -485L 949 -485C 963 -485 974 -490 977 -501C 929 -544 847 -607 847 -607Z",[0.774,0.081]],["M 803 -108L 803 -513L 661 -513L 661 -79L 687 -79C 760 -79 803 -102 803 -108Z",[0.007,0.647]]],"bbox":{"top":-857,"bottom":94,"left":14,"right":980},"hadv":1000}],"text":"近","hadv":1000,"breakAfter":true},{"chars":[{"char":"期","components":[["M 155 -207C 126 -92 71 20 16 89L 27 97C 124 53 214 -17 281 -122C 304 -120 318 -128 323 -140Z",[0.379,0.477]],["M 20 -241L 28 -213L 562 -213C 576 -213 586 -218 588 -229C 558 -267 499 -327 499 -327L 448 -241Z",[0.887,0.054]],["M 34 -685L 42 -657L 549 -657C 562 -657 572 -662 574 -673C 548 -708 497 -762 497 -762L 453 -685Z",[0.778,0.03]],["M 102 -842L 102 -223L 234 -223L 234 -802C 257 -806 264 -815 266 -827Z",[0.004,0.783]],["M 167 -401L 167 -373L 389 -373L 389 -401Z",[0.806,0.004]],["M 168 -548L 168 -520L 385 -520L 385 -548Z",[0.74,0.007]],["M 317 -197L 309 -192C 340 -148 370 -82 374 -21C 487 68 606 -151 317 -197Z",[-0.238,0.337]],["M 329 -841L 329 -222L 463 -222L 463 -800C 488 -804 494 -813 496 -826Z",[0.006,0.778]],["M 562 -771L 562 -451C 562 -256 547 -67 410 82L 419 90C 674 -45 692 -260 692 -452L 692 -771L 712 -771L 562 -823L 562 -781Z",[0.1,0.811]],["M 638 -552L 638 -524L 884 -524L 884 -552Z",[-0.89,0.015]],["M 638 -325L 638 -297L 870 -297L 870 -325Z",[0.822,0.016]],["M 640 -771L 640 -743L 872 -743L 872 -771Z",[0.562,0.038]],["M 799 -771L 799 -75C 799 -62 795 -55 779 -55C 760 -55 671 -60 671 -60L 671 -47C 718 -38 736 -24 751 -3C 764 16 769 49 772 93C 915 80 935 31 935 -60L 935 -721C 955 -726 968 -734 975 -743L 850 -840L 789 -771Z",[0.038,0.83]]],"bbox":{"top":-842,"bottom":97,"left":16,"right":975},"hadv":1000}],"text":"期","hadv":1000,"breakAfter":true},{"chars":[{"char":"开","components":[["M 435 -429L 435 -754L 281 -754L 281 -428C 281 -224 249 -52 28 86L 34 93C 402 -15 435 -225 435 -429Z",[0.156,0.744]],["M 856 -524L 788 -417L 33 -417L 41 -389L 948 -389C 962 -389 973 -394 976 -405C 934 -451 856 -524 856 -524Z",[0.896,0.043]],["M 813 -845L 746 -756L 75 -756L 83 -728L 907 -728C 921 -728 932 -733 935 -744C 890 -785 813 -845 813 -845Z",[0.835,0.04]],["M 726 46L 726 -752L 571 -752L 571 87L 600 87C 680 87 726 55 726 46Z",[0.001,0.797]]],"bbox":{"top":-845,"bottom":93,"left":28,"right":976},"hadv":1000}],"text":"开","hadv":1000,"breakAfter":true},{"chars":[{"char":"发","components":[["M 576 -824L 377 -852C 359 -561 288 -209 24 26L 33 34C 383 -141 490 -463 537 -796C 562 -798 573 -808 576 -824Z",[0.304,0.751]],["M 354 -776L 173 -822C 162 -768 120 -626 93 -563L 137 -601C 113 -594 83 -576 67 -561L 199 -483L 249 -543L 242 -543C 263 -600 303 -726 318 -777L 306 -754C 337 -751 350 -763 354 -776Z",[0.192,0.469]],["M 675 -428L 689 -428C 611 -188 408 -9 108 84L 113 95C 496 45 722 -119 841 -368C 868 -370 878 -374 886 -386L 758 -505Z",[0.573,0.534]],["M 844 -669L 769 -571L 182 -571L 190 -543L 951 -543C 965 -543 977 -548 980 -559C 929 -603 844 -669 844 -669Z",[0.844,0.049]],["M 772 -428L 370 -428L 362 -400L 772 -400Z",[0.851,0.006]],["M 388 -413L 375 -410C 409 -220 510 -18 845 93C 854 10 899 -31 977 -45L 978 -58C 596 -124 429 -253 388 -413Z",[-0.599,0.371]],["M 609 -824L 601 -819C 631 -769 663 -700 672 -634C 797 -536 925 -774 609 -824Z",[-0.078,0.269]]],"bbox":{"top":-852,"bottom":95,"left":24,"right":980},"hadv":1000}],"text":"发","hadv":1000,"breakAfter":true},{"chars":[{"char":"计","components":[["M 268 -576L 27 -576L 36 -548L 268 -548Z",[0.741,0.001]],["M 121 -844L 114 -838C 157 -793 209 -723 232 -658C 369 -583 458 -840 121 -844Z",[-0.26,0.288]],["M 275 -553L 171 -553L 171 -151C 171 -127 163 -116 116 -87L 218 60C 247 40 279 -16 252 -102L 186 -48L 309 -101L 309 -532Z",[0.043,0.753]],["M 137 -91L 228 35C 344 -64 429 -156 471 -205L 468 -214C 332 -160 196 -110 137 -91Z",[0.527,0.32]],["M 173 -576L 171 -576L 171 -496L 309 -496L 309 -535L 299 -525C 330 -527 342 -536 349 -544L 236 -638Z",[0.042,0.097]],["M 856 -581L 782 -481L 368 -481L 376 -453L 959 -453C 974 -453 985 -458 988 -469C 939 -514 856 -581 856 -581Z",[0.821,0.072]],["M 767 -831L 582 -849L 582 91L 610 91C 666 91 730 55 730 40L 730 -803C 759 -807 765 -817 767 -831Z",[0.005,0.83]]],"bbox":{"top":-849,"bottom":91,"left":27,"right":988},"hadv":1000}],"text":"计","hadv":1000,"breakAfter":true},{"chars":[{"char":"划","components":[["M 387 -544C 317 -254 201 -76 15 52L 22 66C 264 -33 409 -188 512 -466C 538 -465 548 -471 553 -484Z",[0.444,0.666]],["M 21 -539L 31 -513L 552 -572C 566 -574 576 -581 578 -592C 529 -627 451 -676 451 -676L 391 -581Z",[0.826,0.132]],["M 128 -854C 129 -517 158 -204 368 20C 410 67 506 120 564 71C 585 54 580 14 542 -58L 570 -238L 560 -240C 538 -196 507 -140 489 -113C 478 -96 469 -96 456 -112C 286 -269 263 -549 268 -808C 294 -812 303 -824 304 -837Z",[-0.272,0.726]],["M 306 -812L 299 -806C 332 -777 368 -725 379 -678C 492 -615 572 -826 306 -812Z",[-0.053,0.235]],["M 592 -772L 592 -149L 616 -149C 667 -149 724 -175 724 -185L 724 -728C 751 -732 759 -743 761 -757Z",[0.02,0.763]],["M 789 -842L 789 -78C 789 -67 784 -61 768 -61C 744 -61 633 -68 633 -68L 633 -55C 688 -45 710 -29 727 -7C 745 15 750 48 754 95C 911 81 933 29 933 -68L 933 -797C 958 -801 968 -810 970 -825Z",[0.042,0.819]]],"bbox":{"top":-854,"bottom":120,"left":15,"right":970},"hadv":1000}],"text":"划","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>最近总有喘不过气的感觉，夜晚盖着被子躺好仔细思考一下，感觉肯定是自己博客拖了两年还没写好的原因。翻个身，想了想，要是写完了，以后就在也不用更新了，于是奋起，决定终于把它搞完。</p>\n<p>现在主要缺少三个功能：</p>\n<ul>\n<li>评论</li>\n<li>快速翻页</li>\n<li>搜索</li>\n</ul>\n<p>其中搜索的后端已经写好了，就缺个前端设计，这个一部分和快速翻页的设计有关，因为搜索的翻页也需要设计。</p>\n<p>快速翻页我的想法是，点击一下现在的页码，可以让侧边栏的内容变成页数列表，而且如果可以的话，现在显示时间的部分变成显示时间区间。这个涉及一部分的后端修改，包括数出来所有的帖子数量，和统计每个区间的时间区间。这个可能造成一定的性能损失？再说了，如果实在太慢可以留一个cache，反正这个cache的一致性非常好维护。</p>\n<p>评论决定砍掉引用原文内容，加一个回复邮件通知。邮件回复就算了，还要处理SMTP。</p>\n<p>预计这些内容可以在接下来两个月里写完，欢迎大家期待我咕咕咕，如果真的还有人在看的话。</p>\n","plain":"最近总有喘不过气的感觉，夜晚盖着被子躺好仔细思考一下，感觉肯定是自己博客拖了两年还没写好的原因。翻个身，想了想，要是写完了，以后就在也不用更新了，于是奋起，决定终于把它搞完。\n现在主要缺少三个功能：\n- 评论\n- 快速翻页\n- 搜索\n其中搜索的后端已经写好了，就缺个前端设计，这个一部分和快速翻页的设计有关，因为搜索的翻页也需要设计。\n快速翻页我的想法是，点击一下现在的页码，可以让侧边栏的内容变成页数列表，而且如果可以的话，现在显示时间的部分变成显示时间区间。这个涉及一部分的后端修改，包括数出来所有的帖子数量，和统计每个区间的时间区间。这个可能造成一定的性能损失？再说了，如果实在太慢可以留一个cache，反正这个cache的一致性非常好维护。\n评论决定砍掉引用原文内容，加一个回复邮件通知。邮件回复就算了，还要处理SMTP。\n预计这些内容可以在接下来两个月里写完，欢迎大家期待我咕咕咕，如果真的还有人在看的话。\n"},{"metadata":{"id":"finished-narcissu","lang":"zh-CN","title":"读完了 Narcissu","tags":["吃书"],"publish_time":"2018-06-21T11:34:21.327Z","update_time":"2018-06-21T11:38:39.122Z","title_outline":{"groups":[{"chars":[{"char":"读","components":[["M 215 -584L 22 -584L 31 -556L 215 -556Z",[-0.781,0.006]],["M 241 -559L 141 -559L 141 -138C 141 -115 133 -104 82 -74L 183 72C 212 51 244 -4 216 -89L 151 -35L 274 -88L 274 -539Z",[0.044,0.767]],["M 98 -844L 90 -839C 125 -794 165 -728 180 -666C 304 -585 408 -819 98 -844Z",[-0.239,0.306]],["M 110 -75L 187 55C 276 -34 344 -122 375 -165L 372 -173C 265 -130 156 -90 110 -75Z",[0.442,0.321]],["M 143 -584L 141 -584L 141 -504L 274 -504L 274 -542L 265 -533C 298 -535 311 -544 317 -552L 205 -645Z",[0.076,0.017]],["M 784 -493L 596 -518C 598 -202 509 -11 244 87L 248 97C 593 20 706 -143 746 -474C 774 -475 781 -482 784 -493Z",[0.35,0.655]],["M 854 -304L 786 -215L 302 -215L 310 -187L 950 -187C 965 -187 976 -192 978 -203C 932 -244 854 -304 854 -304Z",[0.879,0.054]],["M 887 -559L 320 -559L 328 -531L 887 -531Z",[0.819,0.007]],["M 350 -363L 343 -356C 378 -331 416 -282 427 -237C 537 -181 605 -389 350 -363Z",[-0.301,0.239]],["M 803 -799L 737 -713L 361 -713L 369 -685L 895 -685C 909 -685 920 -690 923 -701C 878 -741 803 -799 803 -799Z",[0.751,0.078]],["M 391 -498L 384 -491C 420 -467 458 -420 471 -377C 581 -324 644 -533 391 -498Z",[-0.192,0.148]],["M 710 -842L 544 -856L 544 -542L 678 -542L 678 -817C 702 -821 708 -830 710 -842Z",[0.037,0.553]],["M 676 -155L 668 -148C 731 -90 808 -0 844 78C 979 147 1047 -111 676 -155Z",[-0.419,0.375]],["M 815 -559L 827 -559C 823 -512 812 -430 801 -378L 810 -372C 859 -406 921 -463 957 -504C 978 -505 988 -508 996 -517L 881 -625Z",[-0.048,0.291]]],"bbox":{"top":-856,"bottom":147,"left":22,"right":1047},"hadv":1000}],"text":"读","hadv":1000,"breakAfter":true},{"chars":[{"char":"完","components":[["M 445 -344L 289 -344C 284 -178 270 -34 23 83L 30 95C 395 20 430 -138 445 -344Z",[0.373,0.567]],["M 171 -743L 160 -743C 161 -700 116 -659 85 -643C 43 -624 14 -587 28 -537C 44 -484 110 -466 148 -491C 202 -525 226 -617 171 -743Z",[0.178,0.341]],["M 827 -437L 758 -350L 64 -350L 72 -322L 925 -322C 939 -322 950 -327 953 -338C 906 -378 827 -437 827 -437Z",[0.901,0.038]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 658 -596L 591 -512L 219 -512L 227 -484L 753 -484C 767 -484 778 -489 781 -500C 734 -540 658 -596 658 -596Z",[0.764,0.073]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 675 -345L 531 -345L 531 -48C 531 45 555 69 669 69L 763 69C 931 69 978 41 978 -16C 978 -43 970 -60 933 -75L 930 -207L 921 -207C 896 -144 879 -99 866 -81C 858 -70 852 -67 839 -66C 826 -66 803 -65 781 -65L 704 -65C 680 -65 675 -70 675 -84L 675 -309C 675 -318 675 -334 675 -345Z",[-0.31,0.237]],["M 780 -680L 791 -680C 788 -639 779 -569 769 -524L 776 -518C 829 -543 897 -588 937 -622C 958 -623 968 -626 976 -635L 852 -752Z",[0.117,0.149]]],"bbox":{"top":-871,"bottom":95,"left":14,"right":978},"hadv":1000}],"text":"完","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691}],"text":"Narcissu","hadv":4596,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>读的是小说，读完了正好看到 Steam 上在卖游戏，于是连带着把 <em>雨的边缘</em> 一起买了。</p>\n<p>也许这么说挺奇怪的，但我觉得是很温柔的一个故事。温柔的濑津美在她最后的旅途当中收获了来自大半个世界的温暖，挺幸运的……吗？我是这么想的就是了，这是这部作品给我最大的感受。至于常年的孤单，被迫习得的冷漠之类的，则显得全然没有意义了，那些都很无力。</p>\n<p>从某个角度上而言，我有点羡慕她呢，有种她什么都有了的错觉。但是小说终于是小说，小说之外的事情有些是放不下来的罢。</p>\n<p>阿东在故事结尾大概还很迷茫吧，说着“有必须要传下去的话”，我听起来像是借口之类的。要是我估计就牵着濑津美的手一起走向大海了呢，真亏得他能丢下这么可爱的女孩子（笑）。总感觉这比较算是彻底体现了我的软弱？但是说到底，“代替死去的他人而活着”这件事情我是嗤之以鼻的，总有种自己不配的感觉。至于活着的他人，说一点不尊重的话是，虽然我不知道我现在自认为赋予我人生意义的人是否是我的真心所热爱着的，我现在是断然不希望有别人为了我而活的，那对他们真是太可悲了（笑）。</p>\n<p>最开始在 Bangumi 上发现的这部作品，于是看了。Bangumi 上有人给了个七分，评价只有一句话，说“反正咱不懂自杀者”。稍稍有点生气，不知道为什么，但是没多久也就消了。</p>\n<p>通读了以上全文一遍，总有强说愁的感觉。就这样吧。</p>\n","plain":"读的是小说，读完了正好看到 Steam 上在卖游戏，于是连带着把 雨的边缘 一起买了。\n也许这么说挺奇怪的，但我觉得是很温柔的一个故事。温柔的濑津美在她最后的旅途当中收获了来自大半个世界的温暖，挺幸运的……吗？我是这么想的就是了，这是这部作品给我最大的感受。至于常年的孤单，被迫习得的冷漠之类的，则显得全然没有意义了，那些都很无力。\n从某个角度上而言，我有点羡慕她呢，有种她什么都有了的错觉。但是小说终于是小说，小说之外的事情有些是放不下来的罢。\n阿东在故事结尾大概还很迷茫吧，说着“有必须要传下去的话”，我听起来像是借口之类的。要是我估计就牵着濑津美的手一起走向大海了呢，真亏得他能丢下这么可爱的女孩子（笑）。总感觉这比较算是彻底体现了我的软弱？但是说到底，“代替死去的他人而活着”这件事情我是嗤之以鼻的，总有种自己不配的感觉。至于活着的他人，说一点不尊重的话是，虽然我不知道我现在自认为赋予我人生意义的人是否是我的真心所热爱着的，我现在是断然不希望有别人为了我而活的，那对他们真是太可悲了（笑）。\n最开始在 Bangumi 上发现的这部作品，于是看了。Bangumi 上有人给了个七分，评价只有一句话，说“反正咱不懂自杀者”。稍稍有点生气，不知道为什么，但是没多久也就消了。\n通读了以上全文一遍，总有强说愁的感觉。就这样吧。\n"},{"metadata":{"id":"nginx-listen-with-server_name","lang":"zh-CN","title":"Nginx Listen IP","tags":["技术"],"publish_time":"2018-05-17T16:05:53.163Z","update_time":"2018-05-17T16:10:42.187Z","title_outline":{"groups":[{"chars":[{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"g","components":[["M 258 259C 466 259 586 154 586 45C 586 -43 526 -108 361 -108L 215 -108C 162 -108 140 -125 140 -157C 140 -186 150 -206 172 -237L 154 -246L 154 -237C 76 -187 52 -139 52 -91C 52 -42 82 -7 137 10L 137 14C 169 25 196 25 258 25L 369 25C 436 25 458 63 458 95C 458 170 392 215 257 215C 169 215 116 176 116 102C 116 59 133 36 163 -0L 161 -5C 67 25 23 74 23 128C 23 199 73 259 258 259Z",[-0.296,0.029]],["M 278 -197C 435 -197 510 -276 510 -378C 510 -425 495 -466 468 -496L 463 -501C 427 -539 366 -563 279 -563C 121 -563 46 -485 46 -378C 46 -276 121 -197 278 -197ZM 278 -229C 220 -229 191 -286 191 -378C 191 -475 223 -531 279 -531C 333 -531 366 -476 366 -378C 366 -286 335 -229 278 -229Z",[-0.284,0.0]],["M 428 -491L 596 -474L 596 -552L 578 -563L 434 -506L 428 -506Z",[-0.751,0.177]]],"bbox":{"top":-563,"bottom":259,"left":23,"right":596},"hadv":612},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"x","components":[["M 11 -0L 215 -0L 215 -31L 134 -41L 100 -41L 11 -31Z",[0.808,0.001]],["M 16 -516L 129 -504L 212 -504L 323 -516L 323 -546L 16 -546Z",[-0.783,0.006]],["M 390 -0L 579 -0L 369 -329L 230 -546L 46 -546L 245 -229Z",[-0.433,0.627]],["M 57 -0L 117 -0L 212 -153L 308 -306L 314 -306L 292 -326Z",[0.5,0.734]],["M 295 -0L 606 -0L 606 -31L 487 -41L 442 -41L 295 -31Z",[0.875,0.002]],["M 330 -239L 553 -546L 494 -546L 404 -404L 314 -261L 307 -261Z",[0.481,0.677]],["M 395 -516L 479 -505L 512 -505L 587 -516L 587 -546L 395 -546Z",[-0.745,0.023]]],"bbox":{"top":-546,"bottom":0,"left":11,"right":606},"hadv":617}],"text":"Nginx","hadv":3109,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"L","components":[["M 41 -0L 218 -0L 219 -50L 202 -50L 42 -34Z",[0.751,0.04]],["M 41 -713L 202 -698L 240 -698L 403 -713L 403 -747L 41 -747Z",[-0.878,0.008]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -346L 303 -411C 303 -514 303 -632 306 -747L 130 -747C 133 -631 133 -513 133 -395L 133 -324C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 619 -0L 617 -224L 562 -224L 503 -2L 588 -39L 219 -39Z",[0.547,0.208]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":619},"hadv":651},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697}],"text":"Listen","hadv":3210,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690}],"text":"IP","hadv":1127,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>当你调不出来为什么一个 server_name 匹配不上的时候，请关注是否有另一个 server 块直接听了某个 IP，而不是 0.0.0.0</p>\n<p>因为 Nginx 对 server 块的匹配是先找符合的 listen，随后再看符合的 listen 下面的 server_name。其中找 listen 的时候是先找对应 IP 的，没有再找 0.0.0.0。如果有完全相同的 IP，就不会看监听到 0.0.0.0 上的 server 块了。</p>\n<p>举例: 有以下配置</p>\n<pre><code>eth0 -&gt; 10.1.1.1\neth1 -&gt; 10.1.2.1\n</code></pre>\n<pre><code>server {\n  listen 10.1.1.1:80;\n  server_name a.example.com;\n}\n\nserver {\n  listen 0.0.0.0:80;\n  server_name b.example.com;\n}\n</code></pre>\n<p>一个 Host: b.example.com，如果从 eth1 走，会走到第二个块里。如果从 eth0 走，会走到第一个块里。</p>\n<p>我算是服了</p>\n","plain":"当你调不出来为什么一个 server_name 匹配不上的时候，请关注是否有另一个 server 块直接听了某个 IP，而不是 0.0.0.0\n因为 Nginx 对 server 块的匹配是先找符合的 listen，随后再看符合的 listen 下面的 server_name。其中找 listen 的时候是先找对应 IP 的，没有再找 0.0.0.0。如果有完全相同的 IP，就不会看监听到 0.0.0.0 上的 server 块了。\n举例: 有以下配置\neth0 -> 10.1.1.1\neth1 -> 10.1.2.1\n\nserver {\n  listen 10.1.1.1:80;\n  server_name a.example.com;\n}\n\nserver {\n  listen 0.0.0.0:80;\n  server_name b.example.com;\n}\n\n一个 Host: b.example.com，如果从 eth1 走，会走到第二个块里。如果从 eth0 走，会走到第一个块里。\n我算是服了\n"},{"metadata":{"id":"in-the-making-of-tuoj-buildfs","lang":"zh-CN","title":"捏造 tuoj-buildfs","tags":["技术"],"publish_time":"2018-04-26T18:20:30.284Z","update_time":"2018-04-26T18:20:49.205Z","title_outline":{"groups":[{"chars":[{"char":"捏","components":[["M 15 -384L 64 -218C 77 -221 89 -233 94 -246C 242 -334 345 -406 406 -454L 404 -463C 246 -427 78 -394 15 -384Z",[0.617,0.261]],["M 137 -856L 137 -67C 137 -56 133 -52 119 -52C 100 -52 22 -57 22 -57L 22 -44C 65 -35 82 -21 94 -1C 107 20 111 52 113 95C 253 83 272 34 272 -58L 272 -811C 297 -815 307 -825 309 -840Z",[0.029,0.841]],["M 26 -615L 34 -587L 393 -587C 407 -587 417 -592 420 -603C 386 -643 322 -706 322 -706L 267 -615Z",[0.854,0.077]],["M 321 26L 329 54L 959 54C 974 54 985 49 988 38C 940 -7 858 -74 858 -74L 786 26Z",[0.869,0.058]],["M 371 -217L 379 -189L 934 -189C 948 -189 959 -194 962 -205C 916 -249 836 -314 836 -314L 766 -217Z",[0.851,0.066]],["M 410 -779L 410 -341L 430 -341C 488 -341 547 -372 547 -385L 547 -751L 844 -751L 844 -779L 553 -779L 410 -835Z",[0.142,0.439]],["M 486 -611L 486 -583L 856 -583L 856 -611Z",[-0.738,0.025]],["M 486 -451L 486 -423L 856 -423L 856 -451Z",[-0.827,0.018]],["M 585 -389L 585 38L 725 38L 725 -352C 746 -355 751 -363 753 -375Z",[0.012,0.636]],["M 774 -779L 774 -371L 797 -371C 845 -371 912 -400 913 -409L 913 -727C 935 -732 948 -741 955 -750L 826 -848L 763 -779Z",[0.044,0.672]]],"bbox":{"top":-856,"bottom":95,"left":15,"right":988},"hadv":1000}],"text":"捏","hadv":1000,"breakAfter":true},{"chars":[{"char":"造","components":[["M 219 -137C 196 -137 94 -83 25 -56L 116 88C 124 84 130 77 128 66C 156 10 192 -50 209 -82C 220 -102 232 -104 247 -83C 327 25 409 74 623 74C 704 74 825 74 884 74C 891 17 923 -38 979 -50L 979 -62C 871 -54 780 -53 671 -53C 451 -53 333 -69 260 -124C 246 -133 239 -137 219 -137Z",[-0.832,0.062]],["M 278 -107L 278 -406C 307 -411 322 -419 331 -429L 194 -538L 129 -452L 25 -452L 31 -424L 145 -424L 145 -98Z",[-0.031,0.582]],["M 76 -824L 68 -819C 111 -755 147 -667 154 -585C 288 -473 421 -743 76 -824Z",[-0.226,0.412]],["M 850 -599L 780 -507L 301 -507L 309 -479L 949 -479C 963 -479 975 -484 977 -495C 930 -537 850 -599 850 -599Z",[0.838,0.059]],["M 563 -781L 387 -835C 377 -728 350 -616 317 -540L 329 -533C 410 -582 475 -659 523 -760C 546 -760 559 -768 563 -781Z",[0.274,0.514]],["M 532 -123L 532 -357L 805 -357L 805 -385L 538 -385L 392 -440L 392 -81L 412 -81C 469 -81 532 -111 532 -123Z",[0.191,0.248]],["M 828 -771L 760 -681L 449 -681L 449 -653L 924 -653C 939 -653 950 -658 952 -669C 906 -710 828 -771 828 -771Z",[0.727,0.085]],["M 810 -187L 473 -187L 473 -159L 810 -159Z",[0.881,0.016]],["M 739 -842L 558 -856L 558 -490L 703 -490L 703 -813C 731 -818 737 -828 739 -842Z",[0.026,0.606]],["M 729 -385L 739 -385L 739 -90L 764 -90C 811 -90 880 -117 881 -126L 881 -334C 902 -339 915 -348 921 -356L 792 -453Z",[0.029,0.542]]],"bbox":{"top":-856,"bottom":88,"left":25,"right":979},"hadv":1000}],"text":"造","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"j","components":[["M 15 271C 68 271 133 255 188 199C 245 142 262 78 262 -68L 262 -392L 265 -551L 247 -562L 23 -502L 23 -478L 97 -470C 100 -423 101 -378 101 -313L 101 -111C 101 17 109 133 92 191C 85 216 75 228 62 242L 62 250L 80 250L 80 244L 53 187C 34 146 10 127 -24 127C -67 127 -95 151 -104 198C -92 244 -54 271 15 271Z",[0.12,0.706]],["M 177 -655C 224 -655 263 -689 263 -738C 263 -784 224 -819 177 -819C 129 -819 90 -784 90 -738C 90 -689 129 -655 177 -655Z",[0.006,0.007]]],"bbox":{"top":-819,"bottom":271,"left":-104,"right":265},"hadv":347}],"text":"tuoj","hadv":2081,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":true},{"chars":[{"char":"b","components":[["M 36 -0L 240 15L 266 -76L 266 -469L 263 -479L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -749L 104 -238C 104 -181 103 -95 102 -36L 36 -31Z",[0.003,0.793]],["M 420 17C 557 17 654 -111 654 -275C 654 -463 557 -563 432 -563C 355 -563 286 -528 230 -452L 207 -452L 221 -423C 280 -488 314 -494 352 -494C 427 -494 482 -435 482 -279C 482 -96 419 -54 349 -54C 313 -54 282 -67 249 -104L 228 -91L 239 -91C 286 -19 348 17 420 17Z",[0.002,0.47]]],"bbox":{"top":-826,"bottom":17,"left":31,"right":654},"hadv":689},{"char":"u","components":[["M 253 17C 338 17 404 -33 453 -103L 511 -103L 472 -160C 437 -108 389 -69 335 -69C 286 -69 255 -94 255 -174L 255 -393L 261 -547L 248 -557L 26 -527L 26 -500L 129 -480L 95 -505L 92 -189C 90 -37 153 17 253 17Z",[-0.14,0.565]],["M 443 14L 664 1L 664 -29L 600 -35L 600 -393L 604 -547L 593 -557L 374 -522L 374 -500L 441 -487L 437 -110L 437 -107Z",[-0.032,0.696]]],"bbox":{"top":-557,"bottom":17,"left":26,"right":664},"hadv":691},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"f","components":[["M 101 -0L 270 -0C 267 -79 266 -159 266 -238L 266 -521C 259 -639 264 -719 299 -775C 312 -793 337 -811 368 -816L 368 -824L 318 -824L 318 -815L 342 -770C 368 -714 398 -695 437 -695C 483 -695 509 -723 510 -763C 497 -818 441 -837 381 -837C 318 -837 258 -818 203 -768C 155 -726 117 -661 105 -535L 104 -522L 160 -552L 26 -537L 26 -505L 104 -505L 104 -238C 104 -159 103 -79 101 -0Z",[0.15,0.675]],["M 33 -0L 360 -0L 360 -31L 252 -41L 145 -41L 33 -31Z",[0.877,0.0]],["M 186 -505L 394 -505L 394 -546L 186 -546Z",[0.703,0.009]]],"bbox":{"top":-837,"bottom":0,"left":26,"right":510},"hadv":409},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"buildfs","hadv":3698,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>希望能够给算协的系统弄一个稳定可复现的构建过程，于是：</p>\n<h3>发现 Ubuntu 的仓库没有过去版本的包</h3>\n<p>这个其实是可以理解的，因为如果加上过去的包，Index 就要无限大了。不过为什么连过去某一天的 Snapshot 都没有啊！连 ArchLinux 这种仓库都可以有，Debian 也可以有，估计就是 Ubuntu 摸了。</p>\n<p>本来的配置文件设计希望能够写死版本：</p>\n<div class=\"highlighted highlighted-yaml\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-yaml\"><span style=\"color:#268bd2;\">install</span><span style=\"color:#839496;\">:\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#268bd2;\">g++</span><span style=\"color:#839496;\">: </span><span style=\"color:#2aa198;\">4:5.3.1-1ubuntu1\n</span></code></pre>\n</div>\n<p>现在只能不写版本了，在构建结尾输出包的版本号，并且保证 Judger 和 Client(Dist) 的这些包版本相同。</p>\n<h3>发现 Docker-in-Docker Image 的上游是 Alpine</h3>\n<p>Alpine 的包真多，基本上全都有了，Randisk 用的挺爽的，准备过两天往 RaspberryPi 上来一个。</p>\n<p>坑爹的地方在于，我在搞 Ubuntu 系统，外面是 Alpine，目录结构都不太一样。后面搞 Grub 的时候基本上是在 CI 上 Trial &amp; Error，制造了大量垃圾提交</p>\n<p>用到了上次测试 CI 时候的技能：</p>\n<pre><code>git commit -m \"No-op: trigger CI update\" --allow-empty\n</code></pre>\n<p>可以提交一个空 Commit 干扰其他 Collaborator 的工作。</p>\n<h3>发现 ISOLinux 根本没有错误输出</h3>\n<p>说不出话了，我到现在都不知道 ISOLinux 为什么不工作。最开始的时候提示没有 ldlinux.c32，发现新的 ldlinux.c32 在 /usr/lib/syslinux/modules 里，但是没有 isolinux，isolinux 在另一个包 isolinux 里，路径在 /usr/lib/ISOLINUX/isolinux.bin。</p>\n<p>改了之后还是不行，发现最新版改配置格式了，格式错了也没有输出。改了下格式，有 menu 了，虽然还是启动不了，放到 CI 上跑了一下，又炸了。</p>\n<p>原因是在 Alpine 下面，所有东西都在 /usr/lib/syslinux/modules/bios/*，但是改了我在本地就没办法调试了。</p>\n<h3>发现 grub-mkstandalone 基本不能用在 Bios 上</h3>\n<p>Bios 模式希望把 Ramdisk 在 Real mode 就加载上去，导致内存超小，连一个 linux 模块都放不到 Ramdisk 里，所以 grub-mkstandalone 基本没办法 i386-pc。因为很懒最后就只做了 UEFI 的版本。</p>\n<h3>发现了一个 Go 的 Feature</h3>\n<p>因为特殊原因 git.thusaac.org 走了个代理。 gitlab-runner 虽然在同一台机器上但是跑了一个绕行，走了香港 VPS 的双倍延时+双倍流量。加 extra_hosts 都没用，发现是 Go 如果不用 cgo 的话，是会忽略 /etc/hosts 的。Go 说这是 GNU 的默认行为，只能作罢，加了个 GODEBUG 用 cgo 处理网络问题。</p>\n<h3>发现我选择了一个错误的时间</h3>\n<p>刚写完脚本，就看到了：</p>\n<ul>\n<li>Atom 1.27</li>\n<li>Ubuntu 18.04 LTS</li>\n<li>Node 10</li>\n</ul>\n<h2>Status</h2>\n<p>现在还在组织当中。选手机的镜像里面由于是从 Ubuntu Base 开始搞得，装完桌面环境，没有计算器，没有终端模拟器，没有 LibreOffice，没有 gnome-mines，还要装很多东西。</p>\n<p>以及 Judger 的封装还没做好。但是上传到 Docker Hub 已经调试完了。docker 命令行居然不能在参数里接受有特殊字符的密码，服气。</p>\n","plain":"希望能够给算协的系统弄一个稳定可复现的构建过程，于是：\n\n发现 Ubuntu 的仓库没有过去版本的包\n这个其实是可以理解的，因为如果加上过去的包，Index 就要无限大了。不过为什么连过去某一天的 Snapshot 都没有啊！连 ArchLinux 这种仓库都可以有，Debian 也可以有，估计就是 Ubuntu 摸了。\n本来的配置文件设计希望能够写死版本：\ninstall:\n  g++: 4:5.3.1-1ubuntu1\n\n现在只能不写版本了，在构建结尾输出包的版本号，并且保证 Judger 和 Client(Dist) 的这些包版本相同。\n\n发现 Docker-in-Docker Image 的上游是 Alpine\nAlpine 的包真多，基本上全都有了，Randisk 用的挺爽的，准备过两天往 RaspberryPi 上来一个。\n坑爹的地方在于，我在搞 Ubuntu 系统，外面是 Alpine，目录结构都不太一样。后面搞 Grub 的时候基本上是在 CI 上 Trial & Error，制造了大量垃圾提交\n用到了上次测试 CI 时候的技能：\ngit commit -m \"No-op: trigger CI update\" --allow-empty\n\n可以提交一个空 Commit 干扰其他 Collaborator 的工作。\n\n发现 ISOLinux 根本没有错误输出\n说不出话了，我到现在都不知道 ISOLinux 为什么不工作。最开始的时候提示没有 ldlinux.c32，发现新的 ldlinux.c32 在 /usr/lib/syslinux/modules 里，但是没有 isolinux，isolinux 在另一个包 isolinux 里，路径在 /usr/lib/ISOLINUX/isolinux.bin。\n改了之后还是不行，发现最新版改配置格式了，格式错了也没有输出。改了下格式，有 menu 了，虽然还是启动不了，放到 CI 上跑了一下，又炸了。\n原因是在 Alpine 下面，所有东西都在 /usr/lib/syslinux/modules/bios/*，但是改了我在本地就没办法调试了。\n\n发现 grub-mkstandalone 基本不能用在 Bios 上\nBios 模式希望把 Ramdisk 在 Real mode 就加载上去，导致内存超小，连一个 linux 模块都放不到 Ramdisk 里，所以 grub-mkstandalone 基本没办法 i386-pc。因为很懒最后就只做了 UEFI 的版本。\n\n发现了一个 Go 的 Feature\n因为特殊原因 git.thusaac.org 走了个代理。 gitlab-runner 虽然在同一台机器上但是跑了一个绕行，走了香港 VPS 的双倍延时+双倍流量。加 extra_hosts 都没用，发现是 Go 如果不用 cgo 的话，是会忽略 /etc/hosts 的。Go 说这是 GNU 的默认行为，只能作罢，加了个 GODEBUG 用 cgo 处理网络问题。\n\n发现我选择了一个错误的时间\n刚写完脚本，就看到了：\n- Atom 1.27\n- Ubuntu 18.04 LTS\n- Node 10\n\nStatus\n现在还在组织当中。选手机的镜像里面由于是从 Ubuntu Base 开始搞得，装完桌面环境，没有计算器，没有终端模拟器，没有 LibreOffice，没有 gnome-mines，还要装很多东西。\n以及 Judger 的封装还没做好。但是上传到 Docker Hub 已经调试完了。docker 命令行居然不能在参数里接受有特殊字符的密码，服气。\n"},{"metadata":{"id":"sayonara-stranger","lang":"zh-CN","title":"用一片空白，纪念我所不会认识的人","tags":[],"publish_time":"2018-03-24T20:07:45.260Z","update_time":"2018-03-24T20:07:45.260Z","title_outline":{"groups":[{"chars":[{"char":"用","components":[["M 136 -773L 136 -461C 136 -273 129 -77 25 76L 34 83C 266 -58 278 -276 278 -462L 278 -773L 299 -773L 136 -828L 136 -783Z",[0.078,0.811]],["M 217 -540L 217 -512L 792 -512L 792 -540Z",[-0.834,0.008]],["M 217 -773L 217 -745L 792 -745L 792 -773Z",[-0.626,0.018]],["M 217 -297L 217 -269L 792 -269L 792 -297Z",[-0.951,0.003]],["M 427 -763L 427 80L 453 80C 527 80 569 51 569 42L 569 -763Z",[0.004,0.824]],["M 740 -773L 740 -90C 740 -78 736 -70 720 -70C 700 -70 607 -76 607 -76L 607 -63C 657 -54 675 -39 690 -18C 704 2 709 35 712 80C 864 67 885 17 885 -76L 885 -719C 908 -724 921 -734 929 -743L 795 -849L 729 -773Z",[0.041,0.817]]],"bbox":{"top":-849,"bottom":83,"left":25,"right":929},"hadv":1000}],"text":"用","hadv":1000,"breakAfter":true},{"chars":[{"char":"一","components":[["M 816 -550L 723 -418L 29 -418L 38 -386L 948 -386C 965 -386 977 -391 980 -402C 920 -459 816 -550 816 -550Z",[0.883,0.054]]],"bbox":{"top":-550,"bottom":-386,"left":29,"right":980},"hadv":1000}],"text":"一","hadv":1000,"breakAfter":true},{"chars":[{"char":"片","components":[["M 186 -833L 186 -470C 186 -266 160 -61 23 87L 30 94C 269 -19 326 -245 328 -470L 328 -788C 355 -792 363 -802 365 -816Z",[0.112,0.808]],["M 215 -359L 215 -331L 647 -331L 647 -359Z",[-0.916,0.006]],["M 232 -563L 232 -535L 943 -535C 958 -535 970 -540 972 -551C 923 -597 838 -667 838 -667L 763 -563Z",[0.921,0.041]],["M 511 -854L 511 -554L 662 -554L 662 -810C 693 -815 700 -825 702 -840Z",[-0.003,0.451]],["M 569 -359L 569 91L 594 91C 644 91 718 65 719 57L 719 -307C 740 -312 752 -321 759 -329L 625 -431L 559 -359Z",[0.013,0.677]]],"bbox":{"top":-854,"bottom":94,"left":23,"right":972},"hadv":1000}],"text":"片","hadv":1000,"breakAfter":true},{"chars":[{"char":"空","components":[["M 152 -774L 140 -773C 148 -717 114 -666 83 -646C 45 -629 18 -596 31 -552C 46 -506 97 -490 137 -513C 193 -543 222 -641 152 -774Z",[0.18,0.434]],["M 835 -90L 765 7L 38 7L 46 35L 931 35C 946 35 957 30 960 19C 914 -25 835 -90 835 -90Z",[0.92,0.038]],["M 458 -534C 492 -532 508 -541 514 -555L 325 -649C 286 -562 180 -424 64 -349L 69 -342C 230 -377 374 -456 458 -534Z",[0.509,0.376]],["M 750 -424L 683 -330L 143 -330L 151 -302L 841 -302C 855 -302 866 -307 869 -318C 825 -360 750 -424 750 -424Z",[0.882,0.052]],["M 893 -702L 155 -702L 155 -674L 893 -674Z",[0.736,0.019]],["M 389 -854L 385 -849C 420 -821 444 -768 443 -717C 590 -615 728 -894 389 -854Z",[-0.248,0.128]],["M 577 -330L 427 -330L 427 24L 577 24Z",[0.004,0.568]],["M 550 -619L 543 -611C 642 -555 760 -454 822 -363C 984 -309 1024 -619 550 -619Z",[-0.45,0.3]],["M 776 -702L 788 -702C 784 -659 773 -588 762 -542L 768 -536C 825 -561 899 -606 942 -642C 964 -643 974 -646 982 -656L 852 -778Z",[-0.203,0.061]]],"bbox":{"top":-894,"bottom":35,"left":18,"right":1024},"hadv":1000}],"text":"空","hadv":1000,"breakAfter":true},{"chars":[{"char":"白","components":[["M 125 -639L 125 90L 150 90C 216 90 280 53 280 35L 280 -611L 800 -611L 800 -639L 291 -639L 125 -703Z",[0.137,0.505]],["M 192 -37L 192 -9L 806 -9L 806 -37Z",[-0.954,0.0]],["M 192 -341L 192 -313L 806 -313L 806 -341Z",[-0.907,0.005]],["M 404 -861C 399 -796 386 -698 373 -633L 401 -633C 466 -681 529 -747 574 -791C 597 -791 608 -799 612 -812Z",[0.332,0.247]],["M 722 -639L 722 84L 747 84C 806 84 877 45 878 33L 878 -582C 903 -587 916 -598 924 -607L 783 -720L 710 -639Z",[0.017,0.758]]],"bbox":{"top":-861,"bottom":90,"left":125,"right":924},"hadv":1000}],"text":"白","hadv":1000,"breakAfter":false},{"chars":[{"char":"，","components":[["M 163 54C 118 38 39 11 39 -64C 39 -113 78 -157 135 -157C 190 -157 237 -117 237 -41C 237 60 187 180 56 236L 39 203C 122 162 155 101 163 54Z",[0.017,0.495]]],"bbox":{"top":-157,"bottom":236,"left":39,"right":237},"hadv":1000}],"text":"，","hadv":1000,"breakAfter":true},{"chars":[{"char":"纪","components":[["M 19 -102L 82 70C 95 66 106 55 112 41C 274 -51 381 -125 447 -178L 445 -187C 275 -147 92 -112 19 -102Z",[0.611,0.25]],["M 384 -773L 206 -848C 187 -770 111 -626 58 -586C 46 -579 20 -573 20 -573L 85 -417C 116 -430 138 -478 143 -556L 75 -556L 75 -544C 168 -588 297 -691 359 -768L 325 -761C 359 -751 378 -759 384 -773Z",[0.397,0.566]],["M 494 -583L 325 -670C 287 -565 158 -381 74 -328C 61 -319 30 -313 30 -313L 94 -157C 126 -170 148 -216 154 -294L 87 -294L 88 -282C 216 -345 392 -485 465 -580L 432 -574C 467 -561 487 -570 494 -583Z",[0.514,0.586]],["M 37 -567L 88 -425C 213 -479 314 -534 365 -566L 364 -576C 230 -570 95 -566 37 -567Z",[0.637,0.126]],["M 62 -317L 110 -179C 258 -241 376 -304 438 -340L 437 -351C 282 -334 126 -320 62 -317Z",[0.639,0.17]],["M 828 -767L 420 -767L 429 -739L 828 -739Z",[-0.757,0.011]],["M 453 -517L 453 -51C 453 44 489 65 612 65L 733 65C 933 65 988 44 988 -14C 988 -38 977 -53 938 -68L 934 -198L 924 -198C 901 -136 881 -91 868 -73C 859 -62 850 -59 833 -58C 816 -56 782 -56 748 -56L 635 -56C 599 -56 590 -62 590 -81L 590 -463L 604 -463L 453 -519Z",[-0.304,0.331]],["M 846 -463L 543 -463L 543 -435L 846 -435Z",[0.736,0.045]],["M 755 -767L 767 -767L 767 -342L 790 -342C 835 -342 905 -365 906 -373L 906 -709C 933 -714 949 -726 957 -736L 820 -841Z",[0.045,0.649]]],"bbox":{"top":-848,"bottom":70,"left":19,"right":988},"hadv":1000}],"text":"纪","hadv":1000,"breakAfter":true},{"chars":[{"char":"念","components":[["M 527 -768C 602 -617 723 -506 890 -447C 900 -504 925 -570 985 -594L 985 -610C 807 -629 637 -690 540 -779C 578 -784 589 -791 593 -806L 388 -866C 338 -716 201 -538 28 -436L 32 -427C 263 -489 448 -644 527 -768Z",[-0.606,0.058]],["M 180 -251L 168 -250C 172 -192 133 -140 97 -121C 62 -104 37 -73 49 -32C 64 11 115 24 153 2C 207 -28 240 -121 180 -251Z",[0.229,0.423]],["M 681 -463L 196 -463L 205 -435L 681 -435Z",[0.864,0.006]],["M 440 -289L 263 -302L 263 -54C 263 39 295 60 420 60L 542 60C 743 60 798 40 798 -21C 798 -47 788 -63 747 -77L 744 -200L 734 -200C 709 -138 690 -99 676 -81C 667 -70 660 -67 643 -66C 626 -65 592 -65 560 -65L 446 -65C 413 -65 408 -69 408 -84L 408 -263C 429 -266 438 -275 440 -289Z",[-0.472,0.169]],["M 385 -637L 379 -632C 409 -600 432 -546 432 -495C 556 -401 687 -637 385 -637Z",[-0.18,0.184]],["M 419 -326L 411 -321C 445 -277 476 -211 481 -151C 595 -63 710 -285 419 -326Z",[-0.218,0.31]],["M 616 -463L 628 -463C 604 -417 558 -340 520 -282C 576 -253 624 -248 663 -255C 694 -300 735 -366 757 -405C 781 -408 795 -415 803 -423L 679 -530Z",[0.31,0.407]],["M 738 -242L 730 -236C 780 -183 822 -100 829 -24C 958 75 1074 -188 738 -242Z",[-0.268,0.368]]],"bbox":{"top":-866,"bottom":75,"left":28,"right":1074},"hadv":1000}],"text":"念","hadv":1000,"breakAfter":true},{"chars":[{"char":"我","components":[["M 25 -325L 86 -162C 98 -165 110 -174 116 -187C 325 -269 462 -332 549 -380L 548 -391C 331 -360 112 -332 25 -325Z",[0.708,0.19]],["M 397 -849C 317 -791 156 -709 25 -663L 27 -653C 184 -661 363 -687 474 -718C 510 -706 534 -708 547 -719Z",[0.643,0.171]],["M 26 -530L 34 -502L 951 -502C 965 -502 976 -507 979 -518C 929 -558 848 -616 848 -616L 776 -530Z",[0.93,0.034]],["M 243 -735L 243 -80C 243 -68 238 -60 222 -60C 197 -60 83 -67 83 -67L 83 -55C 142 -45 164 -29 181 -8C 198 13 205 48 207 94C 361 83 385 18 385 -75L 385 -735Z",[0.048,0.794]],["M 781 -482C 723 -297 589 -81 374 46L 381 57C 653 -31 815 -215 908 -391C 932 -388 942 -395 948 -406Z",[0.52,0.598]],["M 527 -836C 528 -479 551 -170 777 25C 825 66 917 110 969 57C 988 37 983 1 944 -65L 968 -238L 959 -241C 938 -196 907 -140 889 -113C 879 -97 871 -97 856 -110C 683 -245 665 -508 670 -790C 696 -794 704 -806 705 -819Z",[-0.279,0.72]],["M 722 -801L 714 -796C 747 -755 775 -691 776 -632C 891 -540 1014 -765 722 -801Z",[0.027,0.287]]],"bbox":{"top":-849,"bottom":110,"left":25,"right":1014},"hadv":1000}],"text":"我","hadv":1000,"breakAfter":true},{"chars":[{"char":"所","components":[["M 250 -726L 87 -777L 87 -456C 87 -278 86 -73 18 87L 28 97C 215 -51 222 -277 222 -451L 222 -712C 237 -714 247 -718 250 -726Z",[0.065,0.822]],["M 416 -328L 132 -328L 132 -300L 416 -300Z",[0.863,0.002]],["M 416 -589L 132 -589L 132 -561L 416 -561Z",[-0.838,0.01]],["M 504 -740L 365 -860C 315 -816 213 -747 135 -706L 138 -695C 241 -704 361 -722 435 -739C 468 -728 491 -729 504 -740Z",[0.509,0.138]],["M 315 -589L 325 -589L 325 -235L 348 -235C 391 -235 458 -258 459 -265L 459 -539C 480 -543 493 -553 499 -561L 375 -655Z",[0.02,0.642]],["M 678 -734L 510 -787L 510 -490C 510 -296 493 -85 347 83L 356 94C 628 -50 650 -295 650 -485L 650 -720C 665 -722 675 -726 678 -734Z",[0.125,0.79]],["M 976 -734L 831 -864C 772 -818 654 -746 563 -703L 565 -693C 682 -700 819 -717 903 -734C 937 -722 962 -723 976 -734Z",[0.492,0.157]],["M 866 -601L 801 -511L 588 -511L 588 -483L 955 -483C 969 -483 980 -488 983 -499C 940 -540 866 -601 866 -601Z",[0.766,0.094]],["M 877 45L 877 -511L 732 -511L 732 83L 759 83C 834 83 877 53 877 45Z",[-0.003,0.844]]],"bbox":{"top":-864,"bottom":97,"left":18,"right":983},"hadv":1000}],"text":"所","hadv":1000,"breakAfter":true},{"chars":[{"char":"不","components":[["M 471 -735C 415 -556 231 -341 25 -206L 30 -198C 315 -305 563 -509 677 -735Z",[0.559,0.573]],["M 31 -740L 39 -712L 941 -712C 956 -712 968 -717 971 -728C 915 -775 822 -845 822 -845L 739 -740Z",[0.89,0.034]],["M 423 -550L 423 95L 451 95C 504 95 569 72 571 64L 571 -528C 591 -531 599 -538 602 -547L 461 -599Z",[0.007,0.774]],["M 596 -498L 589 -491C 679 -426 785 -320 838 -226C 994 -158 1053 -459 596 -498Z",[-0.445,0.36]]],"bbox":{"top":-845,"bottom":95,"left":25,"right":1053},"hadv":1000}],"text":"不","hadv":1000,"breakAfter":true},{"chars":[{"char":"会","components":[["M 542 -776C 600 -613 731 -502 875 -426C 884 -478 922 -539 981 -556L 982 -571C 836 -607 649 -668 558 -788C 592 -791 606 -798 610 -812L 411 -862C 371 -720 190 -509 21 -397L 27 -387C 227 -463 443 -620 542 -776Z",[-0.569,0.044]],["M 808 -420L 732 -324L 75 -324L 83 -296L 917 -296C 932 -296 943 -301 946 -312C 894 -356 808 -420 808 -420Z",[0.893,0.044]],["M 581 -221L 410 -316C 374 -244 254 -114 172 -81C 158 -75 130 -70 130 -70L 189 91C 222 79 248 32 254 -52L 189 -52L 189 -41C 312 -74 483 -157 556 -218L 521 -215C 555 -201 575 -208 581 -221Z",[0.564,0.456]],["M 162 -65L 194 70C 462 25 672 -19 794 -51L 794 -65C 529 -61 267 -62 162 -65Z",[0.817,0.073]],["M 630 -571L 564 -490L 253 -490L 261 -462L 721 -462C 736 -462 747 -467 749 -478C 704 -517 630 -571 630 -571Z",[0.767,0.07]],["M 602 -213L 593 -207C 661 -131 742 -23 781 74C 927 162 1014 -125 602 -213Z",[-0.395,0.433]]],"bbox":{"top":-862,"bottom":162,"left":21,"right":1014},"hadv":1000}],"text":"会","hadv":1000,"breakAfter":true},{"chars":[{"char":"认","components":[["M 252 -580L 25 -580L 34 -552L 252 -552Z",[-0.937,0.005]],["M 257 -556L 150 -556L 150 -156C 150 -132 142 -121 91 -90L 196 62C 226 40 260 -17 231 -106L 163 -50L 292 -105L 292 -535Z",[0.047,0.746]],["M 99 -842L 92 -836C 134 -789 185 -718 208 -652C 342 -575 433 -828 99 -842Z",[-0.323,0.318]],["M 119 -84L 206 42C 305 -77 377 -189 410 -245L 406 -253C 289 -180 169 -109 119 -84Z",[0.451,0.432]],["M 152 -580L 150 -580L 150 -500L 292 -500L 292 -538L 282 -528C 314 -530 327 -540 333 -547L 217 -643Z",[0.008,0.003]],["M 682 -813C 707 -817 717 -826 719 -841L 534 -858C 534 -498 553 -182 271 83L 281 96C 687 -118 676 -451 682 -813Z",[0.188,0.782]],["M 673 -722L 657 -720C 665 -378 695 -61 866 91C 879 15 919 -35 982 -50L 983 -62C 760 -184 689 -405 673 -722Z",[-0.26,0.701]]],"bbox":{"top":-858,"bottom":96,"left":25,"right":983},"hadv":1000}],"text":"认","hadv":1000,"breakAfter":true},{"chars":[{"char":"识","components":[["M 242 -584L 29 -584L 38 -556L 242 -556Z",[-0.806,0.008]],["M 88 -843L 80 -838C 116 -791 157 -724 172 -661C 297 -579 401 -815 88 -843Z",[-0.189,0.319]],["M 253 -559L 149 -559L 149 -155C 149 -131 141 -120 88 -89L 193 61C 222 40 255 -17 226 -105L 159 -49L 287 -104L 287 -538Z",[0.048,0.752]],["M 111 -89L 193 38C 300 -78 379 -187 417 -242L 413 -251C 290 -180 163 -113 111 -89Z",[0.487,0.419]],["M 151 -584L 149 -584L 149 -504L 287 -504L 287 -541L 277 -532C 311 -534 324 -544 330 -551L 215 -647Z",[0.026,0.029]],["M 674 -216L 493 -295C 447 -146 363 -2 284 85L 293 93C 424 34 541 -57 631 -199C 654 -196 668 -204 674 -216Z",[0.421,0.521]],["M 386 -816L 386 -267L 412 -267C 486 -267 530 -291 530 -300L 530 -731L 741 -731L 741 -284L 768 -284C 846 -284 893 -310 893 -317L 893 -720C 917 -724 927 -732 934 -741L 807 -839L 737 -759L 541 -759ZM 851 -368L 500 -368L 500 -340L 851 -340Z",[0.141,0.02]],["M 680 -272L 671 -266C 745 -180 812 -59 834 53C 989 170 1107 -155 680 -272Z",[-0.319,0.457]]],"bbox":{"top":-843,"bottom":170,"left":29,"right":1107},"hadv":1000}],"text":"识","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"人","components":[["M 523 -795C 549 -799 558 -808 560 -823L 366 -841C 365 -517 378 -196 28 81L 38 94C 515 -125 514 -468 523 -795Z",[0.248,0.745]],["M 523 -795L 507 -794C 518 -363 559 -61 845 86C 861 7 906 -48 979 -63L 980 -75C 641 -184 544 -402 523 -795Z",[-0.363,0.634]]],"bbox":{"top":-841,"bottom":94,"left":28,"right":980},"hadv":1000}],"text":"人","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"","plain":""},{"metadata":{"id":"frontend-pre-quit-chklist","lang":"zh-CN","title":"前端踩坑 Checklist","tags":["技术"],"publish_time":"2018-03-17T17:48:48.834Z","update_time":"2018-03-17T17:52:38.960Z","title_outline":{"groups":[{"chars":[{"char":"前","components":[["M 25 -653L 33 -625L 949 -625C 964 -625 975 -630 978 -641C 926 -686 838 -753 838 -753L 761 -653Z",[0.917,0.039]],["M 95 -519L 95 93L 116 93C 175 93 230 61 230 47L 230 -491L 405 -491L 405 -519L 234 -519L 95 -575Z",[0.047,0.723]],["M 156 -371L 156 -343L 416 -343L 416 -371Z",[-0.902,0.003]],["M 156 -208L 156 -180L 416 -180L 416 -208Z",[-0.89,0.001]],["M 214 -847L 207 -842C 245 -798 282 -732 292 -668C 428 -576 546 -834 214 -847Z",[-0.209,0.269]],["M 332 -519L 332 -60C 332 -49 329 -43 316 -43C 298 -43 246 -47 246 -47L 246 -34C 281 -27 294 -12 303 7C 313 26 316 56 317 98C 449 86 467 39 467 -47L 467 -469C 488 -473 501 -482 507 -490L 382 -587L 322 -519Z",[0.037,0.77]],["M 614 -856C 600 -793 573 -699 548 -637L 557 -637C 631 -680 721 -744 772 -788C 796 -788 807 -796 810 -809Z",[0.525,0.243]],["M 551 -547L 551 -104L 574 -104C 624 -104 681 -125 681 -134L 681 -504C 709 -508 716 -519 718 -532Z",[0.023,0.675]],["M 756 -581L 756 -64C 756 -52 751 -48 736 -48C 714 -48 602 -54 602 -54L 602 -42C 657 -32 678 -17 695 2C 712 23 718 53 721 95C 872 83 893 34 893 -57L 893 -539C 916 -542 926 -551 928 -566Z",[0.067,0.723]]],"bbox":{"top":-856,"bottom":98,"left":25,"right":978},"hadv":1000}],"text":"前","hadv":1000,"breakAfter":true},{"chars":[{"char":"端","components":[["M 18 -140L 87 20C 99 16 110 4 114 -10C 242 -95 326 -167 384 -221L 382 -229C 245 -187 91 -151 18 -140Z",[0.56,0.275]],["M 307 -709L 248 -621L 26 -621L 34 -593L 384 -593C 398 -593 409 -598 412 -609C 374 -649 307 -709 307 -709Z",[0.701,0.086]],["M 72 -558L 58 -553C 90 -459 87 -332 78 -261C 135 -146 316 -338 72 -558Z",[-0.094,0.635]],["M 112 -841L 104 -837C 123 -790 141 -727 139 -667C 246 -564 393 -769 112 -841Z",[-0.102,0.369]],["M 407 -525L 246 -568C 239 -438 222 -250 205 -117L 218 -117C 279 -241 336 -401 368 -503C 392 -503 403 -512 407 -525Z",[0.175,0.719]],["M 872 -558L 814 -482L 372 -482L 380 -454L 951 -454C 965 -454 976 -459 979 -470C 939 -506 872 -558 872 -558Z",[0.822,0.059]],["M 503 -723L 410 -723L 410 -576L 431 -613C 414 -607 391 -586 378 -570L 504 -498L 541 -560L 533 -560L 533 -705Z",[0.035,0.377]],["M 513 49L 513 -321L 880 -321L 880 -349L 520 -349L 389 -401L 389 89L 407 89C 459 89 513 61 513 49Z",[0.186,0.365]],["M 570 -775L 410 -790L 410 -670C 511 -670 529 -670 533 -670L 533 -751C 559 -755 568 -763 570 -775Z",[-0.421,0.027]],["M 831 -588L 480 -588L 480 -560L 831 -560Z",[0.748,0.05]],["M 741 -482L 564 -482C 563 -445 556 -377 550 -333L 583 -333C 634 -371 701 -438 741 -482Z",[0.346,0.303]],["M 643 14L 643 -349L 553 -349L 553 36L 569 36C 615 36 643 19 643 14Z",[0.002,0.771]],["M 759 -840L 603 -853L 603 -572L 726 -572L 726 -814C 750 -818 757 -827 759 -840Z",[0.09,0.56]],["M 772 -12L 772 -349L 682 -349L 682 9L 698 9C 744 9 772 -8 772 -12Z",[0.007,0.749]],["M 801 -349L 811 -349L 811 -68C 811 -58 809 -52 798 -52C 787 -52 761 -54 761 -54L 761 -41C 785 -34 794 -22 799 -3C 805 16 806 47 806 88C 923 77 938 32 938 -54L 938 -301C 958 -306 970 -314 976 -322L 856 -411Z",[0.036,0.671]],["M 958 -776L 796 -790L 796 -535L 817 -535C 867 -535 921 -552 921 -560L 921 -748C 949 -753 956 -763 958 -776Z",[0.086,0.486]]],"bbox":{"top":-853,"bottom":89,"left":18,"right":979},"hadv":1000}],"text":"端","hadv":1000,"breakAfter":true},{"chars":[{"char":"踩","components":[["M 22 -74L 82 82C 95 79 106 68 111 55C 263 -21 363 -86 434 -137L 432 -147C 277 -110 103 -82 22 -74Z",[0.638,0.231]],["M 178 -380L 56 -391L 56 -33L 158 -55L 158 -363C 173 -366 177 -372 178 -380Z",[0.01,0.701]],["M 62 -840L 62 -470L 83 -470C 143 -470 179 -495 179 -503L 179 -779L 193 -779Z",[-0.01,0.657]],["M 351 -544L 124 -544L 124 -513L 351 -513Z",[-0.787,0.02]],["M 351 -779L 124 -779L 124 -751L 351 -751Z",[-0.522,0.029]],["M 299 -531L 184 -531L 184 -66L 299 -96Z",[0.008,0.744]],["M 351 -406L 300 -324L 247 -324L 247 -296L 413 -296C 427 -296 437 -301 440 -312C 409 -349 351 -406 351 -406Z",[-0.625,0.02]],["M 280 -779L 290 -779L 290 -484L 310 -484C 348 -484 407 -505 408 -512L 408 -734C 426 -738 439 -746 444 -753L 333 -836Z",[0.02,0.624]],["M 733 -340L 733 -356L 581 -356C 547 -217 477 -71 373 26L 382 37C 555 -50 676 -177 733 -340Z",[0.427,0.594]],["M 869 -453L 809 -367L 409 -367L 417 -339L 951 -339C 965 -339 975 -344 978 -355C 938 -394 869 -453 869 -453Z",[0.854,0.054]],["M 960 -720L 819 -861C 736 -813 569 -746 439 -712L 440 -701C 591 -696 771 -706 885 -723C 920 -709 946 -710 960 -720Z",[0.591,0.132]],["M 452 -664L 442 -660C 460 -614 477 -550 475 -492C 568 -400 697 -581 452 -664Z",[-0.179,0.362]],["M 600 -686L 591 -682C 611 -637 631 -575 631 -518C 733 -422 867 -618 600 -686Z",[-0.1,0.341]],["M 786 -452L 621 -467L 621 96L 647 96C 696 96 758 70 758 60L 758 -430C 779 -433 784 -441 786 -452Z",[0.012,0.727]],["M 755 -358L 745 -354C 767 -188 803 -56 875 34C 894 -32 930 -72 979 -84L 982 -94C 892 -146 800 -240 755 -358Z",[-0.254,0.468]],["M 981 -629L 815 -702C 808 -653 785 -549 766 -482L 773 -478C 836 -518 907 -579 942 -614C 964 -610 977 -619 981 -629Z",[0.279,0.385]]],"bbox":{"top":-861,"bottom":96,"left":22,"right":982},"hadv":1000}],"text":"踩","hadv":1000,"breakAfter":true},{"chars":[{"char":"坑","components":[["M 16 -217L 89 -55C 102 -59 113 -70 118 -83C 266 -172 364 -240 423 -289L 422 -298C 255 -261 84 -228 16 -217Z",[0.599,0.242]],["M 324 -663L 271 -568L 21 -568L 29 -540L 387 -540C 401 -540 411 -545 414 -556C 384 -597 324 -663 324 -663Z",[0.813,0.087]],["M 310 -823L 134 -838L 134 -170L 273 -214L 273 -794C 301 -799 308 -809 310 -823Z",[0.011,0.781]],["M 448 -510L 448 -337C 448 -190 417 -34 218 88L 224 97C 549 -3 582 -194 582 -338L 582 -500L 602 -500L 448 -553Z",[0.211,0.69]],["M 851 -760L 776 -655L 358 -655L 366 -627L 954 -627C 969 -627 980 -632 983 -643C 935 -690 851 -760 851 -760Z",[0.749,0.089]],["M 525 -853L 518 -848C 549 -807 574 -745 576 -687C 699 -588 834 -825 525 -853Z",[-0.199,0.244]],["M 751 -500L 529 -500L 529 -472L 751 -472Z",[-0.661,0.083]],["M 687 -500L 699 -500L 699 -43C 699 37 711 64 796 64L 843 64C 940 64 984 36 984 -14C 984 -39 978 -53 950 -68L 947 -208L 936 -208C 920 -152 903 -93 893 -76C 887 -66 882 -64 876 -64C 871 -63 866 -63 860 -63L 843 -63C 833 -63 830 -68 830 -80L 830 -461C 850 -464 860 -470 866 -478L 750 -572Z",[-0.113,0.631]]],"bbox":{"top":-853,"bottom":97,"left":16,"right":984},"hadv":1000}],"text":"坑","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"C","components":[["M 441 20C 535 20 607 -3 668 -39L 664 -219L 605 -219L 544 -8L 625 -36L 625 -73C 571 -34 528 -19 474 -19C 330 -19 221 -126 221 -373C 221 -619 330 -729 470 -729C 526 -729 569 -714 619 -680L 619 -713L 536 -741L 598 -528L 657 -528L 661 -710C 597 -746 536 -767 442 -767C 222 -767 43 -636 43 -366C 43 -102 218 20 441 20Z",[0.001,0.207]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":668},"hadv":708},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673},{"char":"l","components":[["M 101 -0L 270 -0C 267 -74 266 -161 266 -238L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -161 103 -74 101 -0Z",[-0.009,0.794]],["M 33 -0L 337 -0L 337 -31L 221 -41L 142 -41L 33 -31Z",[-0.869,0.001]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":337},"hadv":366},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512},{"char":"t","components":[["M 250 17C 327 17 377 -12 407 -66L 391 -82C 364 -60 347 -50 322 -50C 282 -50 257 -73 257 -127L 257 -529L 258 -708L 155 -708L 100 -536L 118 -548L 14 -537L 14 -505L 95 -505L 95 -249C 95 -208 94 -179 94 -139C 94 -29 148 17 250 17Z",[-0.056,0.716]],["M 177 -505L 380 -505L 380 -546L 177 -546Z",[0.705,0.008]]],"bbox":{"top":-708,"bottom":17,"left":14,"right":407},"hadv":406}],"text":"Checklist","hadv":4888,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<blockquote>\n<p>持续更新 as long as 我还在写前端，因为前端的坑是踩不完的</p>\n</blockquote>\n<h2>Vue</h2>\n<ul>\n<li>Component 只有一个 Root，附带 transition 不生成 node，所以这样会爆炸:</li>\n</ul>\n<div class=\"highlighted highlighted-html\"><pre style=\"background-color:#002b36;\">\n<code class=\"language-html\"><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">transition</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">key</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">1</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#839496;\">  </span><span style=\"color:#586e75;\">&lt;</span><span style=\"color:#268bd2;\">div </span><span style=\"color:#b58900;\">key</span><span style=\"color:#657b83;\">=</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">2</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#586e75;\">&gt;&lt;/</span><span style=\"color:#268bd2;\">div</span><span style=\"color:#586e75;\">&gt;\n</span><span style=\"color:#586e75;\">&lt;/</span><span style=\"color:#268bd2;\">transition</span><span style=\"color:#586e75;\">&gt;\n</span></code></pre>\n</div>\n<h2>Networking</h2>\n<ul>\n<li>fetch API 默认不带 credentials，就算是 same-origin</li>\n</ul>\n","plain":"持续更新 as long as 我还在写前端，因为前端的坑是踩不完的\n\n\nVue\n- Component 只有一个 Root，附带 transition 不生成 node，所以这样会爆炸:\n<transition>\n  <div key=\"1\"></div>\n  <div key=\"2\"></div>\n</transition>\n\n\nNetworking\n- fetch API 默认不带 credentials，就算是 same-origin\n"},{"metadata":{"id":"incident-2018-3-13","lang":"zh-CN","title":"大家都是文明人","tags":["扯淡"],"publish_time":"2018-03-13T13:00:34.340Z","update_time":"2018-03-13T13:33:20.463Z","title_outline":{"groups":[{"chars":[{"char":"大","components":[["M 595 -832L 396 -850C 395 -475 418 -170 24 83L 32 96C 561 -98 549 -422 558 -803C 582 -807 592 -816 595 -832Z",[0.247,0.728]],["M 824 -654L 741 -549L 33 -549L 40 -521L 945 -521C 958 -521 970 -526 973 -536C 918 -586 824 -654 824 -654Z",[0.877,0.045]],["M 549 -542L 535 -540C 555 -331 619 -52 849 96C 861 12 904 -36 978 -51L 979 -63C 699 -167 578 -351 549 -542Z",[-0.415,0.541]]],"bbox":{"top":-850,"bottom":96,"left":24,"right":979},"hadv":1000}],"text":"大","hadv":1000,"breakAfter":true},{"chars":[{"char":"家","components":[["M 172 -776L 160 -776C 161 -727 120 -680 87 -663C 52 -646 27 -614 40 -572C 55 -528 109 -516 145 -538C 195 -570 222 -656 172 -776Z",[0.216,0.4]],["M 580 -196L 491 -331C 404 -195 222 -57 39 9L 45 22C 252 -13 458 -100 580 -196Z",[0.655,0.4]],["M 510 -333L 423 -461C 352 -354 205 -224 69 -156L 74 -145C 235 -184 408 -260 510 -333Z",[0.605,0.407]],["M 570 -555L 570 -571L 387 -571C 320 -489 203 -385 74 -322L 80 -311C 279 -360 468 -444 570 -555Z",[0.656,0.392]],["M 846 -715L 156 -715L 156 -687L 846 -687Z",[0.741,0.015]],["M 714 -660L 644 -571L 184 -571L 192 -543L 811 -543C 825 -543 837 -548 839 -559C 792 -600 714 -660 714 -660Z",[0.852,0.054]],["M 401 -484L 394 -477C 491 -340 492 -111 460 -50C 455 -41 444 -39 430 -39C 406 -39 343 -43 301 -47L 301 -37C 343 -25 373 -10 386 6C 402 26 410 55 411 95C 490 95 548 83 576 47C 649 -48 632 -343 401 -484Z",[0.016,0.603]],["M 390 -850L 384 -845C 417 -818 445 -769 449 -721C 580 -639 692 -887 390 -850Z",[-0.002,0.153]],["M 912 -424L 770 -543C 712 -486 595 -394 499 -337L 506 -326C 635 -346 778 -383 873 -417C 896 -411 906 -415 912 -424Z",[0.592,0.268]],["M 618 -400L 607 -395C 644 -178 724 -63 856 27C 875 -40 915 -83 970 -95L 971 -106C 824 -153 674 -233 618 -400Z",[-0.417,0.403]],["M 784 -715L 795 -715C 796 -681 795 -622 792 -584L 799 -578C 843 -597 899 -632 932 -659C 953 -660 963 -663 971 -672L 852 -784Z",[0.164,0.253]]],"bbox":{"top":-887,"bottom":95,"left":27,"right":971},"hadv":1000}],"text":"家","hadv":1000,"breakAfter":true},{"chars":[{"char":"都","components":[["M 449 -819C 381 -619 227 -366 10 -211L 19 -200C 289 -325 457 -545 555 -733C 580 -729 591 -736 597 -746Z",[0.514,0.66]],["M 16 -505L 24 -477L 570 -477C 584 -477 594 -482 597 -493C 560 -530 496 -584 496 -584L 439 -505Z",[0.899,0.045]],["M 41 -686L 49 -658L 429 -658C 443 -658 453 -663 456 -674C 422 -710 362 -765 362 -765L 310 -686Z",[0.7,0.036]],["M 120 -375L 120 89L 144 89C 210 89 250 61 250 52L 250 -375L 260 -375L 120 -427Z",[-0.004,0.733]],["M 176 -846L 176 -490L 311 -490L 311 -804C 339 -808 346 -818 348 -832Z",[0.007,0.601]],["M 191 -375L 191 -347L 413 -347L 413 -375Z",[0.793,0.006]],["M 191 -206L 191 -178L 413 -178L 413 -206Z",[0.851,0.003]],["M 191 -38L 191 -10L 413 -10L 413 -38Z",[0.874,0.001]],["M 366 -375L 366 79L 389 79C 434 79 500 54 501 47L 501 -327C 520 -331 532 -340 538 -347L 416 -440L 356 -375Z",[0.01,0.713]],["M 583 -762L 583 93L 608 93C 679 93 720 61 720 51L 720 -762L 734 -762L 583 -831Z",[-0.002,0.852]],["M 652 -762L 652 -734L 855 -734L 855 -762Z",[0.491,0.045]],["M 798 -762C 794 -682 774 -534 758 -456C 809 -392 828 -311 828 -240C 828 -212 821 -197 808 -189C 802 -185 797 -184 788 -184C 776 -184 745 -184 727 -184L 727 -172C 750 -166 765 -155 773 -141C 782 -123 787 -65 787 -26C 915 -27 959 -95 959 -198C 959 -284 907 -394 784 -458C 843 -526 906 -630 944 -695C 968 -696 981 -700 989 -710L 855 -830L 786 -762Z",[-0.002,0.791]]],"bbox":{"top":-846,"bottom":93,"left":10,"right":989},"hadv":1000}],"text":"都","hadv":1000,"breakAfter":true},{"chars":[{"char":"是","components":[["M 205 -314C 199 -187 158 -27 13 84L 19 93C 239 16 326 -118 360 -256C 386 -256 396 -266 399 -281Z",[0.363,0.569]],["M 27 -385L 35 -357L 946 -357C 961 -357 972 -362 975 -373C 928 -417 848 -483 848 -483L 777 -385Z",[0.967,0.034]],["M 188 -778L 188 -409L 210 -409C 273 -409 341 -442 341 -456L 341 -750L 726 -750L 726 -778L 349 -778L 188 -839Z",[0.231,0.244]],["M 262 -646L 262 -618L 732 -618L 732 -646Z",[-0.813,0.013]],["M 262 -512L 262 -484L 732 -484L 732 -512Z",[-0.786,0.018]],["M 293 -192L 285 -188C 332 25 429 78 628 78C 691 78 849 78 911 78C 911 24 931 -25 975 -36L 975 -47C 894 -45 706 -45 630 -45C 446 -45 354 -63 293 -192Z",[-0.759,0.089]],["M 435 -385L 435 -22L 589 13L 589 -385Z",[-0.009,0.587]],["M 501 -220L 501 -192L 859 -192C 874 -192 886 -197 889 -208C 837 -255 749 -325 749 -325L 672 -220Z",[0.681,0.092]],["M 663 -778L 663 -429L 690 -429C 739 -429 816 -454 817 -461L 817 -726C 838 -730 850 -740 856 -748L 719 -851L 653 -778Z",[0.037,0.572]]],"bbox":{"top":-851,"bottom":93,"left":13,"right":975},"hadv":1000}],"text":"是","hadv":1000,"breakAfter":true},{"chars":[{"char":"文","components":[["M 816 -615L 639 -615C 609 -306 439 -55 27 84L 31 94C 549 7 756 -256 816 -615Z",[0.493,0.591]],["M 821 -732L 740 -622L 37 -622L 45 -594L 935 -594C 950 -594 961 -599 964 -610C 912 -659 821 -732 821 -732Z",[0.852,0.046]],["M 259 -615L 246 -608C 316 -191 522 -8 825 96C 851 23 902 -23 975 -34L 978 -46C 651 -111 351 -252 259 -615Z",[-0.59,0.463]],["M 383 -852L 377 -847C 421 -800 461 -727 473 -658C 614 -562 733 -836 383 -852Z",[-0.273,0.296]]],"bbox":{"top":-852,"bottom":96,"left":27,"right":978},"hadv":1000}],"text":"文","hadv":1000,"breakAfter":true},{"chars":[{"char":"明","components":[["M 69 -756L 69 -94L 93 -94C 161 -94 202 -128 202 -138L 202 -756L 215 -756L 69 -810Z",[-0.001,0.806]],["M 138 -756L 138 -728L 346 -728L 346 -756Z",[0.376,0.031]],["M 138 -512L 138 -484L 346 -484L 346 -512Z",[0.723,0.004]],["M 138 -267L 138 -239L 346 -239L 346 -267Z",[0.846,0.002]],["M 507 -776L 507 -455C 507 -247 480 -63 286 85L 294 93C 613 -32 642 -251 642 -456L 642 -776L 662 -776L 507 -829L 507 -786Z",[0.134,0.785]],["M 296 -756L 296 -150L 318 -150C 367 -150 430 -183 431 -193L 431 -706C 451 -711 464 -719 471 -728L 348 -824L 286 -756Z",[0.012,0.785]],["M 565 -776L 565 -748L 849 -748L 849 -776Z",[-0.872,0.002]],["M 565 -550L 565 -522L 849 -522L 849 -550Z",[0.852,0.001]],["M 565 -322L 565 -294L 849 -294L 849 -322Z",[0.871,0.004]],["M 795 -776L 795 -78C 795 -63 790 -56 772 -56C 746 -56 618 -63 618 -63L 618 -50C 678 -39 703 -24 723 -3C 742 17 749 49 753 94C 911 80 932 29 932 -63L 932 -726C 953 -730 966 -739 973 -747L 846 -846L 785 -776Z",[0.048,0.814]]],"bbox":{"top":-846,"bottom":94,"left":69,"right":973},"hadv":1000}],"text":"明","hadv":1000,"breakAfter":true},{"chars":[{"char":"人","components":[["M 523 -795C 549 -799 558 -808 560 -823L 366 -841C 365 -517 378 -196 28 81L 38 94C 515 -125 514 -468 523 -795Z",[0.248,0.745]],["M 523 -795L 507 -794C 518 -363 559 -61 845 86C 861 7 906 -48 979 -63L 980 -75C 641 -184 544 -402 523 -795Z",[-0.363,0.634]]],"bbox":{"top":-841,"bottom":94,"left":28,"right":980},"hadv":1000}],"text":"人","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>文明网络环境，一共就那么多个IPv4，有话好好说。</p>\n<p>一言不合 DDoS 是几个意思啊？你以为我们都是吃素的啊？</p>\n<p>话就说这一次，大家好自为之。我以为我们是个小站，每日 PV 算下来也就几百，但是还是被打了，那就只能说明一件事：这个圈子里的残障人士比例比较高。竞争或者什么的，放在明面上，我们都是用实力说话的，我们不做承担不起的事情。</p>\n<p>如果你问心无愧，那我只能说，朋友，你就是这样的文明人，一辈子也就是这样的文明人了。</p>\n<p>至于我本身，我一直是喜欢夜晚的，也不惮在其中行走。再怎么说，蓝天太亮了，使得星星失去了光芒。而自在寒风中颤抖过一次之后，我们披上了大衣。</p>\n","plain":"文明网络环境，一共就那么多个IPv4，有话好好说。\n一言不合 DDoS 是几个意思啊？你以为我们都是吃素的啊？\n话就说这一次，大家好自为之。我以为我们是个小站，每日 PV 算下来也就几百，但是还是被打了，那就只能说明一件事：这个圈子里的残障人士比例比较高。竞争或者什么的，放在明面上，我们都是用实力说话的，我们不做承担不起的事情。\n如果你问心无愧，那我只能说，朋友，你就是这样的文明人，一辈子也就是这样的文明人了。\n至于我本身，我一直是喜欢夜晚的，也不惮在其中行走。再怎么说，蓝天太亮了，使得星星失去了光芒。而自在寒风中颤抖过一次之后，我们披上了大衣。\n"},{"metadata":{"id":"testing-kpti-performance-hit","lang":"zh-CN","title":"测试 KPTI 对 IO 的性能影响","tags":["技术"],"publish_time":"2018-01-06T14:17:32.945Z","update_time":"2018-01-20T07:59:28.847Z","title_outline":{"groups":[{"chars":[{"char":"测","components":[["M 27 -611L 19 -606C 47 -569 78 -512 86 -459C 199 -380 308 -593 27 -611Z",[-0.201,0.276]],["M 89 -215C 78 -215 46 -215 46 -215L 46 -197C 67 -195 83 -190 97 -180C 120 -164 124 -60 103 46C 112 86 140 98 164 98C 217 98 254 62 256 9C 259 -86 214 -120 211 -178C 210 -204 215 -240 220 -274C 228 -330 268 -546 292 -663L 276 -666C 137 -272 137 -272 118 -236C 108 -215 104 -215 89 -215Z",[0.086,0.788]],["M 87 -841L 80 -836C 108 -795 140 -734 149 -677C 268 -592 384 -816 87 -841Z",[-0.214,0.284]],["M 578 -647L 430 -678C 430 -278 442 -63 255 77L 268 91C 547 -22 533 -247 540 -624C 564 -624 575 -634 578 -647Z",[0.145,0.803]],["M 300 -818L 300 -206L 319 -206C 374 -206 408 -227 408 -234L 408 -744L 561 -744L 561 -232L 581 -232C 637 -232 674 -255 674 -261L 674 -734C 697 -738 708 -745 715 -754L 612 -835L 557 -772L 420 -772Z",[0.029,0.218]],["M 487 -219L 478 -214C 519 -152 565 -65 579 12C 698 102 801 -134 487 -219Z",[-0.291,0.43]],["M 832 -718L 704 -730L 704 -162L 722 -162C 757 -162 799 -181 799 -190L 799 -692C 822 -696 829 -705 832 -718Z",[0.028,0.772]],["M 977 -823L 826 -838L 826 -59C 826 -48 822 -43 808 -43C 790 -43 713 -49 713 -49L 713 -34C 753 -26 771 -14 783 6C 795 25 800 55 802 94C 925 82 940 35 940 -49L 940 -795C 965 -799 975 -808 977 -823Z",[0.024,0.871]]],"bbox":{"top":-841,"bottom":102,"left":19,"right":977},"hadv":1000}],"text":"测","hadv":1000,"breakAfter":true},{"chars":[{"char":"试","components":[["M 212 -588L 19 -588L 28 -560L 212 -560Z",[-0.727,0.009]],["M 86 -844L 78 -839C 116 -793 160 -725 178 -662C 304 -585 400 -821 86 -844Z",[-0.221,0.312]],["M 241 -562L 143 -562L 143 -152C 143 -129 135 -118 83 -88L 182 57C 211 37 243 -18 215 -103L 150 -49L 274 -101L 274 -543Z",[0.048,0.765]],["M 103 -88L 183 39C 283 -71 359 -175 394 -228L 390 -236C 273 -172 153 -110 103 -88Z",[0.469,0.403]],["M 145 -588L 143 -588L 143 -508L 274 -508L 274 -545L 265 -536C 299 -539 312 -548 319 -556L 207 -649Z",[0.039,0.08]],["M 307 -96L 378 46C 390 42 400 32 405 19C 534 -58 621 -117 676 -159L 674 -169C 522 -136 370 -106 307 -96Z",[0.605,0.241]],["M 871 -701L 807 -617L 318 -617L 326 -589L 961 -589C 975 -589 986 -594 989 -605C 945 -644 871 -701 871 -701Z",[0.789,0.061]],["M 573 -495L 521 -419L 327 -419L 335 -391L 641 -391C 654 -391 664 -396 667 -407C 633 -442 573 -495 573 -495Z",[0.844,0.073]],["M 558 -419L 425 -419L 425 -71L 558 -110Z",[0.024,0.588]],["M 801 -838L 627 -856C 627 -505 634 -199 791 19C 824 65 907 123 969 79C 991 63 985 18 954 -54L 979 -235L 969 -237C 950 -194 924 -141 908 -114C 898 -97 892 -96 882 -112C 762 -260 758 -533 765 -809C 792 -813 800 -825 801 -838Z",[-0.208,0.796]],["M 805 -823L 797 -819C 815 -786 830 -736 827 -689C 928 -596 1069 -785 805 -823Z",[0.006,0.316]]],"bbox":{"top":-856,"bottom":123,"left":19,"right":1069},"hadv":1000}],"text":"试","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"K","components":[["M 41 -0L 376 -0L 376 -34L 232 -50L 202 -50L 41 -34Z",[0.86,0.001]],["M 41 -713L 202 -698L 232 -698L 387 -713L 387 -747L 41 -747Z",[-0.509,0.016]],["M 130 -0L 299 -0C 296 -117 296 -230 296 -330L 296 -395C 296 -514 296 -632 299 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.781]],["M 210 -187L 680 -747L 625 -747L 256 -291L 230 -257L 208 -257Z",[0.603,0.717]],["M 556 -0L 741 -0L 466 -509L 359 -384Z",[-0.331,0.611]],["M 465 -0L 783 -0L 783 -34L 639 -50L 614 -50L 465 -34Z",[0.855,0.002]],["M 484 -713L 600 -697L 631 -698L 746 -713L 746 -747L 484 -747Z",[0.587,0.039]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":783},"hadv":786},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437}],"text":"KPTI","hadv":2627,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"对","components":[["M 318 -718L 331 -718C 302 -446 212 -149 21 38L 31 47C 323 -118 427 -397 470 -664C 495 -667 505 -671 512 -683L 388 -793Z",[0.303,0.757]],["M 410 -718L 45 -718L 54 -690L 410 -690Z",[0.656,0.016]],["M 97 -605L 85 -598C 201 -458 287 -242 318 -118C 375 39 531 -56 457 -219C 389 -363 266 -486 97 -605Z",[-0.364,0.646]],["M 880 -702L 819 -602L 457 -602L 465 -574L 959 -574C 973 -574 984 -579 986 -590C 950 -633 880 -702 880 -702Z",[0.71,0.109]],["M 471 -492L 463 -486C 508 -422 526 -333 532 -274C 628 -157 797 -401 471 -492Z",[-0.2,0.4]],["M 870 -833L 690 -850L 690 -83C 690 -71 684 -65 667 -65C 639 -65 505 -72 505 -72L 505 -60C 568 -48 593 -33 614 -10C 635 12 642 45 646 93C 811 78 834 25 834 -72L 834 -805C 858 -809 868 -818 870 -833Z",[0.042,0.813]]],"bbox":{"top":-850,"bottom":93,"left":21,"right":986},"hadv":1000}],"text":"对","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795}],"text":"IO","hadv":1232,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"性","components":[["M 87 -661C 94 -594 65 -519 40 -489C 14 -468 1 -437 18 -408C 38 -376 88 -378 111 -409C 143 -454 151 -544 102 -661Z",[0.149,0.608]],["M 150 -854L 150 95L 178 95C 231 95 289 68 289 57L 289 -808C 317 -812 324 -823 326 -837Z",[0.005,0.851]],["M 296 -689L 285 -684C 302 -649 317 -595 314 -548C 387 -474 495 -619 296 -689Z",[-0.115,0.384]],["M 338 35L 346 63L 966 63C 980 63 992 58 994 47C 947 2 866 -64 866 -64L 794 35Z",[0.868,0.058]],["M 422 -786C 414 -631 381 -466 338 -352L 350 -345C 447 -432 511 -559 553 -718C 576 -718 588 -727 592 -740Z",[0.229,0.672]],["M 403 -302L 411 -274L 924 -274C 938 -274 949 -279 952 -290C 910 -333 836 -397 836 -397L 770 -302Z",[0.85,0.068]],["M 452 -576L 452 -548L 944 -548C 958 -548 969 -553 972 -564C 927 -607 850 -670 850 -670L 782 -576Z",[0.827,0.086]],["M 580 -845L 580 52L 725 52L 725 -802C 749 -806 755 -815 757 -829Z",[0.003,0.842]]],"bbox":{"top":-854,"bottom":95,"left":1,"right":994},"hadv":1000}],"text":"性","hadv":1000,"breakAfter":true},{"chars":[{"char":"能","components":[["M 377 -796L 196 -859C 176 -799 101 -684 47 -654C 35 -648 14 -643 14 -643L 72 -503C 100 -515 121 -554 126 -627L 64 -627L 64 -616C 158 -648 289 -726 354 -789L 318 -782C 354 -773 372 -783 377 -796Z",[0.453,0.48]],["M 33 -641L 83 -517C 234 -559 357 -602 422 -628L 422 -641C 260 -639 102 -639 33 -641Z",[0.817,0.08]],["M 218 50L 218 -445L 441 -445L 441 -473L 223 -473L 87 -528L 87 94L 107 94C 164 94 218 64 218 50Z",[0.073,0.662]],["M 425 -206L 136 -206L 136 -178L 425 -178Z",[-0.898,0.0]],["M 427 -345L 138 -345L 138 -317L 427 -317Z",[-0.905,0.0]],["M 325 -473L 335 -473L 335 -77C 335 -66 332 -60 318 -60C 298 -60 238 -64 238 -64L 238 -51C 276 -44 291 -28 302 -7C 312 14 316 46 317 91C 456 79 475 28 475 -62L 475 -423C 496 -426 508 -436 515 -444L 386 -542Z",[0.047,0.737]],["M 337 -747L 329 -742C 366 -692 399 -619 403 -552C 522 -456 644 -693 337 -747Z",[-0.169,0.346]],["M 721 -824L 547 -838L 547 -514C 547 -424 569 -400 676 -400L 760 -400C 909 -400 960 -425 960 -481C 960 -506 951 -522 917 -537L 913 -639L 903 -639C 884 -591 866 -555 855 -541C 848 -532 839 -530 828 -530C 817 -529 797 -529 778 -529L 715 -529C 693 -529 689 -533 689 -547L 689 -798C 710 -802 719 -811 721 -824Z",[-0.252,0.299]],["M 728 -362L 553 -376L 553 -44C 553 47 576 72 686 72L 772 72C 925 72 977 47 977 -10C 977 -35 968 -51 933 -67L 929 -179L 919 -179C 899 -126 881 -86 869 -71C 862 -62 854 -60 842 -59C 831 -58 810 -58 790 -58L 723 -58C 701 -58 696 -63 696 -77L 696 -336C 718 -339 727 -349 728 -362Z",[-0.263,0.297]],["M 967 -240L 821 -351C 784 -303 707 -226 647 -180L 650 -170C 744 -188 838 -215 901 -235C 936 -226 956 -229 967 -240Z",[0.553,0.216]],["M 956 -691L 820 -801C 784 -758 709 -689 651 -646L 655 -636C 740 -650 831 -672 891 -688C 924 -678 944 -680 956 -691Z",[0.428,0.209]]],"bbox":{"top":-859,"bottom":94,"left":14,"right":977},"hadv":1000}],"text":"能","hadv":1000,"breakAfter":true},{"chars":[{"char":"影","components":[["M 515 -526L 455 -450L 27 -450L 35 -422L 597 -422C 611 -422 621 -427 624 -438C 583 -474 515 -526 515 -526Z",[0.809,0.054]],["M 265 -126L 119 -188C 109 -118 79 -15 33 50L 41 61C 122 22 189 -47 229 -110C 253 -109 261 -116 265 -126Z",[0.319,0.453]],["M 204 -193L 204 -337L 473 -337L 473 -365L 210 -365L 85 -413L 85 -158L 101 -158C 150 -158 204 -183 204 -193Z",[0.397,0.165]],["M 211 -528L 211 -763L 459 -763L 459 -791L 216 -791L 89 -841L 89 -491L 106 -491C 157 -491 211 -517 211 -528Z",[0.191,0.285]],["M 458 -581L 164 -581L 164 -553L 458 -553Z",[-0.916,0.002]],["M 458 -687L 164 -687L 164 -659L 458 -659Z",[0.791,0.005]],["M 471 -238L 172 -238L 172 -210L 471 -210Z",[0.883,0.004]],["M 377 -43L 377 -233L 254 -233L 254 -45C 254 -35 251 -29 239 -29C 225 -29 175 -32 175 -32L 175 -20C 209 -13 221 -0 229 15C 238 32 240 60 241 95C 360 86 377 37 377 -43Z",[0.076,0.554]],["M 260 -560L 253 -556C 261 -539 265 -506 256 -476C 345 -378 519 -536 260 -560Z",[-0.119,0.03]],["M 389 -161L 381 -156C 408 -116 435 -56 438 -1C 543 82 657 -119 389 -161Z",[-0.235,0.329]],["M 406 -365L 415 -365L 415 -175L 436 -175C 473 -175 533 -195 534 -202L 534 -321C 551 -325 562 -333 568 -339L 458 -420Z",[0.004,0.446]],["M 411 -791L 421 -791L 421 -513L 442 -513C 480 -513 540 -533 541 -540L 541 -743C 562 -747 576 -756 582 -764L 465 -851Z",[0.021,0.579]],["M 990 -227L 819 -318C 730 -130 615 -2 463 89L 468 101C 661 44 815 -51 947 -215C 972 -211 983 -215 990 -227Z",[0.553,0.505]],["M 970 -491L 806 -594C 734 -463 652 -348 552 -264L 558 -252C 690 -304 820 -383 929 -482C 953 -477 963 -481 970 -491Z",[0.524,0.472]],["M 962 -746L 804 -846C 735 -724 655 -614 558 -534L 565 -522C 691 -571 817 -646 922 -737C 945 -732 955 -735 962 -746Z",[0.508,0.475]]],"bbox":{"top":-851,"bottom":101,"left":27,"right":990},"hadv":1000}],"text":"影","hadv":1000,"breakAfter":true},{"chars":[{"char":"响","components":[["M 50 -728L 50 -76L 68 -76C 117 -76 160 -102 160 -114L 160 -700L 262 -700L 262 -728L 164 -728L 50 -776Z",[0.023,0.812]],["M 106 -252L 106 -224L 266 -224L 266 -252Z",[0.804,0.002]],["M 213 -728L 213 -131L 232 -131C 272 -131 327 -155 328 -163L 328 -687C 344 -690 354 -697 359 -703L 257 -783L 204 -728Z",[0.007,0.814]],["M 378 -667L 378 95L 400 95C 459 95 512 62 512 46L 512 -639L 852 -639L 852 -667L 519 -667L 378 -724Z",[0.087,0.676]],["M 551 -522L 551 -149L 564 -149C 599 -149 635 -168 635 -176L 635 -494L 714 -494L 714 -522L 639 -522L 551 -559Z",[0.06,0.702]],["M 576 -855C 574 -792 567 -698 562 -645L 590 -645C 634 -684 706 -753 747 -794C 770 -796 785 -804 789 -823Z",[-0.354,0.042]],["M 604 -270L 604 -242L 707 -242L 707 -270Z",[0.668,0.028]],["M 674 -522L 674 -173L 690 -173C 720 -173 767 -191 768 -198L 768 -487C 780 -490 789 -495 793 -500L 709 -565L 667 -522Z",[0.011,0.776]],["M 808 -667L 808 -71C 808 -59 805 -53 790 -53C 773 -53 702 -57 702 -57L 702 -44C 743 -35 758 -21 770 -1C 782 19 785 52 787 97C 929 85 948 35 948 -57L 948 -619C 966 -623 978 -631 984 -639L 859 -735L 798 -667Z",[0.037,0.8]]],"bbox":{"top":-855,"bottom":97,"left":50,"right":984},"hadv":1000}],"text":"响","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<script>\nalert('ha');\n</script>\n<style>\n.hi-img {\n  display:  block;\n}\n\n.hi-img > img {\n  margin: 20px auto;\n  width: 100%;\n}\n</style>\n<div class=\"hi-img\">\n  <img alt=\"Intel sale\" src=\"https://storage.c-3.moe/meow/intel-sale-30.jpg\"></img>\n</div>\n<p>看到狂吹 KPTI 造成 5% ~ 30% 的性能损失，自己测试了一下。环境如下:</p>\n<ul>\n<li>服务器: Aliyun 计算型 c5.large</li>\n<li>操作系统: Ubuntu 16.04.3 LTS</li>\n<li>内核版本: 4.4.0-62-generic / 4.14.12-041412-generic\n<ul>\n<li>4.4.0 内核是 Ubuntu Mainline</li>\n<li>4.14.12 内核是在 <a href=\"http://kernel.ubuntu.com/~kernel-ppa/mainline/\">http://kernel.ubuntu.com/~kernel-ppa/mainline/</a> 下载的。</li>\n</ul>\n</li>\n<li>一共三组:\n<ul>\n<li>A: 4.4.0-62: no KPTI</li>\n<li>B: 4.14.12-041412: \\w KPTI &amp; PCID</li>\n<li>C: 4.14.12-041412: \\w KPTI, no PCID</li>\n</ul>\n</li>\n<li>通过添加内核参数 <code>nopcid noinvpcid</code> 禁用 PCID</li>\n<li>测试科目:\n<ul>\n<li>MongoDB 读写，具体见下方 Gist</li>\n<li>这个博客(C3Blog)，数据库内容和在线版本相同，使用 <code>wrk -c100 -t2 -d10s http://localhost/posts --latency</code> 测试</li>\n</ul>\n</li>\n</ul>\n<h2>TL;DR</h2>\n<p>在开启 PCID 时，KPTI 未造成肉眼可见的性能损失。</p>\n<p>在关闭 PCID 后，C3Blog 出现了 10% 左右的 rps 损失，但是 MongoDB 依旧没有明显的性能区别。可能 JavaScript/Mongoose 带来的 Overhead &gt;&gt; KPTI</p>\n<h2>具体结果</h2>\n<p>贴在了这个 Gist 上: <a href=\"https://gist.github.com/anonymous/879353087717b1eec1e6435b22d94a8c\">https://gist.github.com/anonymous/879353087717b1eec1e6435b22d94a8c</a></p>\n<p>一不小心贴到 Anonymous 上了，嘻嘻，改天挪到自己的 Namespace 下。</p>\n<p>格式是: <code>[Group].[Test].txt</code></p>\n<ul>\n<li>Group: A\\B\\C</li>\n<li>Test:\n<ul>\n<li>uname: <code>uname -r</code> 输出</li>\n<li>c: C3Blog</li>\n<li>m: MongoDB</li>\n</ul>\n</li>\n</ul>\n<style>\niframe.gist {\n  border: none;\n  width: 100%;\n}\n</style>\n<iframe class=\"gist\" src=\"data:text/html;charset=utf-8,%3Cstyle%3E%0D%0Abody%20%7B%20margin%3A%200%20%7D%0D%0A%3C%2Fstyle%3E%0D%0A%3Cscript%3E%0D%0Awindow.addEventListener%28%27message%27%2C%20function%28%29%20%7B%0D%0A%20%20window.parent.postMessage%28%7B%20gist%3Atrue%2C%20height%3A%20document.body.scrollHeight%20%7D%2C%20%27%2A%27%29%3B%0D%0A%7D%2C%20false%29%3B%0D%0A%3C%2Fscript%3E%0D%0A%0D%0A%3Cscript%20src%3D%22https%3A%2F%2Fgist.github.com%2Fanonymous%2F879353087717b1eec1e6435b22d94a8c.js%22%3E%3C%2Fscript%3E\" onload=\"frame=this;window.addEventListener('message',function cb(msg){console.log(msg.data);if(msg.data.gist){frame.height=msg.data.height;window.removeEventListener('message', frame,false)}},false);this.contentWindow.postMessage('', '*')\"></iframe>","plain":"看到狂吹 KPTI 造成 5% ~ 30% 的性能损失，自己测试了一下。环境如下:\n- 服务器: Aliyun 计算型 c5.large\n- 操作系统: Ubuntu 16.04.3 LTS\n- 内核版本: 4.4.0-62-generic / 4.14.12-041412-generic- 4.4.0 内核是 Ubuntu Mainline\n- 4.14.12 内核是在 http://kernel.ubuntu.com/~kernel-ppa/mainline/ 下载的。\n\n- 一共三组:- A: 4.4.0-62: no KPTI\n- B: 4.14.12-041412: \\w KPTI & PCID\n- C: 4.14.12-041412: \\w KPTI, no PCID\n\n- 通过添加内核参数 nopcid noinvpcid 禁用 PCID\n- 测试科目:- MongoDB 读写，具体见下方 Gist\n- 这个博客(C3Blog)，数据库内容和在线版本相同，使用 wrk -c100 -t2 -d10s http://localhost/posts --latency 测试\n\n\nTL;DR\n在开启 PCID 时，KPTI 未造成肉眼可见的性能损失。\n在关闭 PCID 后，C3Blog 出现了 10% 左右的 rps 损失，但是 MongoDB 依旧没有明显的性能区别。可能 JavaScript/Mongoose 带来的 Overhead >> KPTI\n\n具体结果\n贴在了这个 Gist 上: https://gist.github.com/anonymous/879353087717b1eec1e6435b22d94a8c\n一不小心贴到 Anonymous 上了，嘻嘻，改天挪到自己的 Namespace 下。\n格式是: [Group].[Test].txt\n- Group: A\\B\\C\n- Test:- uname: uname -r 输出\n- c: C3Blog\n- m: MongoDB\n\n"},{"metadata":{"id":"hello-2018","lang":"zh-CN","title":"2018","tags":["扯淡"],"publish_time":"2018-01-01T17:06:18.238Z","update_time":"2018-01-01T17:07:28.063Z","title_outline":{"groups":[{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612},{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463},{"char":"8","components":[["M 291 17C 467 17 561 -68 561 -197C 561 -297 500 -370 367 -429C 230 -489 203 -552 203 -615C 203 -685 253 -729 308 -729C 372 -729 409 -674 409 -596C 409 -523 393 -469 352 -415L 360 -407L 360 -410C 487 -457 536 -520 536 -591C 536 -683 466 -764 312 -764C 172 -764 68 -684 68 -560C 68 -460 126 -380 242 -331C 377 -272 416 -211 416 -137C 416 -62 377 -18 304 -18C 229 -18 185 -68 185 -176C 185 -247 204 -293 254 -344L 242 -356L 242 -350C 119 -313 53 -249 53 -157C 53 -57 129 17 291 17Z",[-0.008,0.324]]],"bbox":{"top":-764,"bottom":17,"left":53,"right":561},"hadv":613}],"text":"2018","hadv":2301,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>2018 到了，虽然决定写点什么，但是实际上没什么特别想说的。毕竟去年有高考，今年还不一定需要参加今年或明年的高考，于是毫不紧张。但是刚刚发了一篇以后，忽然意识到已经新一年了，于是一定要写点什么。</p>\n<p>说说现在想要做的事情吧。</p>\n<ul>\n<li>有了赚一些零花钱的必然理由，于是需要去打工了。</li>\n<li>脱离了高中的语文课，继续听着有点扯淡的政治课，却希望去读一点小说。</li>\n<li>不写前端了，做更加浪漫的操作系统、数据库、计算机视觉、机器学习、编译器，把未来的好玩的课快快刷完。</li>\n<li>上了计算机系，和大佬<ruby>互吹<rp>(</rp><rt>23</rt><rp>)</rp></ruby>，却有点想去学数学的双学位了，即使线代作业都做了半天，微积分要两天起步。</li>\n<li>学习机床的操作方法，以及一些 CAD 技巧。一些手工，一些炒菜的方法，等等，以便未来送人礼物的时候有一些更多的选项。</li>\n<li>继续做着 Make something big 的梦，逐渐着手从 Something small 开始。</li>\n</ul>\n<p>和去年一比还真是多了不少，然而转念一想又单薄的可怜。不知道是不是和自己一直想保持童心有点关系（笑）。</p>\n<p>总之，又是新的一年了，总是改不了坏习惯，在每个时间都幻想着未来有好事的发生。说不定真的有呢？</p>\n<p>希望看到这里的人都能坚守自己的挚爱，不论这代表着去争取，去维持还是一起携手共进，不论这意味着煎熬、恐惧亦或从未见过的阳光。</p>\n","plain":"2018 到了，虽然决定写点什么，但是实际上没什么特别想说的。毕竟去年有高考，今年还不一定需要参加今年或明年的高考，于是毫不紧张。但是刚刚发了一篇以后，忽然意识到已经新一年了，于是一定要写点什么。\n说说现在想要做的事情吧。\n- 有了赚一些零花钱的必然理由，于是需要去打工了。\n- 脱离了高中的语文课，继续听着有点扯淡的政治课，却希望去读一点小说。\n- 不写前端了，做更加浪漫的操作系统、数据库、计算机视觉、机器学习、编译器，把未来的好玩的课快快刷完。\n- 上了计算机系，和大佬互吹(23)，却有点想去学数学的双学位了，即使线代作业都做了半天，微积分要两天起步。\n- 学习机床的操作方法，以及一些 CAD 技巧。一些手工，一些炒菜的方法，等等，以便未来送人礼物的时候有一些更多的选项。\n- 继续做着 Make something big 的梦，逐渐着手从 Something small 开始。\n和去年一比还真是多了不少，然而转念一想又单薄的可怜。不知道是不是和自己一直想保持童心有点关系（笑）。\n总之，又是新的一年了，总是改不了坏习惯，在每个时间都幻想着未来有好事的发生。说不定真的有呢？\n希望看到这里的人都能坚守自己的挚爱，不论这代表着去争取，去维持还是一起携手共进，不论这意味着煎熬、恐惧亦或从未见过的阳光。\n"},{"metadata":{"id":"quit-ovz-due-to-docker","lang":"zh-CN","title":"当你想在 OpenVZ 上装 Docker 时","tags":["技术"],"publish_time":"2018-01-01T16:30:39.321Z","update_time":"2018-01-01T16:30:58.266Z","title_outline":{"groups":[{"chars":[{"char":"当","components":[["M 789 -14L 80 -14L 89 14L 789 14Z",[-0.96,0.0]],["M 800 -470L 100 -470L 109 -442L 800 -442Z",[0.848,0.007]],["M 145 -779L 137 -774C 182 -705 228 -613 243 -527C 379 -423 496 -692 145 -779Z",[-0.254,0.428]],["M 801 -245L 149 -245L 158 -217L 801 -217Z",[-0.955,0.0]],["M 610 -840L 426 -854L 426 -456L 573 -456L 573 -811C 601 -815 608 -825 610 -840Z",[0.018,0.627]],["M 906 -722L 715 -794C 689 -688 651 -566 622 -492L 632 -485C 713 -538 795 -615 863 -703C 887 -702 901 -709 906 -722Z",[0.325,0.461]],["M 718 -470L 729 -470L 729 94L 753 94C 807 94 876 59 877 48L 877 -415C 900 -420 914 -430 921 -439L 786 -545Z",[0.012,0.739]]],"bbox":{"top":-854,"bottom":94,"left":80,"right":921},"hadv":1000}],"text":"当","hadv":1000,"breakAfter":true},{"chars":[{"char":"你","components":[["M 204 -856C 169 -661 90 -460 11 -332L 22 -325C 165 -426 276 -572 355 -778C 378 -777 391 -786 396 -799Z",[0.328,0.656]],["M 139 -519L 139 92L 166 92C 223 92 282 62 284 52L 284 -524C 304 -528 312 -535 315 -544L 192 -589Z",[0.011,0.778]],["M 420 -469C 397 -331 349 -185 300 -92L 312 -84C 410 -154 493 -259 554 -395C 577 -395 590 -403 594 -416Z",[0.312,0.593]],["M 464 -853C 433 -698 370 -536 308 -435L 319 -427C 437 -503 534 -614 606 -766C 629 -764 643 -772 648 -785Z",[0.336,0.605]],["M 580 -616L 580 -80C 580 -69 575 -64 560 -64C 538 -64 430 -70 430 -70L 430 -57C 483 -47 504 -32 521 -9C 538 13 543 47 547 94C 702 80 723 27 723 -70L 723 -573C 746 -577 756 -586 758 -601Z",[0.061,0.749]],["M 453 -653L 453 -625L 866 -625L 866 -653Z",[-0.772,0.022]],["M 756 -457L 746 -452C 788 -356 831 -240 840 -132C 975 -9 1096 -292 756 -457Z",[-0.194,0.461]],["M 806 -653C 804 -606 796 -528 787 -476L 794 -470C 847 -501 912 -555 950 -595C 972 -596 982 -599 990 -608L 866 -725L 794 -653Z",[0.249,0.392]]],"bbox":{"top":-856,"bottom":94,"left":11,"right":1096},"hadv":1000}],"text":"你","hadv":1000,"breakAfter":true},{"chars":[{"char":"想","components":[["M 317 -669L 317 -685L 166 -685C 144 -543 97 -393 18 -290L 28 -280C 175 -375 274 -505 317 -669Z",[0.329,0.628]],["M 392 -775L 331 -685L 34 -685L 42 -657L 473 -657C 487 -657 497 -662 500 -673C 461 -714 392 -775 392 -775Z",[0.655,0.082]],["M 167 -225L 156 -224C 163 -169 128 -119 95 -99C 57 -82 30 -49 43 -4C 58 43 112 59 151 36C 207 5 236 -93 167 -225Z",[0.194,0.405]],["M 368 -841L 198 -857L 198 -245L 223 -245C 274 -245 335 -272 335 -283L 335 -816C 359 -820 366 -829 368 -841Z",[0.009,0.769]],["M 439 -228L 262 -241L 262 -49C 262 42 292 62 417 62L 540 62C 739 62 794 44 794 -16C 794 -41 784 -57 743 -72L 740 -183L 731 -183C 705 -125 687 -91 674 -74C 665 -64 658 -61 641 -60C 624 -59 590 -59 558 -59L 443 -59C 411 -59 407 -63 407 -76L 407 -203C 428 -206 437 -215 439 -228Z",[-0.549,0.128]],["M 323 -587L 315 -582C 342 -540 366 -477 368 -420C 474 -331 595 -536 323 -587Z",[-0.145,0.319]],["M 459 -273L 451 -268C 481 -223 507 -158 509 -97C 622 -1 750 -223 459 -273Z",[-0.207,0.316]],["M 636 -302L 636 -740L 844 -740L 844 -768L 640 -768L 500 -823L 500 -257L 520 -257C 578 -257 636 -288 636 -302Z",[0.063,0.636]],["M 842 -355L 567 -355L 567 -327L 842 -327Z",[-0.924,0.003]],["M 842 -497L 567 -497L 567 -469L 842 -469Z",[0.824,0.009]],["M 842 -631L 567 -631L 567 -603L 842 -603Z",[-0.96,0.017]],["M 748 -236L 740 -231C 786 -172 820 -85 821 -6C 947 102 1078 -160 748 -236Z",[-0.218,0.363]],["M 764 -768L 774 -768L 774 -263L 798 -263C 846 -263 916 -290 917 -298L 917 -717C 938 -722 950 -731 957 -739L 827 -838Z",[0.021,0.736]]],"bbox":{"top":-857,"bottom":102,"left":18,"right":1078},"hadv":1000}],"text":"想","hadv":1000,"breakAfter":true},{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"V","components":[["M 6 -713L 163 -698L 199 -698L 360 -716L 360 -747L 6 -747Z",[-0.52,0.013]],["M 320 2L 412 2L 675 -747L 616 -747L 426 -152L 421 -138L 437 -138L 238 -747L 56 -747Z",[-0.092,0.363]],["M 494 -716L 619 -698L 634 -698L 740 -717L 740 -747L 494 -747Z",[0.424,0.089]]],"bbox":{"top":-747,"bottom":2,"left":6,"right":740},"hadv":744},{"char":"Z","components":[["M 25 -0L 604 -0L 607 -223L 553 -223L 488 -10L 528 -39L 201 -39L 201 -68L 193 -12L 600 -699L 600 -747L 49 -747L 40 -531L 102 -531L 157 -736L 118 -708L 423 -708L 423 -691L 433 -733L 25 -48Z",[0.053,0.376]]],"bbox":{"top":-747,"bottom":0,"left":25,"right":607},"hadv":638}],"text":"OpenVZ","hadv":4149,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"上","components":[["M 25 13L 33 41L 947 41C 962 41 974 36 977 25C 920 -23 826 -94 826 -94L 742 13Z",[0.911,0.043]],["M 386 -839L 386 29L 546 29L 546 -792C 574 -796 581 -806 583 -821Z",[0.004,0.811]],["M 477 -453L 477 -425L 876 -425C 891 -425 902 -430 905 -441C 850 -489 758 -559 758 -559L 676 -453Z",[0.76,0.075]]],"bbox":{"top":-839,"bottom":41,"left":25,"right":977},"hadv":1000}],"text":"上","hadv":1000,"breakAfter":true},{"chars":[{"char":"装","components":[["M 575 -281L 575 -297L 383 -297C 310 -216 179 -137 21 -91L 25 -79C 262 -109 464 -172 575 -281Z",[0.745,0.321]],["M 30 -536L 116 -394C 127 -397 137 -407 141 -421C 211 -490 256 -542 284 -578L 282 -586C 180 -564 75 -543 30 -536Z",[0.432,0.188]],["M 845 -391L 776 -297L 40 -297L 48 -269L 941 -269C 955 -269 966 -274 969 -285C 923 -328 845 -391 845 -391Z",[0.917,0.037]],["M 89 -802L 80 -798C 99 -755 113 -695 109 -640C 208 -540 353 -732 89 -802Z",[-0.065,0.416]],["M 385 -187L 279 -187L 279 -97C 279 -77 270 -65 211 -37L 286 98C 315 83 349 39 334 -42L 274 3L 420 -47L 420 -166Z",[0.206,0.43]],["M 252 -44L 292 85C 428 28 540 -31 599 -63L 597 -74C 455 -59 311 -47 252 -44Z",[0.651,0.174]],["M 428 -840L 256 -855L 256 -347L 280 -347C 332 -347 391 -370 391 -380L 391 -812C 419 -816 426 -826 428 -840Z",[0.014,0.723]],["M 420 -237L 279 -196L 279 -156L 420 -156Z",[0.524,0.129]],["M 848 -767L 780 -676L 404 -676L 412 -648L 942 -648C 957 -648 968 -653 971 -664C 925 -706 848 -767 848 -767Z",[0.743,0.082]],["M 419 -408L 412 -403C 429 -384 444 -346 444 -312C 548 -234 671 -422 419 -408Z",[0.08,0.037]],["M 830 -552L 766 -464L 427 -464L 435 -436L 918 -436C 932 -436 943 -441 946 -452C 903 -492 830 -552 830 -552Z",[0.791,0.079]],["M 541 -289L 530 -283C 583 -68 695 25 868 90C 884 22 921 -25 977 -40L 977 -52C 793 -75 611 -129 541 -289Z",[-0.553,0.336]],["M 765 -837L 587 -851L 587 -448L 733 -448L 733 -811C 757 -815 764 -824 765 -837Z",[0.026,0.633]],["M 909 -181L 774 -279C 746 -240 684 -178 632 -140L 641 -129C 720 -136 810 -151 871 -172C 894 -167 903 -172 909 -181Z",[0.505,0.139]]],"bbox":{"top":-855,"bottom":98,"left":21,"right":977},"hadv":1000}],"text":"装","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"r","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -409L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -387 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.021,0.684]],["M 32 -0L 358 -0L 358 -31L 249 -42L 139 -42L 32 -31Z",[-0.874,0.0]],["M 263 -321C 284 -404 314 -449 365 -484L 333 -492L 356 -463C 382 -426 406 -403 444 -403C 494 -403 516 -438 518 -484C 508 -544 469 -563 421 -563C 357 -563 283 -502 256 -386L 224 -386Z",[0.468,0.159]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":518},"hadv":520}],"text":"Docker","hadv":3794,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"时","components":[["M 61 -793L 61 -0L 85 -0C 153 -0 194 -31 194 -40L 194 -739L 207 -739Z",[-0.002,0.826]],["M 316 -185L 137 -185L 137 -157L 316 -157Z",[-0.878,0.008]],["M 316 -466L 137 -466L 137 -438L 316 -438Z",[-0.675,0.024]],["M 316 -739L 137 -739L 137 -711L 316 -711Z",[-0.44,0.024]],["M 263 -739L 273 -739L 273 -58L 295 -58C 343 -58 407 -86 408 -95L 408 -689C 428 -694 441 -702 448 -711L 325 -808Z",[0.008,0.809]],["M 890 -708L 828 -603L 410 -603L 418 -575L 969 -575C 983 -575 994 -580 997 -591C 961 -636 890 -708 890 -708Z",[0.806,0.076]],["M 444 -485L 435 -480C 471 -413 497 -325 494 -243C 620 -123 765 -382 444 -485Z",[-0.176,0.414]],["M 876 -824L 689 -841L 689 -80C 689 -67 683 -60 665 -60C 636 -60 489 -69 489 -69L 489 -56C 558 -44 583 -29 606 -6C 629 16 637 49 642 97C 814 82 839 29 839 -70L 839 -795C 864 -799 874 -809 876 -824Z",[0.046,0.809]]],"bbox":{"top":-841,"bottom":97,"left":61,"right":997},"hadv":1000}],"text":"时","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p><strong>赶紧停下来，千万别这么想</strong></p>\n<p>因为你（很）可能会（依次）遇到以下问题：</p>\n<ul>\n<li>很大可能 Host 在用 OpenVZ 6，内核 2.6，只有 RHEL 才在 backport 一些内核补丁到 2.6，导致你想用到<strong>比较</strong>新的 Docker，只能用 CentOS / RHEL。</li>\n<li>需要 Host 启动 tuntap、bridge 等一系列模块，然而你在容器里根本查不出来什么有什么没有。</li>\n<li>就算你用了续命内核，Docker 也只活到 1.7，新版本仍旧炸。</li>\n<li>1.7.0 会在用 bridge 的时候会有 <strong>Operation not supported</strong>，然而 strace 都看不到有 supported 这个词。</li>\n<li>可以用 –net=host 规避，但是 docker build 没有这个选项。</li>\n<li>在邮件列表里可以查出来上面那个是什么问题：虽然说文档称 1.7 支持 2.6 内核，但是 1.7.0 引入了 Regression。1.7.1 可以工作，但是 1.7 的文档页上没有 1.7.1 的下载链接。</li>\n<li>好不容易跑起来了，只支持 aufs，性能爆炸。</li>\n<li>Docker-compose 的配套版本要从 Github releases 里面翻找，是 1.5。</li>\n<li>1.5 不支持 File version。</li>\n<li>Dockerfile 不支持 Add 等一堆东西。</li>\n</ul>\n<p>除非当 Webserver，我这辈子再也不贪便宜买 OpenVZ 的服务器了。</p>\n","plain":"赶紧停下来，千万别这么想\n因为你（很）可能会（依次）遇到以下问题：\n- 很大可能 Host 在用 OpenVZ 6，内核 2.6，只有 RHEL 才在 backport 一些内核补丁到 2.6，导致你想用到比较新的 Docker，只能用 CentOS / RHEL。\n- 需要 Host 启动 tuntap、bridge 等一系列模块，然而你在容器里根本查不出来什么有什么没有。\n- 就算你用了续命内核，Docker 也只活到 1.7，新版本仍旧炸。\n- 1.7.0 会在用 bridge 的时候会有 Operation not supported，然而 strace 都看不到有 supported 这个词。\n- 可以用 –net=host 规避，但是 docker build 没有这个选项。\n- 在邮件列表里可以查出来上面那个是什么问题：虽然说文档称 1.7 支持 2.6 内核，但是 1.7.0 引入了 Regression。1.7.1 可以工作，但是 1.7 的文档页上没有 1.7.1 的下载链接。\n- 好不容易跑起来了，只支持 aufs，性能爆炸。\n- Docker-compose 的配套版本要从 Github releases 里面翻找，是 1.5。\n- 1.5 不支持 File version。\n- Dockerfile 不支持 Add 等一堆东西。\n除非当 Webserver，我这辈子再也不贪便宜买 OpenVZ 的服务器了。\n"},{"metadata":{"id":"announcement-i-quit","lang":"zh-CN","title":"郑重声明","tags":["郑重"],"publish_time":"2017-12-17T03:16:05.759Z","update_time":"2018-03-16T19:20:37.469Z","title_outline":{"groups":[{"chars":[{"char":"郑","components":[["M 348 -456L 348 -616L 208 -616L 208 -456C 208 -287 187 -81 19 82L 26 90C 322 -45 348 -291 348 -456Z",[0.186,0.745]],["M 469 -501L 401 -398L 34 -398L 42 -370L 560 -370C 574 -370 585 -375 588 -386C 545 -431 469 -501 469 -501Z",[0.817,0.075]],["M 448 -703L 384 -616L 64 -616L 72 -588L 534 -588C 548 -588 559 -593 562 -604C 520 -644 448 -703 448 -703Z",[0.748,0.072]],["M 116 -846L 108 -839C 149 -786 166 -708 171 -657C 267 -547 427 -784 116 -846Z",[-0.161,0.376]],["M 287 -286L 278 -281C 328 -207 382 -110 404 -19C 543 82 653 -192 287 -286Z",[-0.312,0.447]],["M 538 -801L 366 -858C 354 -783 329 -674 305 -600L 316 -600C 385 -656 456 -732 499 -783C 522 -781 534 -789 538 -801Z",[0.277,0.469]],["M 565 -831L 565 95L 592 95C 666 95 709 61 709 51L 709 -760L 723 -760Z",[-0.001,0.836]],["M 882 -760L 626 -760L 626 -732L 882 -732Z",[-0.816,0.045]],["M 772 -760L 785 -760C 775 -677 746 -530 722 -451C 783 -387 808 -307 808 -237C 808 -208 799 -192 784 -184C 776 -180 770 -179 760 -179C 748 -179 710 -179 689 -179L 689 -168C 716 -161 733 -149 741 -135C 752 -117 758 -61 758 -17C 895 -18 941 -89 941 -191C 941 -281 882 -392 748 -454C 815 -520 893 -625 936 -690C 962 -691 975 -695 983 -706L 845 -830Z",[0.016,0.78]]],"bbox":{"top":-858,"bottom":95,"left":19,"right":983},"hadv":1000}],"text":"郑","hadv":1000,"breakAfter":true},{"chars":[{"char":"重","components":[["M 27 26L 35 54L 944 54C 959 54 971 49 974 38C 919 -9 826 -79 826 -79L 744 26Z",[0.912,0.042]],["M 46 -635L 54 -607L 925 -607C 939 -607 951 -612 954 -623C 902 -665 819 -724 819 -724L 745 -635Z",[0.93,0.031]],["M 742 -858C 598 -807 318 -748 100 -722L 101 -707C 333 -700 612 -715 791 -740C 825 -726 849 -726 861 -736Z",[0.779,0.102]],["M 107 -118L 115 -90L 882 -90C 897 -90 908 -95 911 -106C 861 -147 779 -205 779 -205L 708 -118Z",[0.912,0.041]],["M 150 -518L 150 -157L 171 -157C 230 -157 295 -189 295 -202L 295 -490L 731 -490L 731 -518L 303 -518L 150 -576Z",[0.301,0.221]],["M 244 -252L 244 -224L 753 -224L 753 -252Z",[-0.962,0.001]],["M 244 -387L 244 -359L 753 -359L 753 -387Z",[-0.913,0.005]],["M 421 -743L 421 33L 569 33L 569 -743Z",[0.004,0.797]],["M 702 -518L 702 -181L 727 -181C 777 -181 848 -210 849 -219L 849 -467C 870 -471 882 -480 888 -488L 756 -588L 692 -518Z",[0.017,0.597]]],"bbox":{"top":-858,"bottom":54,"left":27,"right":974},"hadv":1000}],"text":"重","hadv":1000,"breakAfter":true},{"chars":[{"char":"声","components":[["M 161 -469L 161 -312C 161 -181 147 -28 25 90L 31 98C 280 -3 303 -184 303 -312L 303 -469L 324 -469L 161 -524L 161 -479Z",[0.144,0.712]],["M 42 -735L 50 -707L 932 -707C 947 -707 958 -712 961 -723C 910 -764 828 -823 828 -823L 755 -735Z",[0.865,0.024]],["M 113 -593L 121 -565L 884 -565C 899 -565 910 -570 913 -581C 862 -623 778 -685 778 -685L 704 -593Z",[0.89,0.034]],["M 222 -262L 222 -234L 778 -234L 778 -262Z",[-0.989,0.001]],["M 222 -469L 222 -441L 778 -441L 778 -469Z",[-0.829,0.012]],["M 425 -855L 425 -584L 572 -584L 572 -813C 600 -817 606 -827 608 -841Z",[0.007,0.412]],["M 429 -469L 429 -253L 566 -253L 566 -469Z",[0.0,0.361]],["M 700 -469L 700 -162L 725 -162C 771 -162 844 -185 845 -192L 845 -418C 866 -422 878 -432 884 -440L 753 -538L 690 -469Z",[0.015,0.561]]],"bbox":{"top":-855,"bottom":98,"left":25,"right":961},"hadv":1000}],"text":"声","hadv":1000,"breakAfter":true},{"chars":[{"char":"明","components":[["M 69 -756L 69 -94L 93 -94C 161 -94 202 -128 202 -138L 202 -756L 215 -756L 69 -810Z",[-0.001,0.806]],["M 138 -756L 138 -728L 346 -728L 346 -756Z",[0.376,0.031]],["M 138 -512L 138 -484L 346 -484L 346 -512Z",[0.723,0.004]],["M 138 -267L 138 -239L 346 -239L 346 -267Z",[0.846,0.002]],["M 507 -776L 507 -455C 507 -247 480 -63 286 85L 294 93C 613 -32 642 -251 642 -456L 642 -776L 662 -776L 507 -829L 507 -786Z",[0.134,0.785]],["M 296 -756L 296 -150L 318 -150C 367 -150 430 -183 431 -193L 431 -706C 451 -711 464 -719 471 -728L 348 -824L 286 -756Z",[0.012,0.785]],["M 565 -776L 565 -748L 849 -748L 849 -776Z",[-0.872,0.002]],["M 565 -550L 565 -522L 849 -522L 849 -550Z",[0.852,0.001]],["M 565 -322L 565 -294L 849 -294L 849 -322Z",[0.871,0.004]],["M 795 -776L 795 -78C 795 -63 790 -56 772 -56C 746 -56 618 -63 618 -63L 618 -50C 678 -39 703 -24 723 -3C 742 17 749 49 753 94C 911 80 932 29 932 -63L 932 -726C 953 -730 966 -739 973 -747L 846 -846L 785 -776Z",[0.048,0.814]]],"bbox":{"top":-846,"bottom":94,"left":69,"right":973},"hadv":1000}],"text":"明","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>从今天开始，你们不要说我在清华附中高等研究实验室待过的。</p>\n<p>很惭愧，给母校和实验室丢人了。</p>\n<style>\n.img-indicator + p img {\n  max-width: 100%;\n  margin: 0 auto;\n}\n</style>\n<div class=\"img-indicator\"></div>\n<p><img src=\"https://storage.c-3.moe/meow/guilty.JPEG\" alt=\"Guilty\" /></p>\n<hr />\n<p>解释一下</p>\n<p>由于我的认知被证明与现实有所偏差，而且我本人在实验室没有做出什么成果，为了不产生消极影响，所以不再以实验室的前辈身份发言、活动。不代表与实验室断绝关系。</p>\n<p>这不是划清界限，我没有对实验室彻底失望。反而是有玩伴长大了得感觉，有了主见，有了话语权。这是很令我开心且惆怅的事情。</p>\n<p>祝好。</p>\n","plain":"从今天开始，你们不要说我在清华附中高等研究实验室待过的。\n很惭愧，给母校和实验室丢人了。\nGuilty\n---\n解释一下\n由于我的认知被证明与现实有所偏差，而且我本人在实验室没有做出什么成果，为了不产生消极影响，所以不再以实验室的前辈身份发言、活动。不代表与实验室断绝关系。\n这不是划清界限，我没有对实验室彻底失望。反而是有玩伴长大了得感觉，有了主见，有了话语权。这是很令我开心且惆怅的事情。\n祝好。\n"},{"metadata":{"id":"fireflies","lang":"zh-CN","title":"萤火","tags":["扯淡"],"publish_time":"2017-12-02T18:03:34.266Z","update_time":"2017-12-02T18:04:06.758Z","title_outline":{"groups":[{"chars":[{"char":"萤","components":[["M 269 -728L 28 -728L 35 -700L 269 -700L 269 -586L 292 -586C 354 -586 409 -605 409 -616L 409 -700L 587 -700L 587 -592L 609 -592C 673 -592 729 -610 729 -622L 729 -700L 949 -700C 964 -700 974 -705 977 -716C 934 -758 858 -819 858 -819L 790 -728L 729 -728L 729 -818C 755 -822 762 -832 763 -845L 587 -860L 587 -728L 409 -728L 409 -818C 434 -822 442 -832 443 -845L 269 -860Z",[0.666,0.024]],["M 154 -651L 142 -651C 149 -604 113 -555 87 -535C 50 -516 26 -481 41 -437C 59 -390 119 -378 152 -405C 197 -441 212 -531 154 -651Z",[0.163,0.416]],["M 92 -72L 141 90C 153 88 166 81 174 68C 462 17 649 -23 774 -58L 774 -72C 486 -68 206 -69 92 -72Z",[0.81,0.076]],["M 850 -574L 150 -574L 150 -546L 850 -546Z",[0.816,0.009]],["M 197 -438L 197 -124L 221 -124C 289 -124 330 -144 330 -153L 330 -357L 684 -357L 684 -142L 710 -142C 782 -142 824 -163 824 -167L 824 -349C 847 -353 856 -359 862 -368L 744 -456L 681 -385L 340 -385ZM 721 -204L 265 -204L 265 -176L 721 -176Z",[0.629,0.027]],["M 609 -496L 437 -510L 437 -29L 577 -44L 577 -470C 602 -474 608 -483 609 -496Z",[0.012,0.695]],["M 632 -148L 624 -142C 678 -83 743 3 773 80C 912 158 996 -105 632 -148Z",[-0.376,0.376]],["M 781 -574L 792 -574C 795 -535 797 -470 796 -426L 802 -421C 848 -444 904 -485 938 -516C 959 -517 968 -520 977 -529L 852 -646Z",[0.098,0.195]]],"bbox":{"top":-860,"bottom":158,"left":26,"right":996},"hadv":1000}],"text":"萤","hadv":1000,"breakAfter":true},{"chars":[{"char":"火","components":[["M 545 -803C 570 -807 580 -816 583 -832L 383 -850C 383 -441 412 -151 20 81L 28 94C 557 -82 537 -386 545 -803Z",[0.23,0.727]],["M 230 -686L 220 -685C 225 -568 173 -467 121 -429C 88 -402 73 -360 97 -321C 126 -278 190 -272 231 -318C 290 -379 321 -504 230 -686Z",[0.196,0.561]],["M 544 -803L 527 -802C 537 -336 575 -42 858 95C 872 18 917 -35 987 -50L 988 -61C 653 -165 563 -379 544 -803Z",[-0.346,0.646]],["M 937 -587L 760 -692C 729 -600 655 -437 589 -331L 597 -322C 714 -395 824 -497 897 -573C 923 -571 932 -578 937 -587Z",[0.384,0.491]]],"bbox":{"top":-850,"bottom":95,"left":20,"right":988},"hadv":1000}],"text":"火","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>最近关于三种颜色，听到一种说法是众人讨论某些人的无为而使舆论被压制，最后反而害了孩子。</p>\n<p>反驳倒是没什么可以反驳的，毕竟非常客观。只是想起一段话，来自著名社会活动家：</p>\n<blockquote>\n<p>愿中国青年都摆脱冷气，只是向上走，不必听自暴自弃者流的话。能做事的做事，能发声的发声。有一分热，发一分光，就令萤火一般，也可以在黑暗里发一点光，不必等候炬火。</p>\n<p><strong>此后如竟没有炬火：我便是唯一的光。</strong></p>\n</blockquote>\n","plain":"最近关于三种颜色，听到一种说法是众人讨论某些人的无为而使舆论被压制，最后反而害了孩子。\n反驳倒是没什么可以反驳的，毕竟非常客观。只是想起一段话，来自著名社会活动家：\n愿中国青年都摆脱冷气，只是向上走，不必听自暴自弃者流的话。能做事的做事，能发声的发声。有一分热，发一分光，就令萤火一般，也可以在黑暗里发一点光，不必等候炬火。\n此后如竟没有炬火：我便是唯一的光。\n\n"},{"metadata":{"id":"getting-around-in-japan","lang":"zh-CN","title":"日本的交通","tags":["扯淡"],"publish_time":"2017-08-19T15:27:32.236Z","update_time":"2017-08-19T16:21:49.888Z","title_outline":{"groups":[{"chars":[{"char":"日","components":[["M 175 -744L 175 90L 200 90C 266 90 328 53 328 34L 328 -716L 776 -716L 776 -744L 337 -744L 175 -808Z",[0.098,0.63]],["M 243 -400L 243 -372L 756 -372L 756 -400Z",[-0.908,0.005]],["M 243 -42L 243 -14L 756 -14L 756 -42Z",[0.945,0.0]],["M 686 -744L 686 80L 711 80C 769 80 842 45 844 34L 844 -692C 864 -697 875 -705 882 -714L 747 -822L 676 -744Z",[0.009,0.793]]],"bbox":{"top":-822,"bottom":90,"left":175,"right":882},"hadv":1000}],"text":"日","hadv":1000,"breakAfter":true},{"chars":[{"char":"本","components":[["M 528 -606L 528 -622L 347 -622C 302 -423 187 -199 22 -62L 31 -54C 290 -175 455 -367 528 -606Z",[0.431,0.633]],["M 808 -731L 729 -622L 63 -622L 71 -594L 919 -594C 934 -594 945 -599 948 -610C 897 -658 808 -731 808 -731Z",[0.879,0.047]],["M 634 -274L 566 -172L 241 -172L 249 -144L 726 -144C 740 -144 751 -149 754 -160C 711 -205 634 -274 634 -274Z",[0.808,0.078]],["M 615 -838L 421 -857L 421 92L 449 92C 510 92 570 64 570 52L 570 -804C 604 -809 613 -821 615 -838Z",[0.005,0.834]],["M 574 -622L 564 -618C 614 -367 698 -189 850 -76C 873 -147 920 -194 978 -206L 981 -217C 818 -286 652 -428 574 -622Z",[-0.417,0.519]]],"bbox":{"top":-857,"bottom":92,"left":22,"right":981},"hadv":1000}],"text":"本","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"交","components":[["M 784 -377L 610 -453C 533 -225 355 -20 27 83L 32 95C 420 43 632 -141 744 -361C 768 -359 779 -366 784 -377Z",[0.599,0.525]],["M 836 -772L 759 -662L 41 -662L 49 -634L 944 -634C 959 -634 970 -639 973 -650C 923 -698 836 -772 836 -772Z",[0.932,0.042]],["M 453 -549L 280 -637C 246 -533 166 -395 63 -309L 69 -299C 221 -347 341 -441 415 -534C 439 -532 449 -539 453 -549Z",[0.448,0.463]],["M 317 -426L 305 -418C 395 -127 596 15 858 95C 878 25 919 -22 984 -35L 986 -47C 713 -88 426 -189 317 -426Z",[-0.648,0.378]],["M 361 -856L 354 -851C 396 -808 439 -740 453 -676C 590 -591 696 -852 361 -856Z",[-0.307,0.285]],["M 591 -614L 584 -607C 671 -544 762 -440 801 -343C 955 -262 1032 -572 591 -614Z",[-0.367,0.345]]],"bbox":{"top":-856,"bottom":95,"left":27,"right":1032},"hadv":1000}],"text":"交","hadv":1000,"breakAfter":true},{"chars":[{"char":"通","components":[["M 227 -162C 202 -162 92 -86 21 -49L 113 93C 121 88 127 80 124 70C 154 8 198 -68 217 -106C 228 -126 239 -129 253 -106C 329 20 415 77 627 77C 706 77 826 77 885 77C 891 19 922 -31 976 -45L 976 -56C 868 -49 779 -48 672 -48C 450 -47 343 -70 267 -146C 254 -158 247 -162 227 -162Z",[-0.82,0.076]],["M 274 -137L 274 -442C 303 -447 318 -455 326 -465L 192 -572L 129 -488L 21 -488L 27 -460L 144 -460L 144 -105Z",[-0.026,0.604]],["M 65 -832L 57 -827C 99 -768 143 -685 158 -609C 287 -515 398 -766 65 -832Z",[-0.251,0.397]],["M 785 -782L 334 -782L 343 -754L 785 -754Z",[0.639,0.013]],["M 490 -112L 490 -551L 801 -551L 801 -579L 496 -579L 357 -634L 357 -68L 377 -68C 433 -68 490 -98 490 -112Z",[0.121,0.516]],["M 805 -302L 430 -302L 430 -274L 805 -274Z",[0.812,0.036]],["M 805 -442L 430 -442L 430 -414L 805 -414Z",[0.755,0.047]],["M 443 -719L 439 -707C 520 -678 565 -633 588 -596C 685 -499 907 -720 443 -719Z",[-0.407,0.156]],["M 684 -119L 684 -579L 560 -579L 560 -92L 583 -92C 646 -92 683 -113 684 -119Z",[0.003,0.745]],["M 716 -782L 727 -782C 707 -744 664 -684 630 -647L 636 -640C 709 -658 810 -693 869 -725C 891 -726 900 -729 909 -738L 788 -852Z",[0.718,0.043]],["M 748 -579L 758 -579L 758 -203C 758 -193 756 -187 744 -187C 731 -187 701 -189 701 -189L 701 -177C 729 -171 737 -157 743 -142C 750 -125 751 -98 752 -61C 875 -71 891 -113 891 -192L 891 -529C 912 -533 925 -543 931 -550L 807 -645Z",[0.038,0.724]]],"bbox":{"top":-852,"bottom":93,"left":21,"right":976},"hadv":1000}],"text":"通","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>去日本待了两周，回来了都不会过马路了。在东京马路正中心站定，四周车主都会立即踩下刹车，投向你的目光中饱含敬畏。而日本城区路网密到了十米一个红绿灯，好几次闯了红灯都设有发现，不知道私家车在日本城市的存在价值是否比得上中国城市的自行车。</p>\n<p>与之相对的是日本国民引以为傲的公共交通系统。虽说是在丑恶的资本社会中成长起来的，价钱自然沒有国内计划经济得那么赏心悦目，但方便是足够的。一张卡可以刷遍关东关西的电车公交，公交按键下车，电车时刻表、双向通行的闸口等等。快车和加急的存在，使电车至少是不会像十三号线一样挤得我下不了车。</p>\n<p>方便之余，不免让我感觉少了预期中的人的气息。与有缝铁轨的咔咔声一起消失的，还有孩子的哭闹声、聊天声。有两个大叔在看书，书包着书皮，仔细一看，一个是轻小说，一个少年漫。</p>\n<p>令人吃惊的地方在于细节。公交车在开门时会向上下车的一侧倾斜，公路中央立着的路标可以按下一个按纽变为盲文，两个一单行道的路口也会有斑马线，并配有带扬声器的红绿灯。</p>\n<p>前几天深圳地铁“女性专用车厢”闹得开了锅，最后好像也是不了了之。但第一次见到实物是在日本，很普遍，每个城市都有。仔细一想，女性与男性生理层面上是否有普遍的体能差距呢？大概。</p>\n<p>于是在近处观察后，发觉这是已经冷却下来的现代城市，其中的人和工具都冷静地知道自己要做什么，需要什么，并清楚自己属于钢筋水泥的土地。但人终于是人，工具也是人为人而造的。就像四处竖立的自动售货机，当终于看到为其装填的小伙子时，才会发现它满是人情味，在某种意义上，更甚于街边的小卖铺。</p>\n<p>花火大会后，JR大津站前排起了长队，连检票口都保持开放了。经过两小时的漫长等待，身着彩色和服的人们登上加开的列车，并一改常态，有说有笑。</p>\n","plain":"去日本待了两周，回来了都不会过马路了。在东京马路正中心站定，四周车主都会立即踩下刹车，投向你的目光中饱含敬畏。而日本城区路网密到了十米一个红绿灯，好几次闯了红灯都设有发现，不知道私家车在日本城市的存在价值是否比得上中国城市的自行车。\n与之相对的是日本国民引以为傲的公共交通系统。虽说是在丑恶的资本社会中成长起来的，价钱自然沒有国内计划经济得那么赏心悦目，但方便是足够的。一张卡可以刷遍关东关西的电车公交，公交按键下车，电车时刻表、双向通行的闸口等等。快车和加急的存在，使电车至少是不会像十三号线一样挤得我下不了车。\n方便之余，不免让我感觉少了预期中的人的气息。与有缝铁轨的咔咔声一起消失的，还有孩子的哭闹声、聊天声。有两个大叔在看书，书包着书皮，仔细一看，一个是轻小说，一个少年漫。\n令人吃惊的地方在于细节。公交车在开门时会向上下车的一侧倾斜，公路中央立着的路标可以按下一个按纽变为盲文，两个一单行道的路口也会有斑马线，并配有带扬声器的红绿灯。\n前几天深圳地铁“女性专用车厢”闹得开了锅，最后好像也是不了了之。但第一次见到实物是在日本，很普遍，每个城市都有。仔细一想，女性与男性生理层面上是否有普遍的体能差距呢？大概。\n于是在近处观察后，发觉这是已经冷却下来的现代城市，其中的人和工具都冷静地知道自己要做什么，需要什么，并清楚自己属于钢筋水泥的土地。但人终于是人，工具也是人为人而造的。就像四处竖立的自动售货机，当终于看到为其装填的小伙子时，才会发现它满是人情味，在某种意义上，更甚于街边的小卖铺。\n花火大会后，JR大津站前排起了长队，连检票口都保持开放了。经过两小时的漫长等待，身着彩色和服的人们登上加开的列车，并一改常态，有说有笑。\n"},{"metadata":{"id":"hi","lang":"zh-CN","title":"你好！","tags":["扯淡","解谜"],"publish_time":"2017-06-23T03:31:43.112Z","update_time":"2017-06-23T03:34:28.176Z","title_outline":{"groups":[{"chars":[{"char":"你","components":[["M 204 -856C 169 -661 90 -460 11 -332L 22 -325C 165 -426 276 -572 355 -778C 378 -777 391 -786 396 -799Z",[0.328,0.656]],["M 139 -519L 139 92L 166 92C 223 92 282 62 284 52L 284 -524C 304 -528 312 -535 315 -544L 192 -589Z",[0.011,0.778]],["M 420 -469C 397 -331 349 -185 300 -92L 312 -84C 410 -154 493 -259 554 -395C 577 -395 590 -403 594 -416Z",[0.312,0.593]],["M 464 -853C 433 -698 370 -536 308 -435L 319 -427C 437 -503 534 -614 606 -766C 629 -764 643 -772 648 -785Z",[0.336,0.605]],["M 580 -616L 580 -80C 580 -69 575 -64 560 -64C 538 -64 430 -70 430 -70L 430 -57C 483 -47 504 -32 521 -9C 538 13 543 47 547 94C 702 80 723 27 723 -70L 723 -573C 746 -577 756 -586 758 -601Z",[0.061,0.749]],["M 453 -653L 453 -625L 866 -625L 866 -653Z",[-0.772,0.022]],["M 756 -457L 746 -452C 788 -356 831 -240 840 -132C 975 -9 1096 -292 756 -457Z",[-0.194,0.461]],["M 806 -653C 804 -606 796 -528 787 -476L 794 -470C 847 -501 912 -555 950 -595C 972 -596 982 -599 990 -608L 866 -725L 794 -653Z",[0.249,0.392]]],"bbox":{"top":-856,"bottom":94,"left":11,"right":1096},"hadv":1000}],"text":"你","hadv":1000,"breakAfter":true},{"chars":[{"char":"好","components":[["M 309 -612L 321 -612C 301 -339 234 -76 16 82L 25 92C 341 -42 421 -294 455 -560C 478 -564 488 -568 495 -579L 376 -683Z",[0.295,0.74]],["M 395 -612L 20 -612L 29 -584L 395 -584Z",[-0.849,0.012]],["M 73 -302L 52 -284C 162 -219 289 -107 347 -3C 462 72 652 -151 73 -302Z",[-0.561,0.43]],["M 52 -284L 168 -248C 229 -419 296 -700 321 -816L 303 -801C 347 -800 355 -813 358 -826L 186 -856C 172 -739 100 -426 52 -284Z",[0.196,0.754]],["M 830 -758L 412 -758L 421 -730L 830 -730Z",[0.609,0.024]],["M 866 -500L 796 -403L 429 -403L 437 -375L 963 -375C 978 -375 989 -380 992 -391C 946 -435 866 -500 866 -500Z",[0.789,0.085]],["M 780 -556L 604 -571L 604 -71C 604 -61 599 -56 585 -56C 565 -56 465 -62 465 -62L 465 -49C 516 -40 535 -25 551 -3C 566 18 571 51 574 96C 724 83 745 32 745 -63L 745 -529C 768 -532 778 -541 780 -556Z",[0.059,0.749]],["M 771 -758L 783 -758C 760 -705 709 -595 670 -535L 681 -535C 762 -579 863 -655 928 -707C 951 -708 961 -711 969 -720L 846 -830Z",[0.408,0.397]]],"bbox":{"top":-856,"bottom":96,"left":16,"right":992},"hadv":1000}],"text":"好","hadv":1000,"breakAfter":false},{"chars":[{"char":"！","components":[["M 249 8C 299 8 338 -30 338 -78C 338 -126 299 -166 249 -166C 199 -166 160 -126 160 -78C 160 -30 199 8 249 8Z",[0.022,0.0]],["M 234 -249L 265 -249L 289 -379C 328 -552 337 -628 337 -677C 337 -744 298 -777 250 -777C 201 -777 162 -744 162 -677C 162 -628 172 -553 210 -379Z",[-0.003,0.691]]],"bbox":{"top":-777,"bottom":8,"left":160,"right":338},"hadv":1000}],"text":"！","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.hi-img {\n  display:  block;\n}\n\n.hi-img > img {\n  margin: 20px auto;\n  width: 100%;\n}\n</style>\n<div class=\"hi-img\">\n  <img src=\"https://storage.c-3.moe/meow/hi.png\" alt=\"Hi!\">\n</div>\n<p>就这样，起码我还活着呢，故事也要接着进行下去。</p>\n<p>下完雨的晚霞真漂亮，今天找个时间去拍一下。</p>\n","plain":"就这样，起码我还活着呢，故事也要接着进行下去。\n下完雨的晚霞真漂亮，今天找个时间去拍一下。\n"},{"metadata":{"id":"T-minus-12h","lang":"zh-CN","title":"T-12h","tags":["扯淡"],"publish_time":"2017-06-06T12:40:21.814Z","update_time":"2017-06-06T12:40:45.543Z","title_outline":{"groups":[{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714}],"text":"T","hadv":714,"breakAfter":false},{"chars":[{"char":"-","components":[["M 45 -252L 337 -252L 337 -325L 45 -325Z",[-0.751,0.001]]],"bbox":{"top":-325,"bottom":-252,"left":45,"right":337},"hadv":382}],"text":"-","hadv":382,"breakAfter":false},{"chars":[{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463},{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613},{"char":"h","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -445L 263 -459L 263 -656L 266 -817L 253 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -168 103 -51 101 -0Z",[-0.011,0.796]],["M 36 -0L 325 -0L 325 -31L 220 -41L 140 -41L 36 -31Z",[0.862,0.0]],["M 446 -0L 615 -0C 613 -51 612 -165 612 -238L 612 -368C 612 -504 547 -563 449 -563C 366 -563 310 -526 242 -437L 191 -437L 225 -390C 280 -455 334 -488 377 -488C 421 -488 450 -460 450 -383L 450 -238C 450 -165 449 -51 446 -0Z",[-0.132,0.567]],["M 384 -0L 674 -0L 674 -31L 564 -41L 486 -41L 384 -31Z",[-0.86,0.003]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":674},"hadv":700}],"text":"12h","hadv":1776,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>今天飘点毛毛雨，把手里的书都打湿了。</p>\n<p>从某 Top3 大学的北门走出，遇到了附中接待处老师和她女儿。小姑娘一身粉色的连衣裙，转一下，再转一下，裙摆飘得高高的，对我笑咪咪。</p>\n<p>她看着我：“你是二楼实验室的大哥哥吗？”</p>\n<p>“是，”我回答，“不过马上就不是了。”</p>\n<p>让狂欢开始吧。</p>\n","plain":"今天飘点毛毛雨，把手里的书都打湿了。\n从某 Top3 大学的北门走出，遇到了附中接待处老师和她女儿。小姑娘一身粉色的连衣裙，转一下，再转一下，裙摆飘得高高的，对我笑咪咪。\n她看着我：“你是二楼实验室的大哥哥吗？”\n“是，”我回答，“不过马上就不是了。”\n让狂欢开始吧。\n"},{"metadata":{"id":"welcome-to-subway-line-10","lang":"zh-CN","title":"在北京地铁 10 号线上","tags":["扯淡"],"publish_time":"2017-05-21T13:52:48.488Z","update_time":"2017-05-21T13:57:55.522Z","title_outline":{"groups":[{"chars":[{"char":"在","components":[["M 565 -807L 363 -858C 322 -647 215 -367 19 -192L 27 -183C 304 -319 450 -571 527 -784C 553 -786 562 -795 565 -807Z",[0.398,0.676]],["M 818 -747L 737 -644L 43 -644L 51 -616L 935 -616C 950 -616 961 -621 964 -632C 909 -678 818 -747 818 -747Z",[0.835,0.05]],["M 359 -400L 237 -444L 180 -369L 180 92L 208 92C 265 92 325 64 327 54L 327 -380C 346 -384 355 -390 359 -400Z",[0.02,0.712]],["M 835 -98L 758 -1L 335 -1L 343 27L 944 27C 959 27 971 22 974 11C 921 -33 835 -98 835 -98Z",[0.861,0.059]],["M 784 -426L 713 -336L 360 -336L 368 -308L 884 -308C 898 -308 910 -313 912 -324C 864 -366 784 -426 784 -426Z",[0.808,0.077]],["M 718 -558L 539 -573L 539 13L 686 13L 686 -532C 710 -536 717 -545 718 -558Z",[0.004,0.743]]],"bbox":{"top":-858,"bottom":92,"left":19,"right":974},"hadv":1000}],"text":"在","hadv":1000,"breakAfter":true},{"chars":[{"char":"北","components":[["M 22 -203L 102 -28C 115 -32 126 -44 130 -58C 253 -157 333 -234 378 -286L 376 -293C 232 -252 81 -215 22 -203Z",[0.49,0.273]],["M 57 -562L 66 -534L 384 -534L 384 -562Z",[-0.763,0.01]],["M 301 -825L 301 92L 329 92C 383 92 443 63 443 51L 443 -779C 471 -783 478 -794 480 -808Z",[0.006,0.839]],["M 541 -824L 541 -67C 541 35 575 60 685 60L 770 60C 930 60 982 32 982 -29C 982 -55 971 -72 934 -90L 929 -237L 920 -237C 900 -175 880 -117 866 -97C 857 -86 847 -83 836 -82C 824 -82 805 -81 785 -81L 721 -81C 694 -81 685 -89 685 -111L 685 -777C 710 -781 719 -792 720 -805Z",[-0.158,0.643]],["M 813 -678C 781 -603 716 -483 638 -390L 643 -382C 771 -436 877 -504 942 -563C 963 -554 980 -557 988 -569Z",[0.429,0.404]]],"bbox":{"top":-825,"bottom":92,"left":22,"right":988},"hadv":1000}],"text":"北","hadv":1000,"breakAfter":true},{"chars":[{"char":"京","components":[["M 401 -160L 238 -256C 200 -168 115 -40 22 40L 29 49C 165 6 286 -73 362 -148C 386 -144 396 -151 401 -160Z",[0.48,0.416]],["M 833 -796L 756 -696L 34 -696L 42 -668L 944 -668C 959 -668 970 -673 973 -684C 921 -729 833 -796 833 -796Z",[0.905,0.037]],["M 348 -299L 348 -529L 738 -529L 738 -557L 356 -557L 197 -617L 197 -253L 218 -253C 280 -253 348 -285 348 -299Z",[0.338,0.184]],["M 728 -344L 253 -344L 253 -316L 728 -316Z",[0.888,0.003]],["M 580 -69L 580 -344L 427 -344L 427 -73C 427 -63 423 -56 408 -56C 387 -56 288 -62 288 -62L 288 -51C 342 -41 361 -25 375 -5C 391 16 395 49 398 95C 556 85 580 25 580 -69Z",[0.091,0.571]],["M 368 -860L 362 -855C 404 -818 449 -756 466 -697C 610 -621 704 -892 368 -860Z",[-0.268,0.212]],["M 628 -228L 620 -222C 684 -158 760 -64 797 22C 946 102 1029 -183 628 -228Z",[-0.39,0.371]],["M 644 -557L 654 -557L 654 -262L 681 -262C 732 -262 806 -291 807 -299L 807 -505C 828 -509 840 -519 846 -527L 710 -629Z",[0.025,0.522]]],"bbox":{"top":-892,"bottom":102,"left":22,"right":1029},"hadv":1000}],"text":"京","hadv":1000,"breakAfter":true},{"chars":[{"char":"地","components":[["M 14 -156L 82 3C 95 -2 105 -14 109 -28C 237 -122 323 -201 378 -257L 375 -265C 237 -215 82 -171 14 -156Z",[0.552,0.311]],["M 31 -539L 39 -511L 373 -511C 386 -511 396 -516 399 -527C 369 -569 307 -637 307 -637L 253 -539Z",[0.845,0.086]],["M 126 -831L 126 -140L 261 -184L 261 -787C 289 -792 296 -802 298 -816Z",[0.01,0.795]],["M 770 -619L 280 -444L 298 -421L 806 -602L 796 -628Z",[0.752,0.312]],["M 383 -767L 383 -74C 383 38 434 59 567 59L 698 59C 924 59 982 34 982 -32C 982 -57 968 -74 925 -90L 921 -225L 911 -225C 886 -159 864 -113 849 -93C 838 -83 825 -79 808 -78C 787 -76 751 -75 711 -75L 583 -75C 537 -75 521 -84 521 -113L 521 -721C 546 -725 555 -736 557 -749Z",[-0.244,0.47]],["M 584 -851L 584 -122L 608 -122C 659 -122 717 -150 717 -162L 717 -807C 744 -811 751 -821 753 -835Z",[0.011,0.801]],["M 789 -622C 787 -409 784 -336 768 -320C 763 -315 757 -312 745 -312C 730 -312 708 -312 697 -314L 697 -302C 723 -293 732 -282 742 -264C 751 -247 752 -216 752 -174C 800 -174 838 -185 867 -209C 914 -246 921 -305 924 -572C 944 -575 956 -582 963 -590L 847 -687L 778 -622Z",[0.109,0.666]]],"bbox":{"top":-851,"bottom":59,"left":14,"right":982},"hadv":1000}],"text":"地","hadv":1000,"breakAfter":true},{"chars":[{"char":"铁","components":[["M 272 -774C 299 -776 309 -785 313 -798L 134 -854C 121 -751 71 -568 12 -465L 20 -459C 129 -538 227 -667 272 -774Z",[0.311,0.586]],["M 333 -407L 276 -324L 31 -324L 39 -296L 407 -296C 421 -296 431 -301 434 -312C 398 -350 333 -407 333 -407Z",[0.8,0.075]],["M 310 -611L 252 -527L 86 -527L 94 -499L 387 -499C 401 -499 412 -504 414 -515C 376 -553 310 -611 310 -611Z",[0.863,0.079]],["M 262 -526L 161 -526L 161 -119C 161 -96 154 -85 113 -57L 216 77C 243 57 271 3 244 -76L 185 -24L 295 -60L 295 -506Z",[0.031,0.758]],["M 330 -773L 272 -692L 134 -692L 142 -664L 407 -664C 421 -664 431 -669 434 -680C 396 -717 330 -773 330 -773Z",[0.662,0.102]],["M 144 -65L 218 67C 318 -33 394 -130 430 -178L 426 -186C 311 -133 193 -83 144 -65Z",[0.472,0.362]],["M 788 -839L 615 -855C 615 -415 645 -133 346 78L 355 92C 771 -79 746 -367 751 -810C 775 -814 785 -823 788 -839Z",[0.17,0.784]],["M 634 -733L 471 -772C 461 -650 431 -520 396 -432L 409 -425C 489 -490 552 -588 595 -709C 618 -710 630 -719 634 -733Z",[0.27,0.624]],["M 863 -445L 796 -357L 415 -357L 423 -329L 955 -329C 969 -329 980 -334 983 -345C 938 -386 863 -445 863 -445Z",[0.841,0.067]],["M 829 -689L 764 -602L 509 -602L 509 -574L 919 -574C 933 -574 944 -579 947 -590C 903 -630 829 -689 829 -689Z",[0.9,0.069]],["M 741 -354L 727 -351C 739 -214 778 -7 889 88C 895 9 929 -28 992 -43L 992 -56C 838 -120 759 -238 741 -354Z",[-0.297,0.525]]],"bbox":{"top":-855,"bottom":92,"left":12,"right":992},"hadv":1000}],"text":"铁","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"1","components":[["M 160 -0L 331 -0C 329 -79 327 -160 327 -237L 327 -586L 331 -749L 316 -759L 46 -698L 46 -662L 163 -676L 163 -237C 163 -160 162 -79 160 -0Z",[-0.023,0.754]],["M 48 -0L 434 3L 434 -27L 323 -51L 171 -51L 48 -31Z",[-0.863,0.005]]],"bbox":{"top":-759,"bottom":3,"left":46,"right":434},"hadv":463},{"char":"0","components":[["M 306 17C 444 17 570 -102 570 -375C 570 -646 444 -764 306 -764C 167 -764 43 -646 43 -375C 43 -102 167 17 306 17ZM 306 -18C 246 -18 196 -94 196 -375C 196 -654 246 -729 306 -729C 365 -729 417 -653 417 -375C 417 -95 365 -18 306 -18Z",[-0.0,0.201]]],"bbox":{"top":-764,"bottom":17,"left":43,"right":570},"hadv":612}],"text":"10","hadv":1075,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"号","components":[["M 855 -516L 785 -420L 30 -420L 38 -392L 951 -392C 966 -392 977 -397 980 -408C 934 -451 855 -516 855 -516Z",[0.898,0.038]],["M 427 -406L 264 -406C 253 -371 219 -288 196 -247L 242 -283C 216 -277 185 -261 168 -244L 302 -168L 352 -227L 345 -227C 367 -271 407 -361 427 -406Z",[0.233,0.332]],["M 344 -499L 344 -759L 750 -759L 750 -787L 352 -787L 199 -845L 199 -454L 219 -454C 279 -454 344 -486 344 -499Z",[0.322,0.207]],["M 761 -255L 289 -255L 278 -227L 761 -227Z",[-0.956,0.004]],["M 746 -564L 285 -564L 285 -536L 746 -536Z",[0.801,0.009]],["M 695 -255L 705 -255C 690 -153 665 -72 638 -55C 628 -48 618 -47 601 -47C 577 -47 482 -52 419 -57L 418 -47C 475 -36 524 -18 547 4C 569 24 574 57 573 93C 648 94 691 84 728 62C 788 26 823 -68 845 -202C 866 -205 879 -211 886 -220L 766 -320Z",[0.305,0.41]],["M 651 -787L 661 -787L 661 -480L 686 -480C 733 -480 806 -503 808 -510L 808 -736C 829 -740 841 -749 847 -757L 714 -857Z",[0.043,0.533]]],"bbox":{"top":-857,"bottom":94,"left":30,"right":980},"hadv":1000}],"text":"号","hadv":1000,"breakAfter":true},{"chars":[{"char":"线","components":[["M 352 -779L 182 -848C 165 -766 98 -615 50 -572C 39 -564 14 -558 14 -558L 76 -409C 106 -422 127 -468 131 -541L 65 -541L 66 -529C 153 -580 270 -692 327 -773L 294 -766C 328 -756 347 -765 352 -779Z",[0.385,0.613]],["M 459 -584L 305 -677C 268 -572 144 -385 62 -328C 49 -320 20 -313 20 -313L 82 -165C 111 -178 133 -221 138 -296L 75 -296L 75 -284C 198 -350 363 -492 431 -584L 398 -579C 432 -564 452 -572 459 -584Z",[0.497,0.605]],["M 26 -110L 88 55C 101 51 112 40 117 26C 273 -60 375 -134 444 -189L 442 -198C 283 -156 104 -121 26 -110Z",[0.616,0.256]],["M 34 -549L 78 -424C 187 -468 281 -515 328 -540L 328 -552C 207 -549 86 -548 34 -549Z",[0.688,0.112]],["M 42 -308L 86 -174C 234 -231 353 -288 416 -321L 416 -332C 261 -320 106 -310 42 -308Z",[0.653,0.15]],["M 949 -305L 785 -398C 656 -165 482 -34 272 58L 277 71C 529 17 727 -82 903 -294C 928 -290 941 -293 949 -305Z",[0.629,0.493]],["M 841 -519L 776 -418L 365 -374L 375 -347L 962 -410C 975 -411 987 -419 988 -430C 932 -468 841 -519 841 -519Z",[0.827,0.157]],["M 797 -684L 731 -585L 404 -554L 414 -527L 914 -575C 928 -576 939 -583 941 -595C 885 -633 797 -684 797 -684Z",[0.738,0.157]],["M 685 -837L 508 -854C 509 -497 540 -176 777 35C 827 78 923 125 977 72C 996 53 991 17 951 -51L 977 -229L 968 -232C 945 -187 912 -129 894 -102C 883 -85 874 -85 859 -99C 668 -248 644 -528 650 -808C 676 -812 684 -824 685 -837Z",[-0.299,0.726]],["M 661 -820L 654 -815C 686 -780 721 -723 731 -671C 853 -594 954 -822 661 -820Z",[-0.136,0.161]]],"bbox":{"top":-854,"bottom":125,"left":14,"right":996},"hadv":1000}],"text":"线","hadv":1000,"breakAfter":true},{"chars":[{"char":"上","components":[["M 25 13L 33 41L 947 41C 962 41 974 36 977 25C 920 -23 826 -94 826 -94L 742 13Z",[0.911,0.043]],["M 386 -839L 386 29L 546 29L 546 -792C 574 -796 581 -806 583 -821Z",[0.004,0.811]],["M 477 -453L 477 -425L 876 -425C 891 -425 902 -430 905 -441C 850 -489 758 -559 758 -559L 676 -453Z",[0.76,0.075]]],"bbox":{"top":-839,"bottom":41,"left":25,"right":977},"hadv":1000}],"text":"上","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>想起个故事。</p>\n<p>忘了什么时候，大概两三年以前吧，就在这个季节，坐地铁 10 号线，并秉持着孩童的心态，在第一节车厢透过玻璃看驾驶舱的面板。话说现在还能看到驾驶舱的也就只有 10 号和 13 号了吧。</p>\n<p>北土城站，一个看上去没有双腿的乞丐和他有双腿的儿子上了车，差不多一边高，拉着站着的人的裤腿，行行好，行行好。</p>\n<p>对上孩子的眼睛了。摸了摸兜里，一块硬币叮叮当当响，但天气热，我想吃冰淇淋。为保公平，我蹲下来，问那个孩子：“你卖什么东西吗，或是能给我表演什么？你会做什么呢？”</p>\n<p>孩子玩弄手里的玩具车，别开视线，说：“我会杀人，杀人。”</p>\n<p>我起身了。孩子父亲转过头拉我的裤腿，一次，两次，然后冲着后面的车厢爬去，任孩子跟在他身后。</p>\n<p>故事讲完了。当时我还小，于是会蹲下和孩子说话，也会在事后轻易忘记。现在做不到了，也就只能安静的盯着驾驶舱里蹦蹦跳跳的数字和往身后飞去的隧道里的灯。</p>\n","plain":"想起个故事。\n忘了什么时候，大概两三年以前吧，就在这个季节，坐地铁 10 号线，并秉持着孩童的心态，在第一节车厢透过玻璃看驾驶舱的面板。话说现在还能看到驾驶舱的也就只有 10 号和 13 号了吧。\n北土城站，一个看上去没有双腿的乞丐和他有双腿的儿子上了车，差不多一边高，拉着站着的人的裤腿，行行好，行行好。\n对上孩子的眼睛了。摸了摸兜里，一块硬币叮叮当当响，但天气热，我想吃冰淇淋。为保公平，我蹲下来，问那个孩子：“你卖什么东西吗，或是能给我表演什么？你会做什么呢？”\n孩子玩弄手里的玩具车，别开视线，说：“我会杀人，杀人。”\n我起身了。孩子父亲转过头拉我的裤腿，一次，两次，然后冲着后面的车厢爬去，任孩子跟在他身后。\n故事讲完了。当时我还小，于是会蹲下和孩子说话，也会在事后轻易忘记。现在做不到了，也就只能安静的盯着驾驶舱里蹦蹦跳跳的数字和往身后飞去的隧道里的灯。\n"},{"metadata":{"id":"fk-wd","lang":"zh-CN","title":"干 TM 西部数据","tags":["扯淡"],"publish_time":"2017-04-23T08:56:41.187Z","update_time":"2017-04-23T08:56:41.187Z","title_outline":{"groups":[{"chars":[{"char":"干","components":[["M 28 -428L 36 -400L 945 -400C 960 -400 972 -405 975 -416C 919 -463 827 -532 827 -532L 745 -428Z",[0.931,0.04]],["M 88 -743L 96 -715L 889 -715C 904 -715 915 -720 918 -731C 864 -777 773 -845 773 -845L 693 -743Z",[0.889,0.037]],["M 419 -743L 419 96L 448 96C 528 96 574 64 574 55L 574 -743Z",[0.005,0.809]]],"bbox":{"top":-845,"bottom":96,"left":28,"right":975},"hadv":1000}],"text":"干","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"T","components":[["M 23 -531L 82 -531L 143 -747L 62 -708L 651 -708L 571 -747L 633 -531L 691 -531L 687 -747L 27 -747Z",[0.741,0.005]],["M 169 -0L 546 -0L 546 -34L 378 -50L 332 -50L 169 -34Z",[-0.875,0.0]],["M 269 -0L 445 -0C 442 -117 442 -235 442 -352L 442 -395C 442 -514 442 -632 445 -747L 269 -747C 272 -630 272 -513 272 -395L 272 -351C 272 -232 272 -114 269 -0Z",[-0.001,0.771]]],"bbox":{"top":-747,"bottom":0,"left":23,"right":691},"hadv":714},{"char":"M","components":[["M 24 -0L 295 -0L 295 -34L 172 -50L 148 -50L 24 -34Z",[0.827,0.0]],["M 40 -713L 182 -698L 198 -698L 198 -747L 40 -747Z",[-0.41,0.041]],["M 133 -0L 182 -0L 182 -346L 176 -747L 137 -747Z",[-0.002,0.939]],["M 424 -0L 476 -0L 722 -665L 735 -700L 767 -700L 767 -747L 709 -747L 504 -198L 497 -179L 525 -179L 313 -747L 150 -747L 150 -700L 157 -700Z",[-0.102,0.36]],["M 621 -0L 973 -0L 973 -34L 811 -50L 782 -50L 621 -34Z",[-0.866,0.001]],["M 708 -0L 884 -0C 880 -114 880 -232 880 -351L 880 -395C 880 -513 880 -631 884 -747L 716 -747L 712 -327C 710 -235 712 -117 708 -0Z",[0.003,0.779]],["M 795 -698L 812 -698L 970 -713L 970 -747L 795 -747Z",[0.705,0.101]]],"bbox":{"top":-747,"bottom":0,"left":24,"right":973},"hadv":1014}],"text":"TM","hadv":1728,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"西","components":[["M 837 -856L 758 -757L 26 -757L 34 -729L 953 -729C 968 -729 980 -734 983 -745C 928 -790 837 -856 837 -856Z",[0.816,0.043]],["M 91 -606L 91 80L 117 80C 189 80 232 54 232 45L 232 -522L 769 -522L 769 76L 795 76C 870 76 917 47 917 40L 917 -509C 941 -514 952 -522 959 -532L 835 -630L 764 -550L 243 -550ZM 825 -44L 173 -44L 173 -16L 825 -16Z",[0.379,0.013]],["M 461 -529L 461 -757L 326 -757L 326 -529C 326 -397 320 -259 232 -152L 239 -144C 444 -241 461 -398 461 -529Z",[0.105,0.747]],["M 667 -757L 534 -757L 534 -305C 534 -224 547 -197 635 -197L 686 -197C 794 -197 835 -219 835 -273C 835 -297 825 -315 794 -329L 789 -332L 780 -332C 772 -330 761 -328 753 -327C 746 -326 733 -325 727 -325C 720 -325 711 -325 704 -325L 682 -325C 670 -325 667 -329 667 -343L 667 -719C 667 -730 667 -744 667 -757Z",[-0.13,0.618]]],"bbox":{"top":-856,"bottom":80,"left":26,"right":983},"hadv":1000}],"text":"西","hadv":1000,"breakAfter":true},{"chars":[{"char":"部","components":[["M 476 -519L 405 -427L 29 -427L 37 -399L 574 -399C 589 -399 600 -404 602 -415C 555 -457 476 -519 476 -519Z",[0.825,0.066]],["M 464 -790L 396 -701L 43 -701L 51 -673L 559 -673C 573 -673 585 -678 587 -689C 541 -730 464 -790 464 -790Z",[0.69,0.069]],["M 107 -346L 107 70L 131 70C 197 70 237 49 237 40L 237 -265L 364 -265L 364 49L 389 49C 459 49 501 26 501 21L 501 -256C 524 -260 534 -266 540 -275L 423 -364L 360 -293L 248 -293ZM 429 -48L 169 -48L 169 -20L 429 -20Z",[0.166,0.04]],["M 127 -654L 117 -650C 140 -600 156 -531 150 -469C 248 -369 384 -566 127 -654Z",[-0.173,0.396]],["M 203 -848L 196 -843C 217 -815 234 -767 231 -722C 344 -628 485 -837 203 -848Z",[-0.041,0.222]],["M 530 -620L 356 -672C 353 -615 337 -493 321 -412L 329 -408C 392 -466 459 -550 492 -599C 516 -598 528 -609 530 -620Z",[0.238,0.441]],["M 590 -827L 590 97L 615 97C 686 97 727 65 727 55L 727 -758L 741 -758Z",[-0.001,0.845]],["M 871 -758L 668 -758L 668 -730L 871 -730Z",[-0.17,0.046]],["M 792 -758L 805 -758C 796 -676 769 -530 747 -452C 810 -387 836 -309 836 -237C 836 -208 828 -193 813 -184C 806 -180 800 -179 790 -179C 776 -179 738 -179 716 -179L 716 -168C 743 -161 759 -150 768 -136C 778 -118 784 -63 784 -23C 919 -24 966 -91 965 -194C 965 -284 908 -391 773 -455C 837 -521 908 -625 950 -690C 975 -691 988 -695 996 -705L 863 -826Z",[0.007,0.774]]],"bbox":{"top":-848,"bottom":97,"left":29,"right":996},"hadv":1000}],"text":"部","hadv":1000,"breakAfter":true},{"chars":[{"char":"数","components":[["M 325 -617L 325 -633L 185 -633C 155 -544 99 -451 22 -388L 31 -375C 162 -430 270 -510 325 -617Z",[0.455,0.499]],["M 372 -298L 384 -298C 342 -125 227 6 27 79L 33 92C 290 45 441 -73 513 -250C 536 -253 545 -256 552 -266L 440 -363Z",[0.509,0.552]],["M 475 -715L 420 -638L 30 -638L 38 -610L 547 -610C 561 -610 571 -615 573 -626C 537 -662 475 -715 475 -715Z",[0.723,0.062]],["M 430 -298L 36 -298L 45 -270L 430 -270Z",[-0.899,0.002]],["M 68 -820L 59 -815C 78 -779 97 -724 98 -675C 189 -594 306 -767 68 -820Z",[-0.152,0.335]],["M 83 -156L 69 -134C 179 -113 331 -49 400 21C 517 60 612 -200 83 -156Z",[-0.666,0.235]],["M 69 -134L 188 -120C 231 -187 288 -298 315 -352L 286 -340C 334 -330 346 -341 352 -353L 202 -406C 181 -346 111 -198 69 -134Z",[0.318,0.507]],["M 386 -841L 223 -856L 223 -391L 246 -391C 295 -391 353 -414 353 -423L 353 -816C 377 -820 384 -829 386 -841Z",[0.015,0.71]],["M 341 -596L 333 -591C 364 -552 400 -493 413 -439C 527 -366 622 -578 341 -596Z",[-0.192,0.264]],["M 544 -780L 403 -824C 394 -767 383 -702 374 -662L 388 -655C 426 -681 470 -721 506 -759C 527 -759 540 -768 544 -780Z",[0.353,0.34]],["M 919 -626L 762 -626C 755 -335 676 -79 377 85L 382 94C 788 -23 893 -295 919 -626Z",[0.354,0.687]],["M 793 -811L 602 -853C 594 -670 557 -469 508 -332L 520 -325C 634 -434 707 -588 754 -787C 777 -788 789 -798 793 -811Z",[0.223,0.697]],["M 598 -610L 587 -589C 613 -280 676 -39 861 95C 879 30 917 -9 985 -24L 988 -34C 761 -137 639 -324 598 -610Z",[-0.372,0.638]],["M 868 -719L 798 -626L 618 -626L 618 -598L 964 -598C 979 -598 990 -603 993 -614C 946 -656 868 -719 868 -719Z",[0.635,0.121]]],"bbox":{"top":-856,"bottom":95,"left":22,"right":993},"hadv":1000}],"text":"数","hadv":1000,"breakAfter":true},{"chars":[{"char":"据","components":[["M 13 -379L 66 -220C 79 -224 90 -235 94 -249C 230 -336 324 -408 381 -455L 379 -464C 230 -426 72 -390 13 -379Z",[0.602,0.278]],["M 129 -856L 129 -67C 129 -56 125 -52 111 -52C 93 -52 16 -57 16 -57L 16 -44C 59 -35 75 -21 88 -0C 100 20 104 52 106 97C 247 84 265 35 265 -58L 265 -811C 290 -815 300 -825 302 -840Z",[0.028,0.841]],["M 26 -614L 34 -586L 370 -586C 384 -586 394 -591 396 -602C 368 -643 309 -711 309 -711L 257 -614Z",[0.674,0.051]],["M 377 -771L 377 -498C 377 -305 369 -91 266 79L 276 85C 500 -69 512 -312 512 -499L 512 -771L 532 -771L 377 -824L 377 -781Z",[0.086,0.819]],["M 463 -407L 463 -379L 951 -379C 966 -379 977 -384 979 -395C 935 -437 859 -499 859 -499L 793 -407Z",[0.888,0.05]],["M 466 -771L 466 -743L 870 -743L 870 -771Z",[-0.647,0.032]],["M 466 -585L 466 -557L 870 -557L 870 -585Z",[-0.729,0.029]],["M 477 -213L 477 95L 496 95C 551 95 610 67 610 55L 610 -185L 850 -185L 850 -213L 615 -213L 477 -266Z",[0.162,0.304]],["M 546 -0L 546 28L 859 28L 859 -0Z",[0.911,0.001]],["M 630 -550L 630 -208L 765 -208L 765 -516C 783 -519 788 -526 789 -536Z",[0.02,0.588]],["M 792 -213L 792 90L 816 90C 860 90 929 68 930 61L 930 -163C 951 -167 964 -176 970 -184L 842 -280L 782 -213Z",[0.012,0.594]],["M 795 -771L 795 -539L 819 -539C 865 -539 932 -565 932 -574L 932 -724C 951 -728 963 -736 968 -743L 845 -835L 785 -771Z",[-0.03,0.432]]],"bbox":{"top":-856,"bottom":97,"left":13,"right":979},"hadv":1000}],"text":"据","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>今天把 WD 硬盘插上，直接 Fail 了。已经坏了两个 WD 的硬盘了，一个 Element，一个 Passport，Element 还被砸了下，这次这个 Passport 连动都没动，放着半个月插上就坏了，无话可说。</p>\n<p>有咔咔的响声，自己拆了下，没有划痕，读写头也没卡住，可能是读写头坏了。看考完有没有时间去找人修一下吧，还是有不少东西的，所有的照片，之前的稿子之类的。</p>\n<p>我以后一不买西部数据的硬盘，二不买 HDD，气死我了。</p>\n","plain":"今天把 WD 硬盘插上，直接 Fail 了。已经坏了两个 WD 的硬盘了，一个 Element，一个 Passport，Element 还被砸了下，这次这个 Passport 连动都没动，放着半个月插上就坏了，无话可说。\n有咔咔的响声，自己拆了下，没有划痕，读写头也没卡住，可能是读写头坏了。看考完有没有时间去找人修一下吧，还是有不少东西的，所有的照片，之前的稿子之类的。\n我以后一不买西部数据的硬盘，二不买 HDD，气死我了。\n"},{"metadata":{"id":"plot-of-inside","lang":"zh-CN","title":"关于 INSIDE 的剧情","tags":["扯淡"],"publish_time":"2017-04-03T12:31:25.941Z","update_time":"2017-04-04T11:38:44.654Z","title_outline":{"groups":[{"chars":[{"char":"关","components":[["M 556 -431L 556 -600L 396 -600L 396 -430C 396 -249 345 -64 22 85L 25 93C 509 -11 555 -251 556 -431Z",[0.303,0.635]],["M 825 -459L 745 -359L 32 -359L 40 -331L 941 -331C 956 -331 968 -336 971 -347C 916 -392 825 -459 825 -459Z",[0.894,0.043]],["M 774 -702L 697 -607L 96 -607L 104 -579L 884 -579C 899 -579 911 -584 914 -595C 861 -639 774 -702 774 -702Z",[0.88,0.047]],["M 221 -848L 214 -843C 252 -790 287 -716 296 -645C 428 -545 555 -802 221 -848Z",[-0.216,0.333]],["M 551 -356L 541 -352C 590 -121 680 12 857 92C 874 17 918 -34 975 -50L 977 -62C 796 -95 622 -193 551 -356Z",[-0.481,0.403]],["M 807 -798L 614 -855C 602 -778 575 -665 547 -589L 557 -589C 637 -645 720 -723 769 -779C 792 -778 803 -786 807 -798Z",[0.283,0.406]]],"bbox":{"top":-855,"bottom":93,"left":22,"right":977},"hadv":1000}],"text":"关","hadv":1000,"breakAfter":true},{"chars":[{"char":"于","components":[["M 26 -449L 34 -421L 946 -421C 961 -421 973 -426 975 -437C 920 -483 829 -550 829 -550L 748 -449Z",[0.913,0.041]],["M 109 -745L 117 -717L 875 -717C 890 -717 901 -722 904 -733C 850 -778 761 -844 761 -844L 682 -745Z",[0.9,0.042]],["M 426 -745L 426 -90C 426 -78 420 -70 404 -70C 375 -70 237 -78 237 -78L 237 -66C 305 -55 330 -38 350 -16C 372 7 380 43 382 93C 552 82 579 13 579 -85L 579 -745Z",[0.058,0.773]]],"bbox":{"top":-844,"bottom":93,"left":26,"right":975},"hadv":1000}],"text":"于","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"I","components":[["M 41 -0L 395 -0L 395 -34L 233 -50L 202 -50L 41 -34Z",[-0.868,0.0]],["M 41 -713L 202 -698L 233 -698L 395 -713L 395 -747L 41 -747Z",[-0.902,0.008]],["M 130 -0L 307 -0C 304 -117 304 -235 304 -352L 304 -395C 304 -514 304 -632 307 -747L 130 -747C 134 -630 134 -513 134 -395L 134 -351C 134 -232 134 -114 130 -0Z",[-0.0,0.771]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":395},"hadv":437},{"char":"D","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -393C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -393L 133 -360C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 351 -0C 603 -0 756 -142 756 -376C 756 -606 613 -747 368 -747L 218 -747L 218 -709L 353 -709C 496 -709 582 -593 582 -374C 582 -162 496 -37 349 -37L 218 -37Z",[0.005,0.459]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":756},"hadv":799},{"char":"E","components":[["M 41 -0L 218 -0L 218 -50L 202 -50L 41 -34Z",[0.751,0.039]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 634 -0L 632 -207L 576 -207L 519 -1L 605 -39L 218 -39Z",[0.604,0.185]],["M 218 -363L 467 -363L 467 -399L 218 -399Z",[-0.86,0.001]],["M 554 -548L 612 -548L 613 -747L 218 -747L 218 -708L 583 -708L 499 -747Z",[-0.58,0.193]],["M 454 -263L 504 -263L 504 -505L 454 -505L 438 -395L 438 -374Z",[0.007,0.742]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":634},"hadv":674}],"text":"INSIDE","hadv":3784,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"剧","components":[["M 87 -799L 87 -497C 87 -303 86 -83 11 90L 21 97C 210 -66 215 -311 215 -498L 215 -789L 235 -789L 87 -840Z",[0.062,0.841]],["M 517 -505L 455 -419L 158 -419L 166 -391L 601 -391C 615 -391 626 -396 629 -407C 588 -446 517 -505 517 -505Z",[0.783,0.076]],["M 509 -610L 163 -610L 163 -582L 509 -582Z",[0.668,0.02]],["M 509 -789L 163 -789L 163 -761L 509 -761Z",[0.648,0.021]],["M 188 -308L 188 96L 210 96C 273 96 312 76 312 67L 312 -230L 453 -230L 453 81L 476 81C 543 81 583 60 583 54L 583 -221C 605 -225 615 -232 621 -241L 509 -325L 449 -258L 322 -258ZM 515 -15L 274 -15L 274 13L 515 13Z",[0.191,0.032]],["M 472 -551L 320 -564L 320 -245L 443 -245L 443 -528C 464 -531 470 -539 472 -551Z",[0.017,0.599]],["M 453 -789L 463 -789L 463 -532L 485 -532C 525 -532 588 -553 589 -560L 589 -743C 608 -747 620 -755 625 -762L 509 -849Z",[0.037,0.555]],["M 790 -723L 637 -737L 637 -142L 658 -142C 703 -142 754 -164 754 -174L 754 -695C 781 -699 788 -709 790 -723Z",[0.017,0.774]],["M 971 -837L 805 -853L 805 -66C 805 -54 800 -49 785 -49C 764 -49 667 -55 667 -55L 667 -42C 716 -33 736 -19 751 1C 766 21 771 52 774 94C 916 81 935 33 935 -56L 935 -809C 960 -813 969 -822 971 -837Z",[0.027,0.865]]],"bbox":{"top":-853,"bottom":97,"left":11,"right":971},"hadv":1000}],"text":"剧","hadv":1000,"breakAfter":true},{"chars":[{"char":"情","components":[["M 85 -675C 92 -605 66 -525 41 -494C 17 -473 6 -443 22 -417C 42 -388 89 -394 110 -425C 139 -469 147 -559 100 -675Z",[0.15,0.63]],["M 149 -854L 149 95L 176 95C 227 95 283 69 283 58L 283 -809C 310 -813 318 -823 320 -837Z",[0.005,0.856]],["M 286 -688L 275 -683C 294 -643 311 -582 309 -530C 383 -455 486 -606 286 -688Z",[-0.097,0.45]],["M 336 -497L 344 -469L 954 -469C 968 -469 979 -474 982 -485C 937 -525 863 -583 863 -583L 797 -497Z",[0.874,0.027]],["M 362 -730L 370 -702L 943 -702C 957 -702 968 -707 971 -718C 926 -758 851 -816 851 -816L 785 -730Z",[0.777,0.031]],["M 403 -618L 411 -590L 915 -590C 929 -590 940 -595 943 -606C 901 -644 831 -698 831 -698L 770 -618Z",[0.88,0.049]],["M 415 -402L 415 93L 436 93C 495 93 554 61 554 47L 554 -374L 824 -374L 824 -402L 560 -402L 415 -459Z",[0.107,0.538]],["M 491 -292L 491 -264L 813 -264L 813 -292Z",[-0.914,0.0]],["M 491 -176L 491 -148L 813 -148L 813 -176Z",[0.914,0.0]],["M 575 -847L 575 -486L 715 -486L 715 -807C 739 -811 746 -820 747 -833Z",[0.043,0.58]],["M 755 -402L 755 -75C 755 -63 751 -57 737 -57C 718 -57 637 -61 637 -61L 637 -49C 682 -40 698 -25 712 -4C 725 16 729 49 731 95C 876 82 896 31 896 -59L 896 -351C 917 -356 929 -365 936 -373L 806 -471L 745 -402Z",[0.071,0.664]]],"bbox":{"top":-854,"bottom":95,"left":6,"right":982},"hadv":1000}],"text":"情","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>嗯，这<strong>显然</strong>有剧透。</p>\n<p>清明假期把 INSIDE 通关了。简单说下我的理解，恩。以下假设游戏中的一切细节都是为剧情设计的，而不是为了操作方便或者只是彩蛋。</p>\n<p>为了自圆其说，我只能假设 INSIDE 是个 Meta-game，不然隐藏部分是没有办法解释的。</p>\n<h2>背景</h2>\n<p>大概，人类遭遇了一个大灾难，人口大幅下降，为了维护<del>世界和平</del>社会稳定，高层给科学家拨款建立了一个设施，研究如何控制人作为劳动力。科学家搞出了如下成果：</p>\n<ul>\n<li>最初，通过一种寄生虫控制宿主（1区，也就是城乡结合部那块儿）</li>\n<li>后来，可以直接控制特定改造过的人的头盔（2区）</li>\n<li>以及，克隆改造人的罐<del>头</del>子（在两次森林场景中可以看到）</li>\n</ul>\n<p>大部分克隆人是没有自我意识、意愿的，只有基本的反射和控制身体的控制能力（2、4区，摔趴地上的人是可以自己站起来，并且疼的嗷嗷叫的，但是不会因为疼的不行而停止活动）。但是还是会有少量克隆人拥有自我意识，所以负责管理克隆人的工作人员又让科学家设计了一个射杀自由活动克隆人的机器，并派人四处巡逻。</p>\n<p>由于人只能同一时刻控制他人进行同一个动作，所以科学家又搞出来了让人体直接从水中获取营养和氧气的技术（3区、4区），和制造融合人体的技术（4区），造出了那个有超强控制能力的肉球球，插上插头控制劳动力。</p>\n<p>此外，科学家还搞出了：</p>\n<ul>\n<li>从爆炸的冲击波中收集能量（2区，从冲击波的扩散距离和能量来看，很可能是小型核爆）</li>\n<li>反重力，方便保存实验个体，进行试验（4区）</li>\n</ul>\n<p>克隆和精神控制成为了“清洁绿色的劳动力来源”，引得人们带着孩子前来围观（2区，小男孩假装被控制），而管理者和科学家成为了唯二两种职业。</p>\n<p>研究跨越了很长时间，在这个过程中，较低部分的实验室被水淹没了（2区前部，3区）。废弃的实验室中，一部分能够在水中生存的人逃离了束缚，变成流浪的水中萝莉，并不断尝试把不能在水中生存的人转化为同类来扩张。</p>\n<p>肉球球进化控制能力需要不断有新个体加入。高层决策者知道自己在游戏里，希望利用游戏的玩家完成这一计划。</p>\n<h2>故事</h2>\n<p>高层在肉球球的控制网络中秘密加入了一条特别线路（黄线），并在设施各处设置了保险，在肉球球水缸旁的楼缝里安装了总闸。这些特别线路通到玉米地地下的一个密室里，接上了游戏外玩家的电脑，并不断在设施旁放置克隆出来的，由红衣服标记的小男孩，由玩家控制，筛选具有最强<strong>控制能力</strong>大脑的个体，并最终并入肉球球。</p>\n<p>普通管理者当然不知道怎么回事，看见小男孩就要抓，以为是逃出来的有自我意识的克隆人。然而一般而言抓不住，抓住了高层也会重新放一个。</p>\n<p>普通科学家当然也不知道怎么回事，看到小男孩最多有点惊讶，并不会有什么怀疑。恩搞学术的是有这种气息。直到最后发现小男孩跑到水缸里以后才拍着窗子大喊雅蠛蝶。</p>\n<p>只有高层知道怎么回事，会派人对小男孩进行暗中观察（3区里有潜水员在外面看）。</p>\n<p>中途遇到水中萝莉。萝莉总要把小男孩拖下水，并带到有插头的地方转变。然而除了最后一次距离足够近（只有4区有插头，最后一次剧情杀距离四区只有一个场景），小男孩被萝莉插完还剩一口气可以活下去（到了水底才吐出来），其他每次都离得太远了，小男孩早就死了。</p>\n<p>最后小男孩到了肉球球的水缸旁，完成了整个测试，高层已经开始准备让肉球球和小男孩融合（好奇怪）了。肉球球参数不正常，吸引不明真相的科学家和管理者纷纷围观。可以注意到，只有这里和前面从高处透过一个活门掉到地下水里的场景，是打领带的科学家和戴面具的管理者同时出现的，充分说明这是两个阵营。</p>\n<p>小男孩拔开了肉球球的插头，让肉球球的意识不再被系统占据，同时也断开了它和克隆人的连接，为融合做好了准备。肉球球把小男孩融入其中，原本在控制小男孩的玩家转而控制肉球球。最后肉球球从设施逃出，但是事实上只是跑到了另一个设计好的圈套里。这点可以从最后的场景和之前出现的一个沙盘一模一样看出，连非自然的光线和肉球球的落点都一样。过程中科学家抖得不行，但是也是按照高层的计划，一点一点把肉球球勾引到圈套中。</p>\n<p>之后，肉球球被重新放回水缸，科学家又换了一群，不知道过了多少年终于又出现了下一个能够抵达水缸的小男孩，而已经没有任何一个科学家是见过上次逃脱的了。</p>\n<p>不知道在某个小男孩前往水缸的途中，玩家发现了黄色线路的存在，并跟随者线路找到了发射器。发射器被破坏以后，不论多少个小男孩摔死淹死，或是和肉球球融合，发射器都没有恢复工作，只是被重新组装起来。这大概一方面佐证了肉球球逃脱并不是游戏真正结束，也说明了这个计划存在了很长很长时间，大概从设施被水淹之前就开始了。高层也是一届一届换，只是知道黄色线路的存在，而不知道怎么修复它了。</p>\n<p>终于，不知道在多少个小男孩的努力下，所有分散在设施中的保险都被断开，总闸可以被关闭。关闭总闸后，可能是应急，从总闸背后的显示器可以看出，的原先被封死的密室中备用电源启动，密室的安全门开始工作。进入密室中，玩家发现了控制小男孩的头盔，并最终拔开备用电源，关闭了整个系统。</p>\n<p>随后游戏重新开始，保险和总闸被重置，这才是游戏真正的结局和重启。</p>\n<p>为什么高层能够预料到小男孩会一路到达肉球球那里并帮助她逃脱呢？就这个只能用 Meta 解释了，因为这是个 2D-Platformer 解谜游戏，小男孩移动只有两个自由度，竖直方向还有平台和重力限制。况且根据经验，他们也很清楚外面世界玩家先入为主的目的：这个游戏在 Steam 上有反乌托邦的标签，当然是要去解放无意识的劳动力了。</p>\n<p>所以说，如果不去找隐藏剧情，玩家全程被游戏中的高层耍。只有去找隐藏的发射器，才是玩游戏。</p>\n<p>而在这一博弈中，科学家和管理者是高层永远的牺牲品。</p>\n<h2>自由</h2>\n<p>这么看下来，最后获得自由的，只有玩家本身。而科学家和管理者，大概依旧会被蒙在鼓里。反乌托邦，大概说的是那一群人吧。</p>\n<p>至于克隆人，按照这种猜想，他们一开始就没有自我意识，有无自由的概念都难说了。</p>\n<p>所以在那个世界里，只有水中萝莉算是最可爱的灵魂了，谁能说她们去把小男孩溺死不是因为她们角度下的善良呢？也可能是因为孤独罢！我要批评一波 Playdead 给水中萝莉配的阴森 BGM 了。恩水中萝莉还是可爱，这里放两张和小男孩缠绵的图，作为结尾，嘻嘻。</p>\n<style>\n.inside-imgs img {\n  max-width: 100%;\n  margin: 20px auto;\n}\n</style>\n<div class=\"inside-imgs\">\n  <img src=\"https://storage.c-3.moe/meow/INSIDE_1.jpg\">\n  <img src=\"https://storage.c-3.moe/meow/INSIDE_2.jpg\">\n</div>","plain":"嗯，这显然有剧透。\n清明假期把 INSIDE 通关了。简单说下我的理解，恩。以下假设游戏中的一切细节都是为剧情设计的，而不是为了操作方便或者只是彩蛋。\n为了自圆其说，我只能假设 INSIDE 是个 Meta-game，不然隐藏部分是没有办法解释的。\n\n背景\n大概，人类遭遇了一个大灾难，人口大幅下降，为了维护世界和平社会稳定，高层给科学家拨款建立了一个设施，研究如何控制人作为劳动力。科学家搞出了如下成果：\n- 最初，通过一种寄生虫控制宿主（1区，也就是城乡结合部那块儿）\n- 后来，可以直接控制特定改造过的人的头盔（2区）\n- 以及，克隆改造人的罐头子（在两次森林场景中可以看到）\n大部分克隆人是没有自我意识、意愿的，只有基本的反射和控制身体的控制能力（2、4区，摔趴地上的人是可以自己站起来，并且疼的嗷嗷叫的，但是不会因为疼的不行而停止活动）。但是还是会有少量克隆人拥有自我意识，所以负责管理克隆人的工作人员又让科学家设计了一个射杀自由活动克隆人的机器，并派人四处巡逻。\n由于人只能同一时刻控制他人进行同一个动作，所以科学家又搞出来了让人体直接从水中获取营养和氧气的技术（3区、4区），和制造融合人体的技术（4区），造出了那个有超强控制能力的肉球球，插上插头控制劳动力。\n此外，科学家还搞出了：\n- 从爆炸的冲击波中收集能量（2区，从冲击波的扩散距离和能量来看，很可能是小型核爆）\n- 反重力，方便保存实验个体，进行试验（4区）\n克隆和精神控制成为了“清洁绿色的劳动力来源”，引得人们带着孩子前来围观（2区，小男孩假装被控制），而管理者和科学家成为了唯二两种职业。\n研究跨越了很长时间，在这个过程中，较低部分的实验室被水淹没了（2区前部，3区）。废弃的实验室中，一部分能够在水中生存的人逃离了束缚，变成流浪的水中萝莉，并不断尝试把不能在水中生存的人转化为同类来扩张。\n肉球球进化控制能力需要不断有新个体加入。高层决策者知道自己在游戏里，希望利用游戏的玩家完成这一计划。\n\n故事\n高层在肉球球的控制网络中秘密加入了一条特别线路（黄线），并在设施各处设置了保险，在肉球球水缸旁的楼缝里安装了总闸。这些特别线路通到玉米地地下的一个密室里，接上了游戏外玩家的电脑，并不断在设施旁放置克隆出来的，由红衣服标记的小男孩，由玩家控制，筛选具有最强控制能力大脑的个体，并最终并入肉球球。\n普通管理者当然不知道怎么回事，看见小男孩就要抓，以为是逃出来的有自我意识的克隆人。然而一般而言抓不住，抓住了高层也会重新放一个。\n普通科学家当然也不知道怎么回事，看到小男孩最多有点惊讶，并不会有什么怀疑。恩搞学术的是有这种气息。直到最后发现小男孩跑到水缸里以后才拍着窗子大喊雅蠛蝶。\n只有高层知道怎么回事，会派人对小男孩进行暗中观察（3区里有潜水员在外面看）。\n中途遇到水中萝莉。萝莉总要把小男孩拖下水，并带到有插头的地方转变。然而除了最后一次距离足够近（只有4区有插头，最后一次剧情杀距离四区只有一个场景），小男孩被萝莉插完还剩一口气可以活下去（到了水底才吐出来），其他每次都离得太远了，小男孩早就死了。\n最后小男孩到了肉球球的水缸旁，完成了整个测试，高层已经开始准备让肉球球和小男孩融合（好奇怪）了。肉球球参数不正常，吸引不明真相的科学家和管理者纷纷围观。可以注意到，只有这里和前面从高处透过一个活门掉到地下水里的场景，是打领带的科学家和戴面具的管理者同时出现的，充分说明这是两个阵营。\n小男孩拔开了肉球球的插头，让肉球球的意识不再被系统占据，同时也断开了它和克隆人的连接，为融合做好了准备。肉球球把小男孩融入其中，原本在控制小男孩的玩家转而控制肉球球。最后肉球球从设施逃出，但是事实上只是跑到了另一个设计好的圈套里。这点可以从最后的场景和之前出现的一个沙盘一模一样看出，连非自然的光线和肉球球的落点都一样。过程中科学家抖得不行，但是也是按照高层的计划，一点一点把肉球球勾引到圈套中。\n之后，肉球球被重新放回水缸，科学家又换了一群，不知道过了多少年终于又出现了下一个能够抵达水缸的小男孩，而已经没有任何一个科学家是见过上次逃脱的了。\n不知道在某个小男孩前往水缸的途中，玩家发现了黄色线路的存在，并跟随者线路找到了发射器。发射器被破坏以后，不论多少个小男孩摔死淹死，或是和肉球球融合，发射器都没有恢复工作，只是被重新组装起来。这大概一方面佐证了肉球球逃脱并不是游戏真正结束，也说明了这个计划存在了很长很长时间，大概从设施被水淹之前就开始了。高层也是一届一届换，只是知道黄色线路的存在，而不知道怎么修复它了。\n终于，不知道在多少个小男孩的努力下，所有分散在设施中的保险都被断开，总闸可以被关闭。关闭总闸后，可能是应急，从总闸背后的显示器可以看出，的原先被封死的密室中备用电源启动，密室的安全门开始工作。进入密室中，玩家发现了控制小男孩的头盔，并最终拔开备用电源，关闭了整个系统。\n随后游戏重新开始，保险和总闸被重置，这才是游戏真正的结局和重启。\n为什么高层能够预料到小男孩会一路到达肉球球那里并帮助她逃脱呢？就这个只能用 Meta 解释了，因为这是个 2D-Platformer 解谜游戏，小男孩移动只有两个自由度，竖直方向还有平台和重力限制。况且根据经验，他们也很清楚外面世界玩家先入为主的目的：这个游戏在 Steam 上有反乌托邦的标签，当然是要去解放无意识的劳动力了。\n所以说，如果不去找隐藏剧情，玩家全程被游戏中的高层耍。只有去找隐藏的发射器，才是玩游戏。\n而在这一博弈中，科学家和管理者是高层永远的牺牲品。\n\n自由\n这么看下来，最后获得自由的，只有玩家本身。而科学家和管理者，大概依旧会被蒙在鼓里。反乌托邦，大概说的是那一群人吧。\n至于克隆人，按照这种猜想，他们一开始就没有自我意识，有无自由的概念都难说了。\n所以在那个世界里，只有水中萝莉算是最可爱的灵魂了，谁能说她们去把小男孩溺死不是因为她们角度下的善良呢？也可能是因为孤独罢！我要批评一波 Playdead 给水中萝莉配的阴森 BGM 了。恩水中萝莉还是可爱，这里放两张和小男孩缠绵的图，作为结尾，嘻嘻。\n"},{"metadata":{"id":"finished-三日間の幸福","lang":"zh-CN","title":"看完了《三日间的幸福》","tags":["吃书","扯淡"],"publish_time":"2017-03-12T11:27:53.648Z","update_time":"2018-06-21T11:04:19.445Z","title_outline":{"groups":[{"chars":[{"char":"看","components":[["M 372 -739C 330 -511 214 -284 25 -143L 34 -133C 308 -260 463 -465 526 -723L 526 -739Z",[0.422,0.672]],["M 40 -492L 48 -464L 944 -464C 959 -464 971 -469 973 -480C 923 -522 840 -582 840 -582L 767 -492Z",[0.927,0.035]],["M 768 -855C 615 -802 316 -740 85 -712L 87 -697C 332 -691 630 -708 819 -734C 854 -720 878 -720 890 -730Z",[0.763,0.103]],["M 109 -613L 117 -585L 881 -585C 895 -585 906 -590 909 -601C 860 -642 780 -699 780 -699L 710 -613Z",[0.888,0.026]],["M 412 -392L 426 -392L 320 -430L 269 -358L 269 96L 296 96C 369 96 412 65 412 55Z",[0.013,0.715]],["M 337 -392L 337 -364L 760 -364L 760 -392Z",[-0.85,0.013]],["M 338 -271L 338 -243L 761 -243L 761 -271Z",[-0.95,0.005]],["M 338 -142L 338 -114L 761 -114L 761 -142Z",[-0.942,0.001]],["M 338 -9L 338 19L 761 19L 761 -9Z",[0.934,0.0]],["M 697 -392L 697 92L 722 92C 770 92 841 65 842 57L 842 -344C 860 -348 871 -356 877 -363L 750 -460L 687 -392Z",[0.01,0.7]]],"bbox":{"top":-855,"bottom":96,"left":25,"right":973},"hadv":1000}],"text":"看","hadv":1000,"breakAfter":true},{"chars":[{"char":"完","components":[["M 445 -344L 289 -344C 284 -178 270 -34 23 83L 30 95C 395 20 430 -138 445 -344Z",[0.373,0.567]],["M 171 -743L 160 -743C 161 -700 116 -659 85 -643C 43 -624 14 -587 28 -537C 44 -484 110 -466 148 -491C 202 -525 226 -617 171 -743Z",[0.178,0.341]],["M 827 -437L 758 -350L 64 -350L 72 -322L 925 -322C 939 -322 950 -327 953 -338C 906 -378 827 -437 827 -437Z",[0.901,0.038]],["M 843 -680L 162 -680L 162 -652L 843 -652Z",[0.802,0.01]],["M 658 -596L 591 -512L 219 -512L 227 -484L 753 -484C 767 -484 778 -489 781 -500C 734 -540 658 -596 658 -596Z",[0.764,0.073]],["M 397 -852L 392 -847C 431 -814 455 -756 454 -700C 597 -595 739 -871 397 -852Z",[-0.436,0.243]],["M 675 -345L 531 -345L 531 -48C 531 45 555 69 669 69L 763 69C 931 69 978 41 978 -16C 978 -43 970 -60 933 -75L 930 -207L 921 -207C 896 -144 879 -99 866 -81C 858 -70 852 -67 839 -66C 826 -66 803 -65 781 -65L 704 -65C 680 -65 675 -70 675 -84L 675 -309C 675 -318 675 -334 675 -345Z",[-0.31,0.237]],["M 780 -680L 791 -680C 788 -639 779 -569 769 -524L 776 -518C 829 -543 897 -588 937 -622C 958 -623 968 -626 976 -635L 852 -752Z",[0.117,0.149]]],"bbox":{"top":-871,"bottom":95,"left":14,"right":978},"hadv":1000}],"text":"完","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":true},{"chars":[{"char":"《","components":[["M 832 80L 569 -380L 832 -840L 803 -858L 529 -380L 803 98Z",[0.001,0.709]],["M 974 80L 711 -380L 974 -840L 945 -858L 671 -380L 945 98Z",[0.002,0.707]]],"bbox":{"top":-858,"bottom":98,"left":529,"right":974},"hadv":1000}],"text":"《","hadv":1000,"breakAfter":false},{"chars":[{"char":"三","components":[["M 834 -143L 751 -38L 29 -38L 37 -10L 953 -10C 968 -10 980 -15 983 -26C 927 -73 834 -143 834 -143Z",[0.913,0.042]],["M 781 -835L 700 -732L 81 -732L 89 -704L 898 -704C 913 -704 925 -709 928 -720C 873 -766 781 -835 781 -835Z",[0.788,0.056]],["M 713 -500L 634 -401L 146 -401L 154 -373L 825 -373C 840 -373 852 -378 855 -389C 801 -434 713 -500 713 -500Z",[0.893,0.053]]],"bbox":{"top":-835,"bottom":-10,"left":29,"right":983},"hadv":1000}],"text":"三","hadv":1000,"breakAfter":true},{"chars":[{"char":"日","components":[["M 175 -744L 175 90L 200 90C 266 90 328 53 328 34L 328 -716L 776 -716L 776 -744L 337 -744L 175 -808Z",[0.098,0.63]],["M 243 -400L 243 -372L 756 -372L 756 -400Z",[-0.908,0.005]],["M 243 -42L 243 -14L 756 -14L 756 -42Z",[0.945,0.0]],["M 686 -744L 686 80L 711 80C 769 80 842 45 844 34L 844 -692C 864 -697 875 -705 882 -714L 747 -822L 676 -744Z",[0.009,0.793]]],"bbox":{"top":-822,"bottom":90,"left":175,"right":882},"hadv":1000}],"text":"日","hadv":1000,"breakAfter":true},{"chars":[{"char":"间","components":[["M 273 -715L 88 -732L 88 93L 113 93C 169 93 228 62 228 49L 228 -681C 262 -686 270 -698 273 -715Z",[0.008,0.825]],["M 186 -859L 179 -853C 224 -805 272 -731 290 -662C 422 -580 520 -834 186 -859Z",[-0.235,0.321]],["M 299 -630L 299 -87L 323 -87C 390 -87 430 -116 430 -125L 430 -581L 431 -581Z",[0.0,0.742]],["M 611 -203L 384 -203L 384 -175L 611 -175Z",[-0.919,0.033]],["M 616 -581L 389 -581L 389 -553L 616 -553Z",[-0.553,0.056]],["M 619 -397L 392 -397L 392 -369L 619 -369Z",[-0.751,0.046]],["M 821 -764L 427 -764L 436 -736L 821 -736Z",[0.554,0.018]],["M 552 -581L 560 -581L 560 -110L 583 -110C 633 -110 693 -147 693 -158L 693 -541C 707 -544 715 -550 719 -555L 609 -640Z",[0.017,0.719]],["M 759 -764L 769 -764L 769 -82C 769 -69 764 -61 747 -61C 724 -61 608 -68 608 -68L 608 -55C 665 -45 687 -30 705 -8C 723 12 729 45 732 91C 888 77 909 26 909 -67L 909 -714C 930 -718 942 -727 949 -735L 821 -835Z",[0.047,0.813]]],"bbox":{"top":-859,"bottom":93,"left":88,"right":949},"hadv":1000}],"text":"间","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"幸","components":[["M 835 -654L 758 -558L 26 -558L 34 -530L 946 -530C 961 -530 973 -535 976 -546C 922 -590 835 -654 835 -654Z",[0.865,0.04]],["M 807 -249L 730 -154L 64 -154L 72 -126L 917 -126C 931 -126 943 -131 946 -142C 893 -186 807 -249 807 -249Z",[0.913,0.041]],["M 760 -429L 686 -337L 118 -337L 126 -309L 866 -309C 880 -309 892 -314 895 -325C 844 -367 760 -429 760 -429Z",[0.894,0.046]],["M 740 -810L 665 -716L 134 -716L 142 -688L 849 -688C 864 -688 875 -693 878 -704C 826 -747 740 -810 740 -810Z",[0.922,0.048]],["M 258 -528L 250 -524C 269 -479 284 -420 281 -362C 394 -251 556 -465 258 -528Z",[-0.134,0.266]],["M 607 -841L 422 -855L 422 -541L 575 -541L 575 -815C 599 -819 605 -828 607 -841Z",[0.036,0.518]],["M 575 67L 575 -337L 422 -337L 422 97L 451 97C 529 97 574 73 575 67Z",[0.006,0.656]],["M 785 -499L 595 -536C 588 -473 572 -379 554 -317L 565 -317C 630 -363 706 -429 748 -476C 772 -477 782 -486 785 -499Z",[0.323,0.329]]],"bbox":{"top":-855,"bottom":97,"left":26,"right":976},"hadv":1000}],"text":"幸","hadv":1000,"breakAfter":true},{"chars":[{"char":"福","components":[["M 245 -637L 258 -637C 226 -501 130 -331 8 -213L 16 -205C 182 -288 322 -438 392 -577C 417 -580 428 -583 437 -593L 318 -707Z",[0.422,0.622]],["M 337 -637L 34 -637L 43 -609L 337 -609Z",[0.738,0.005]],["M 127 -857L 120 -853C 141 -812 161 -755 163 -700C 278 -601 422 -816 127 -857Z",[-0.377,0.28]],["M 283 49L 283 -452L 149 -342L 149 90L 173 90C 240 90 283 58 283 49Z",[0.032,0.728]],["M 273 -430L 262 -426C 282 -380 303 -316 304 -260C 388 -181 495 -346 273 -430Z",[-0.176,0.424]],["M 851 -860L 783 -770L 397 -770L 405 -742L 947 -742C 961 -742 972 -747 975 -758C 929 -799 851 -860 851 -860Z",[0.81,0.07]],["M 538 52L 538 -324L 855 -324L 855 -352L 544 -352L 408 -405L 408 94L 427 94C 482 94 538 65 538 52Z",[0.15,0.429]],["M 585 -441L 585 -622L 812 -622L 812 -650L 589 -650L 455 -701L 455 -402L 473 -402C 526 -402 585 -430 585 -441Z",[0.207,0.194]],["M 886 -9L 506 -9L 506 19L 886 19Z",[-0.928,0.002]],["M 886 -186L 506 -186L 506 -158L 886 -158Z",[0.882,0.022]],["M 819 -484L 540 -484L 540 -456L 819 -456Z",[0.899,0.004]],["M 730 -350L 615 -350L 615 8L 730 8Z",[0.01,0.634]],["M 752 -650L 762 -650L 762 -418L 786 -418C 829 -418 898 -440 899 -446L 899 -600C 920 -604 933 -613 939 -621L 812 -716Z",[0.005,0.459]],["M 791 -352L 802 -352L 802 86L 825 86C 869 86 935 61 936 54L 936 -302C 957 -306 971 -315 977 -323L 852 -419Z",[0.017,0.681]]],"bbox":{"top":-860,"bottom":94,"left":8,"right":977},"hadv":1000}],"text":"福","hadv":1000,"breakAfter":false},{"chars":[{"char":"》","components":[["M 26 80L 55 98L 329 -380L 55 -858L 26 -840L 289 -380Z",[0.001,0.711]],["M 168 80L 197 98L 471 -380L 197 -858L 168 -840L 431 -380Z",[0.001,0.71]]],"bbox":{"top":-858,"bottom":98,"left":26,"right":471},"hadv":1000}],"text":"》","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>其实是第二遍，第一次看的时候太困了，所以再来一次。</p>\n<p>故事挺可爱的，我很喜欢，感觉挺适合我的。孤单一个人的时候看一看，有奇效。</p>\n<p>想起当时刷 <code>名学</code> 的时候在贵乎上看到的一段话，大概意思就是，日本的动画、漫画、小说和电视剧之类的，总是希望作品能够有尽量多的内涵，尽量多的解读角度。</p>\n<p>但是作者自己也说了，他“也丝毫不曾想过要透过作品谈论生命的价值，或是爱情的力量”。看来是引发了我强行解读的坏毛病。尽管如此，《三日间的幸福》里说的，都还挺合我的口味就是了。</p>\n<p>强行安利不可取，少女恋爱小说还是少读的好，各位切记。我去补漫画了。</p>\n","plain":"其实是第二遍，第一次看的时候太困了，所以再来一次。\n故事挺可爱的，我很喜欢，感觉挺适合我的。孤单一个人的时候看一看，有奇效。\n想起当时刷 名学 的时候在贵乎上看到的一段话，大概意思就是，日本的动画、漫画、小说和电视剧之类的，总是希望作品能够有尽量多的内涵，尽量多的解读角度。\n但是作者自己也说了，他“也丝毫不曾想过要透过作品谈论生命的价值，或是爱情的力量”。看来是引发了我强行解读的坏毛病。尽管如此，《三日间的幸福》里说的，都还挺合我的口味就是了。\n强行安利不可取，少女恋爱小说还是少读的好，各位切记。我去补漫画了。\n"},{"metadata":{"id":"io-to-moe","lang":"zh-CN","title":"新域名","tags":["Meta","扯淡"],"publish_time":"2017-03-05T11:14:13.335Z","update_time":"2017-03-05T11:14:28.617Z","title_outline":{"groups":[{"chars":[{"char":"新","components":[["M 256 -234L 99 -303C 92 -217 67 -82 23 7L 32 17C 117 -46 179 -140 218 -218C 243 -217 252 -224 256 -234Z",[0.258,0.549]],["M 445 -566L 386 -483L 24 -483L 32 -455L 524 -455C 538 -455 548 -460 551 -471C 512 -509 445 -566 445 -566Z",[0.782,0.067]],["M 427 -417L 371 -338L 37 -338L 45 -310L 500 -310C 514 -310 524 -315 527 -326C 490 -363 427 -417 427 -417Z",[0.823,0.065]],["M 427 -778L 370 -699L 40 -699L 48 -671L 503 -671C 517 -671 527 -676 530 -687C 492 -724 427 -778 427 -778Z",[0.748,0.066]],["M 120 -675L 110 -671C 126 -625 142 -562 139 -506C 226 -415 353 -587 120 -675Z",[-0.193,0.394]],["M 347 -47L 347 -475L 210 -475L 210 -50C 210 -40 207 -33 194 -33C 177 -33 117 -37 117 -37L 117 -25C 156 -18 170 -4 180 12C 190 29 192 56 193 93C 328 83 347 36 347 -47Z",[0.042,0.732]],["M 190 -854L 183 -849C 206 -815 227 -762 227 -712C 338 -621 471 -830 190 -854Z",[-0.093,0.251]],["M 498 -631L 341 -679C 333 -616 316 -525 298 -464L 311 -464C 367 -509 425 -569 461 -613C 483 -611 494 -619 498 -631Z",[0.29,0.429]],["M 355 -284L 345 -279C 369 -232 388 -164 384 -104C 478 -11 605 -202 355 -284Z",[-0.174,0.39]],["M 702 -721L 534 -773L 534 -433C 534 -252 524 -64 412 84L 421 94C 658 -38 673 -251 673 -429L 673 -706C 688 -708 699 -713 702 -721Z",[0.094,0.799]],["M 855 -597L 783 -496L 598 -496L 598 -468L 956 -468C 970 -468 982 -473 984 -484C 937 -529 855 -597 855 -597Z",[0.63,0.138]],["M 969 -741L 824 -856C 781 -809 693 -738 619 -698L 622 -687C 723 -695 834 -715 902 -737C 936 -727 957 -730 969 -741Z",[0.439,0.284]],["M 882 56L 882 -496L 740 -496L 740 94L 766 94C 839 94 881 64 882 56Z",[-0.003,0.84]]],"bbox":{"top":-856,"bottom":94,"left":23,"right":984},"hadv":1000}],"text":"新","hadv":1000,"breakAfter":true},{"chars":[{"char":"域","components":[["M 9 -157L 90 -3C 102 -7 112 -19 116 -33C 241 -129 323 -204 373 -255L 371 -263C 223 -216 70 -172 9 -157Z",[0.543,0.296]],["M 24 -562L 32 -534L 370 -534C 384 -534 394 -539 397 -550C 365 -590 304 -652 304 -652L 251 -562Z",[0.875,0.094]],["M 122 -832L 122 -141L 262 -186L 262 -788C 290 -792 297 -803 299 -817Z",[0.01,0.787]],["M 275 -134L 347 1C 358 -2 368 -12 372 -25C 519 -105 618 -166 682 -210L 680 -221C 512 -182 344 -146 275 -134Z",[0.662,0.253]],["M 343 -659L 351 -631L 951 -631C 965 -631 975 -636 978 -647C 940 -684 875 -738 875 -738L 818 -659Z",[0.963,0.051]],["M 359 -524L 359 -223L 377 -223C 430 -223 462 -246 462 -253L 462 -524L 463 -524L 359 -564Z",[0.003,0.669]],["M 836 -558C 765 -210 625 -44 394 75L 400 90C 689 2 847 -147 950 -490C 978 -490 987 -496 992 -509Z",[0.461,0.66]],["M 417 -339L 417 -311L 563 -311L 563 -339Z",[0.725,0.017]],["M 431 -524L 431 -496L 577 -496L 577 -524Z",[0.541,0.04]],["M 521 -524L 521 -259L 540 -259C 574 -259 628 -279 629 -287L 629 -489C 640 -492 648 -497 652 -501L 560 -570L 514 -524Z",[0.035,0.602]],["M 627 -839C 628 -514 645 -166 815 26C 855 76 924 118 975 79C 997 62 989 7 963 -45L 988 -243L 978 -244C 963 -202 937 -140 921 -113C 911 -97 902 -98 891 -110C 759 -244 751 -540 757 -793C 780 -798 789 -809 790 -822Z",[-0.222,0.78]],["M 798 -819L 790 -813C 815 -789 835 -744 834 -704C 934 -627 1044 -818 798 -819Z",[0.207,0.357]]],"bbox":{"top":-839,"bottom":118,"left":9,"right":1044},"hadv":1000}],"text":"域","hadv":1000,"breakAfter":true},{"chars":[{"char":"名","components":[["M 657 -718L 673 -718C 562 -490 311 -286 24 -170L 29 -159C 403 -228 678 -408 834 -653C 863 -655 874 -659 882 -672L 748 -800Z",[0.616,0.527]],["M 550 -807L 354 -860C 295 -691 163 -488 36 -379L 43 -371C 229 -458 406 -630 508 -792C 537 -790 545 -796 550 -807Z",[0.48,0.584]],["M 451 55L 451 -315L 465 -315L 368 -350L 301 -264L 301 98L 329 98C 406 98 451 65 451 55Z",[0.025,0.653]],["M 310 -611L 303 -607C 328 -564 353 -504 357 -445C 483 -345 624 -579 310 -611Z",[-0.204,0.242]],["M 767 -718L 375 -718L 355 -690L 767 -690Z",[0.63,0.018]],["M 840 -315L 379 -315L 379 -287L 840 -287Z",[-0.959,0.004]],["M 818 -25L 381 -25L 381 3L 818 3Z",[0.936,0.0]],["M 723 -315L 734 -315L 734 81L 760 81C 812 81 886 50 887 41L 887 -260C 910 -265 923 -275 930 -284L 791 -390Z",[0.025,0.605]]],"bbox":{"top":-860,"bottom":98,"left":24,"right":930},"hadv":1000}],"text":"名","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>由于无法承受 <code>.io</code> 域名一年 400 CNY 的高价，换成了 <code>.moe</code> 域名，虽然说过程十分蛋疼，但是至少<strong>萌</strong>了起来。</p>\n<p>同时发现了 Godaddy 的阴谋：GoDaddy 一个 <code>.moe</code> 域名卖 170+ CNY，然后整天往我的邮箱发 6 折优惠的邮件，但是只能用在新域名，简直阴险。反观 name.com，只卖 ~130 CNY，而且 WHOIS 隐身可以用优惠码直接免费拿，业界良心。<del>虽然说 name.com 的 <code>.io</code> 卖 99 USD 就是了。</del></p>\n<p>其实也就是换一下 Postfix 设置，换一下 Google Analytics &amp; Search Console &amp; Sign-In 的域名，改一下 Nginx 配置，换了波 HTTPS 证书，没什么大事。</p>\n<p>希望这个域名不要用一年之后发现交不起钱，然后换个 <code>.me</code> 之类的就可以。毕竟挺萌的。</p>\n","plain":"由于无法承受 .io 域名一年 400 CNY 的高价，换成了 .moe 域名，虽然说过程十分蛋疼，但是至少萌了起来。\n同时发现了 Godaddy 的阴谋：GoDaddy 一个 .moe 域名卖 170+ CNY，然后整天往我的邮箱发 6 折优惠的邮件，但是只能用在新域名，简直阴险。反观 name.com，只卖 ~130 CNY，而且 WHOIS 隐身可以用优惠码直接免费拿，业界良心。虽然说 name.com 的 .io 卖 99 USD 就是了。\n其实也就是换一下 Postfix 设置，换一下 Google Analytics & Search Console & Sign-In 的域名，改一下 Nginx 配置，换了波 HTTPS 证书，没什么大事。\n希望这个域名不要用一年之后发现交不起钱，然后换个 .me 之类的就可以。毕竟挺萌的。\n"},{"metadata":{"id":"snowing","lang":"zh-CN","title":"下雪了","tags":["扯淡"],"publish_time":"2017-02-21T13:53:09.918Z","update_time":"2017-02-21T13:53:23.458Z","title_outline":{"groups":[{"chars":[{"char":"下","components":[["M 831 -861L 747 -753L 25 -753L 33 -725L 952 -725C 968 -725 980 -730 983 -741C 926 -789 831 -861 831 -861Z",[0.83,0.048]],["M 557 52L 557 -753L 402 -753L 402 95L 431 95C 508 95 557 62 557 52Z",[0.002,0.818]],["M 540 -554L 533 -547C 630 -467 743 -346 805 -235C 979 -151 1056 -488 540 -554Z",[-0.44,0.388]]],"bbox":{"top":-861,"bottom":95,"left":25,"right":1056},"hadv":1000}],"text":"下","hadv":1000,"breakAfter":true},{"chars":[{"char":"雪","components":[["M 161 -719L 149 -718C 156 -659 120 -608 84 -589C 49 -573 23 -543 34 -500C 48 -457 96 -443 136 -463C 193 -492 227 -587 161 -719Z",[0.207,0.433]],["M 737 8L 128 8L 137 36L 737 36Z",[0.954,0.0]],["M 755 -869L 683 -778L 134 -778L 142 -750L 858 -750C 872 -750 883 -755 886 -766C 837 -808 755 -869 755 -869Z",[0.804,0.051]],["M 849 -648L 145 -648L 145 -620L 849 -620Z",[0.798,0.009]],["M 746 -296L 147 -296L 156 -268L 746 -268Z",[0.918,0.001]],["M 742 -145L 171 -145L 180 -117L 742 -117Z",[0.93,0.004]],["M 384 -422L 176 -422L 176 -394L 384 -394Z",[-0.863,0.019]],["M 378 -534L 208 -534L 208 -506L 378 -506Z",[-0.636,0.031]],["M 568 -360L 568 -778L 426 -778L 426 -331L 452 -331C 525 -331 568 -354 568 -360Z",[-0.001,0.692]],["M 794 -421L 601 -421L 601 -393L 794 -393Z",[-0.555,0.098]],["M 766 -533L 601 -533L 601 -505L 766 -505Z",[-0.499,0.109]],["M 678 -296L 688 -296L 688 91L 713 91C 764 91 834 61 835 52L 835 -245C 856 -249 868 -258 875 -266L 743 -367Z",[0.016,0.63]],["M 799 -648L 810 -648C 809 -604 803 -529 796 -480L 804 -474C 851 -504 911 -555 946 -592C 967 -593 977 -596 985 -605L 867 -717Z",[-0.21,0.328]]],"bbox":{"top":-869,"bottom":91,"left":23,"right":985},"hadv":1000}],"text":"雪","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>北京下雪了，这是好的，并且是今年最大的一场。</p>\n<p>没想到这么暖和的一个冬天，到了春天门口来这么一场雪。只是没人跟我一块打雪仗就是了。</p>\n<p>嗯，还是这种天气好，空气清新，没有太阳暴晒或是大风凛冽，天上远远的蒙着一个盖子，有种特别的安全感，并不比那些风和日丽的晴朗日子差到哪里去。况且北京有没有风和日丽的晴朗日子，这已经是最好的了。</p>\n<p>希望明天还有没化的雪，后天没有没化的雪，直到夏天还有没化的雪。</p>\n","plain":"北京下雪了，这是好的，并且是今年最大的一场。\n没想到这么暖和的一个冬天，到了春天门口来这么一场雪。只是没人跟我一块打雪仗就是了。\n嗯，还是这种天气好，空气清新，没有太阳暴晒或是大风凛冽，天上远远的蒙着一个盖子，有种特别的安全感，并不比那些风和日丽的晴朗日子差到哪里去。况且北京有没有风和日丽的晴朗日子，这已经是最好的了。\n希望明天还有没化的雪，后天没有没化的雪，直到夏天还有没化的雪。\n"},{"metadata":{"id":"offline-access","lang":"zh-CN","title":"没有信号","tags":["Meta"],"publish_time":"2017-02-19T09:21:13.357Z","update_time":"2017-02-19T09:21:13.357Z","title_outline":{"groups":[{"chars":[{"char":"没","components":[["M 29 -612L 22 -607C 54 -566 89 -503 100 -445C 221 -363 328 -591 29 -612Z",[-0.262,0.302]],["M 96 -217C 85 -217 49 -217 49 -217L 49 -199C 71 -197 89 -192 104 -182C 128 -165 132 -65 111 43C 122 83 151 96 176 96C 232 96 271 60 273 5C 276 -87 230 -118 228 -177C 227 -204 235 -242 244 -277C 257 -333 324 -557 364 -679L 349 -683C 154 -277 154 -277 129 -238C 117 -217 112 -217 96 -217Z",[0.138,0.758]],["M 85 -843L 78 -838C 116 -796 162 -732 181 -672C 316 -597 409 -847 85 -843Z",[-0.338,0.281]],["M 718 -392L 732 -392C 671 -174 506 -5 250 87L 254 98C 593 44 789 -109 889 -334C 914 -337 924 -340 931 -352L 801 -470Z",[0.531,0.547]],["M 421 -790L 421 -701C 421 -611 409 -490 304 -397L 309 -389C 534 -464 559 -614 559 -702L 559 -780L 579 -780L 421 -834Z",[0.188,0.619]],["M 793 -392L 337 -392L 346 -364L 793 -364Z",[-0.928,0.0]],["M 452 -386L 441 -380C 500 -88 642 21 862 94C 882 19 926 -32 991 -48L 992 -60C 755 -91 530 -156 452 -386Z",[-0.571,0.363]],["M 734 -780L 493 -780L 493 -752L 734 -752Z",[-0.677,0.065]],["M 664 -780L 675 -780L 675 -570C 675 -486 685 -460 778 -460L 830 -460C 935 -460 981 -488 981 -540C 981 -565 973 -579 943 -595L 937 -597L 928 -597C 920 -595 908 -593 900 -592C 894 -591 880 -590 873 -590C 867 -590 857 -590 850 -590L 827 -590C 815 -590 812 -594 812 -605L 812 -744C 830 -746 842 -752 848 -759L 730 -852Z",[-0.159,0.335]]],"bbox":{"top":-852,"bottom":98,"left":22,"right":992},"hadv":1000}],"text":"没","hadv":1000,"breakAfter":true},{"chars":[{"char":"有","components":[["M 372 -858C 326 -666 212 -419 20 -266L 28 -257C 291 -370 444 -589 525 -779C 551 -780 560 -789 563 -800Z",[0.442,0.644]],["M 39 -683L 47 -655L 938 -655C 953 -655 965 -660 967 -671C 913 -717 822 -783 822 -783L 742 -683Z",[0.943,0.036]],["M 385 -513L 399 -513L 289 -553L 240 -474L 240 92L 267 92C 341 92 385 60 385 51Z",[0.009,0.768]],["M 317 -358L 317 -330L 768 -330L 768 -358Z",[-0.906,0.009]],["M 317 -513L 317 -485L 768 -485L 768 -513Z",[-0.787,0.018]],["M 317 -202L 317 -174L 768 -174L 768 -202Z",[-0.951,0.001]],["M 677 -513L 677 -86C 677 -73 673 -66 657 -66C 634 -66 526 -72 526 -72L 526 -60C 580 -50 601 -34 618 -12C 635 10 640 44 644 92C 802 78 824 25 824 -69L 824 -459C 847 -463 861 -473 868 -483L 732 -588L 666 -513Z",[0.067,0.71]]],"bbox":{"top":-858,"bottom":92,"left":20,"right":967},"hadv":1000}],"text":"有","hadv":1000,"breakAfter":true},{"chars":[{"char":"信","components":[["M 392 -803L 193 -859C 162 -659 89 -447 16 -312L 27 -305C 169 -413 276 -567 351 -781C 375 -781 388 -790 392 -803Z",[0.303,0.665]],["M 309 -554L 188 -598L 135 -528L 135 95L 162 95C 218 95 276 65 278 54L 278 -534C 298 -538 306 -544 309 -554Z",[0.012,0.786]],["M 863 -759L 793 -663L 314 -663L 322 -635L 960 -635C 974 -635 985 -640 988 -651C 942 -694 863 -759 863 -759Z",[0.771,0.07]],["M 810 -611L 746 -523L 374 -523L 382 -495L 896 -495C 911 -495 922 -500 924 -511C 882 -551 810 -611 810 -611Z",[0.764,0.079]],["M 808 -464L 744 -376L 382 -376L 390 -348L 895 -348C 909 -348 920 -353 923 -364C 881 -404 808 -464 808 -464Z",[0.819,0.074]],["M 528 50L 528 -219L 825 -219L 825 -247L 535 -247L 386 -304L 386 94L 406 94C 465 94 528 63 528 50Z",[0.179,0.286]],["M 830 -23L 469 -23L 469 5L 830 5Z",[0.924,0.001]],["M 520 -860L 514 -855C 550 -815 583 -752 590 -692C 722 -600 843 -853 520 -860Z",[-0.09,0.194]],["M 739 -247L 749 -247L 749 81L 774 81C 823 81 893 53 894 44L 894 -196C 915 -200 927 -210 933 -218L 803 -316Z",[0.022,0.556]]],"bbox":{"top":-860,"bottom":95,"left":16,"right":988},"hadv":1000}],"text":"信","hadv":1000,"breakAfter":true},{"chars":[{"char":"号","components":[["M 855 -516L 785 -420L 30 -420L 38 -392L 951 -392C 966 -392 977 -397 980 -408C 934 -451 855 -516 855 -516Z",[0.898,0.038]],["M 427 -406L 264 -406C 253 -371 219 -288 196 -247L 242 -283C 216 -277 185 -261 168 -244L 302 -168L 352 -227L 345 -227C 367 -271 407 -361 427 -406Z",[0.233,0.332]],["M 344 -499L 344 -759L 750 -759L 750 -787L 352 -787L 199 -845L 199 -454L 219 -454C 279 -454 344 -486 344 -499Z",[0.322,0.207]],["M 761 -255L 289 -255L 278 -227L 761 -227Z",[-0.956,0.004]],["M 746 -564L 285 -564L 285 -536L 746 -536Z",[0.801,0.009]],["M 695 -255L 705 -255C 690 -153 665 -72 638 -55C 628 -48 618 -47 601 -47C 577 -47 482 -52 419 -57L 418 -47C 475 -36 524 -18 547 4C 569 24 574 57 573 93C 648 94 691 84 728 62C 788 26 823 -68 845 -202C 866 -205 879 -211 886 -220L 766 -320Z",[0.305,0.41]],["M 651 -787L 661 -787L 661 -480L 686 -480C 733 -480 806 -503 808 -510L 808 -736C 829 -740 841 -749 847 -757L 714 -857Z",[0.043,0.533]]],"bbox":{"top":-857,"bottom":94,"left":30,"right":980},"hadv":1000}],"text":"号","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>这几天放假，给博客加了个 ServiceWorker，现在可以离线访问了。</p>\n<p>最大一个坑是数据库连接。按照传统服务端的习性，DB 连接是要共享的。所以本来用 IDB 的时候是在 Install 的时候把数据库连接初始化，然后以后每次 Fetch 就直接用已有的连接。本来工作的挺好的，开发环境下也一点问题都没有，直到我第一次重启浏览器，就崩了…</p>\n<p>成吧，重启浏览器后不会再跑一次 install，也没有 activate，只能在每次 Fetch 来的时候重开连接。反正是客户端，毫不担心连接数爆炸，嘻嘻。</p>\n<p>用 Webpack 也有坑，不知道都有哪些文件，所以不能 Cache，装个插件才能解决。</p>\n<p>大概也就这样吧，其实并不是什么难事，我做这个的动机主要是刷 Lighthouse 分数，现在已经有 97 分，我距离满分骨粉只差一个跨越大洋的网络。</p>\n","plain":"这几天放假，给博客加了个 ServiceWorker，现在可以离线访问了。\n最大一个坑是数据库连接。按照传统服务端的习性，DB 连接是要共享的。所以本来用 IDB 的时候是在 Install 的时候把数据库连接初始化，然后以后每次 Fetch 就直接用已有的连接。本来工作的挺好的，开发环境下也一点问题都没有，直到我第一次重启浏览器，就崩了…\n成吧，重启浏览器后不会再跑一次 install，也没有 activate，只能在每次 Fetch 来的时候重开连接。反正是客户端，毫不担心连接数爆炸，嘻嘻。\n用 Webpack 也有坑，不知道都有哪些文件，所以不能 Cache，装个插件才能解决。\n大概也就这样吧，其实并不是什么难事，我做这个的动机主要是刷 Lighthouse 分数，现在已经有 97 分，我距离满分骨粉只差一个跨越大洋的网络。\n"},{"metadata":{"id":"your-name-earthbound","lang":"zh-CN","title":"关于君名外传","tags":["君の名は。"],"publish_time":"2017-01-27T12:30:27.552Z","update_time":"2017-01-28T14:41:57.573Z","title_outline":{"groups":[{"chars":[{"char":"关","components":[["M 556 -431L 556 -600L 396 -600L 396 -430C 396 -249 345 -64 22 85L 25 93C 509 -11 555 -251 556 -431Z",[0.303,0.635]],["M 825 -459L 745 -359L 32 -359L 40 -331L 941 -331C 956 -331 968 -336 971 -347C 916 -392 825 -459 825 -459Z",[0.894,0.043]],["M 774 -702L 697 -607L 96 -607L 104 -579L 884 -579C 899 -579 911 -584 914 -595C 861 -639 774 -702 774 -702Z",[0.88,0.047]],["M 221 -848L 214 -843C 252 -790 287 -716 296 -645C 428 -545 555 -802 221 -848Z",[-0.216,0.333]],["M 551 -356L 541 -352C 590 -121 680 12 857 92C 874 17 918 -34 975 -50L 977 -62C 796 -95 622 -193 551 -356Z",[-0.481,0.403]],["M 807 -798L 614 -855C 602 -778 575 -665 547 -589L 557 -589C 637 -645 720 -723 769 -779C 792 -778 803 -786 807 -798Z",[0.283,0.406]]],"bbox":{"top":-855,"bottom":93,"left":22,"right":977},"hadv":1000}],"text":"关","hadv":1000,"breakAfter":true},{"chars":[{"char":"于","components":[["M 26 -449L 34 -421L 946 -421C 961 -421 973 -426 975 -437C 920 -483 829 -550 829 -550L 748 -449Z",[0.913,0.041]],["M 109 -745L 117 -717L 875 -717C 890 -717 901 -722 904 -733C 850 -778 761 -844 761 -844L 682 -745Z",[0.9,0.042]],["M 426 -745L 426 -90C 426 -78 420 -70 404 -70C 375 -70 237 -78 237 -78L 237 -66C 305 -55 330 -38 350 -16C 372 7 380 43 382 93C 552 82 579 13 579 -85L 579 -745Z",[0.058,0.773]]],"bbox":{"top":-844,"bottom":93,"left":26,"right":975},"hadv":1000}],"text":"于","hadv":1000,"breakAfter":true},{"chars":[{"char":"君","components":[["M 363 -778C 344 -489 250 -258 22 -118L 30 -109C 366 -231 494 -456 530 -762L 530 -778Z",[0.352,0.678]],["M 45 -605L 53 -577L 952 -577C 967 -577 977 -582 980 -593C 939 -634 868 -696 868 -696L 805 -605Z",[0.871,0.019]],["M 126 -437L 135 -409L 740 -409L 740 -437Z",[-0.888,0.004]],["M 136 -778L 145 -750L 740 -750L 740 -778Z",[-0.665,0.012]],["M 398 -253L 412 -253L 269 -305L 256 -289L 256 92L 283 92C 355 92 398 62 398 53Z",[-0.004,0.614]],["M 332 -253L 332 -225L 802 -225L 802 -253Z",[-0.97,0.004]],["M 343 -15L 343 13L 813 13L 813 -15Z",[0.94,0.0]],["M 661 -778L 661 -353L 685 -353C 733 -353 804 -379 805 -387L 805 -727C 826 -732 838 -741 845 -749L 714 -848L 651 -778Z",[0.033,0.649]],["M 703 -253L 703 80L 729 80C 776 80 849 55 850 47L 850 -203C 870 -207 882 -216 888 -224L 757 -322L 693 -253Z",[0.014,0.559]]],"bbox":{"top":-848,"bottom":92,"left":22,"right":980},"hadv":1000}],"text":"君","hadv":1000,"breakAfter":true},{"chars":[{"char":"名","components":[["M 657 -718L 673 -718C 562 -490 311 -286 24 -170L 29 -159C 403 -228 678 -408 834 -653C 863 -655 874 -659 882 -672L 748 -800Z",[0.616,0.527]],["M 550 -807L 354 -860C 295 -691 163 -488 36 -379L 43 -371C 229 -458 406 -630 508 -792C 537 -790 545 -796 550 -807Z",[0.48,0.584]],["M 451 55L 451 -315L 465 -315L 368 -350L 301 -264L 301 98L 329 98C 406 98 451 65 451 55Z",[0.025,0.653]],["M 310 -611L 303 -607C 328 -564 353 -504 357 -445C 483 -345 624 -579 310 -611Z",[-0.204,0.242]],["M 767 -718L 375 -718L 355 -690L 767 -690Z",[0.63,0.018]],["M 840 -315L 379 -315L 379 -287L 840 -287Z",[-0.959,0.004]],["M 818 -25L 381 -25L 381 3L 818 3Z",[0.936,0.0]],["M 723 -315L 734 -315L 734 81L 760 81C 812 81 886 50 887 41L 887 -260C 910 -265 923 -275 930 -284L 791 -390Z",[0.025,0.605]]],"bbox":{"top":-860,"bottom":98,"left":24,"right":930},"hadv":1000}],"text":"名","hadv":1000,"breakAfter":true},{"chars":[{"char":"外","components":[["M 395 -668L 408 -668C 383 -357 291 -73 21 87L 29 97C 419 -32 516 -307 557 -611C 582 -615 592 -619 599 -631L 469 -747Z",[0.325,0.717]],["M 390 -814L 194 -856C 177 -644 110 -435 27 -295L 38 -288C 189 -395 289 -552 351 -790C 375 -791 386 -800 390 -814Z",[0.28,0.691]],["M 190 -508L 183 -503C 218 -455 243 -384 243 -318C 369 -210 511 -459 190 -508Z",[-0.196,0.321]],["M 460 -668L 252 -668L 245 -640L 460 -640Z",[-0.135,0.011]],["M 790 -835L 606 -853L 606 96L 635 96C 691 96 753 67 753 55L 753 -807C 781 -811 788 -821 790 -835Z",[0.004,0.836]],["M 736 -543L 728 -538C 777 -470 831 -379 854 -293C 1000 -193 1112 -475 736 -543Z",[-0.245,0.325]]],"bbox":{"top":-856,"bottom":97,"left":21,"right":1112},"hadv":1000}],"text":"外","hadv":1000,"breakAfter":true},{"chars":[{"char":"传","components":[["M 396 -796L 194 -854C 163 -660 89 -456 16 -327L 26 -320C 169 -421 277 -567 355 -775C 379 -775 391 -783 396 -796Z",[0.313,0.647]],["M 301 -547L 178 -592L 125 -522L 125 97L 152 97C 209 97 268 67 270 56L 270 -527C 290 -531 298 -538 301 -547Z",[0.011,0.781]],["M 862 -576L 792 -480L 275 -480L 283 -452L 961 -452C 976 -452 987 -457 990 -468C 943 -511 862 -576 862 -576Z",[0.824,0.064]],["M 813 -759L 747 -670L 333 -670L 341 -642L 905 -642C 920 -642 931 -647 933 -658C 889 -699 813 -759 813 -759Z",[0.806,0.066]],["M 732 -818L 550 -856C 533 -743 456 -436 405 -303L 447 -342C 423 -334 395 -316 379 -301L 511 -225L 562 -286L 555 -286C 595 -419 669 -706 696 -817L 685 -794C 716 -792 728 -805 732 -818Z",[0.208,0.736]],["M 399 -154L 393 -144C 511 -98 656 -0 727 90C 881 126 887 -172 399 -154Z",[-0.591,0.335]],["M 809 -314L 482 -314L 491 -286L 809 -286Z",[0.8,0.045]],["M 720 -314L 732 -314C 713 -246 672 -136 635 -65L 641 -60C 725 -107 832 -188 895 -249C 918 -251 928 -254 937 -264L 802 -393Z",[0.303,0.404]]],"bbox":{"top":-856,"bottom":126,"left":16,"right":990},"hadv":1000}],"text":"传","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>把君名的外传看完了，感觉新海诚监督这个人啊，简直没有变，夹杂的私货太含蓄。</p>\n<h2>我要客观</h2>\n<p>君名的问题很显著，看了很多遍以后愈发的明显：人物塑造挺失败的，看完漫画和外传之后才丰满起来。再者剧情也没什么新意，宣传又单一而缺乏深度，Fanbase 也太激进。但是要说到立意，虽说弄明白是挺麻烦的，现在给我的感觉还是挺丰富的。</p>\n<p>一是命运感，主角二人的相遇、相爱、再相遇，妈妈和爸爸的相遇、相爱、分离，爸爸的从政，千年来宫水家族的传承，都是为了在千年后拯救这一村子人。大多宣传专注于主角之间的重逢，而忽视了妈妈口中“每个人都在神明的指引下找到自己的位置”这一层意思，引了不少黑。</p>\n<p>二是日常的美。可能新海监督想表达的更多是乡愁这个概念，但是给我这个城市人的感觉是在表现身边熟悉事物的美妙罢了。在<a href=\"your-name\">你是谁</a>里扯了太多，不再说。这大概是吸引我跑去一遍又一遍看电影的主要原因：现实很骨感，我还是更喜欢那边的世界。</p>\n<div style=\"opacity: 0.3; text-align: center;\">再见我去找三叶了.jpg</div>\n<p>三是人与人之间的联系，地域和其上的传统将不同时空的人们联系起来。三叶和泷的联系说的是依恋、勇气和决心，宫水家族巫女之间的联系说的是希望和坚守，而三叶和村民的联系对她可能就是一种累赘了。四叶说：“我们不孤独呢”，三叶却听不进去——处于关系网中心的她太累了。顺便看宫水爸爸对支撑村子的关系网的描述，忽然有种《乡土中国》感觉，一个人的存在取决于周遭人对她的共同认知，背负责任至死，对我而言是挺悲哀的一件事情。奶奶已经习惯这种生活了，于是习以为常，倒是苦了高中生三叶。</p>\n<p>说实话，这方面之中除了三叶和泷的羁绊以外，在电影中表达力度严重不足。和父亲的矛盾啊，和奶奶、妹妹的生活日常啊，和朋友、同学之间的交往之类的，一笔带过。于是有质疑，三叶有朋友有家人，怎么就寂寞了，然后莫名其妙异地恋？有个关系不好的镇长老爸最多有点尴尬吧。这是电影的一大漏洞。</p>\n<p>四，也是我觉得是新海监督想表达的本质，是遗忘。</p>\n<p>新海诚监督在访谈中谈及君名灵感来源于11年地震（之前写成了东京大地震，抱歉），说：</p>\n<blockquote>\n<p>人会忘记许多事情，包括“喜欢”这样一种情感，但我们要挣扎着努力不要忘记，然后坚强地活下去。</p>\n</blockquote>\n<p>而影片中主角忘记了换身拯救小镇的经历，爸爸冻结了对于宫水一家的归属感和爱意，巫女忘记了祭祀的意义，连小镇的人们被拯救后，住进了大城市，大概把已经被摧毁的小镇子给遗忘了吧。加纳新太借平安时代的宫水巫女之口，也表达了这种遗忘的必然性。可以看出，新海诚对于此是持有很悲观的态度的。</p>\n<p>与之对比的，是即使陨石落下也坚守乡土的平安时代糸守镇的镇民，和为了保护未来镇民而设计复杂祭祀步骤的第一代宫水巫女。就我的（利用小脑袋做出的过度）理解，这是在说对错误、苦难的坚守、反思以及在此之上的进步。对于不知道是不是新海诚这个 seemingly young man 在表达对这种快餐化时代还是什么什么的批评。</p>\n<p>恰逢APA酒店店主之“人们会很快忘记”，放在一起不知是相合还是说有反讽意味。</p>\n<p>所以说，我觉得，这是个P HE，只是这次新海监督打了打商业算盘，并且算是填填坑，里子还是那个整天给你带来抑郁的新海诚。</p>\n<h2>说说三叶</h2>\n<p>正传没读，据说是围绕泷的。漫画更多针对二人之间的情感发展，外传是完全围绕三叶的。</p>\n<p>漫画和外传里的三叶是怎样一个人呢？</p>\n<p>在别人面前，品行端庄，安分守己，有点过度拘谨的大小姐。</p>\n<p>在妹妹面前，担当起了母亲的责任，却没有脱离姐姐的身份。</p>\n<p>在泷面前，恩，就是个比最普通的高中妹子还爱撒娇的人。</p>\n<p>这样的三叶带入剧情才对头，电影中表现的村姑形象太单薄了。新海诚监督的人物塑造还欠火候，奈何环境渲染这种大招没用出来，可惜了。</p>\n<p>* 外传里三叶可爱至极，尤其是和妹妹的互动，一定要看外传。</p>\n<h2>对于新海诚</h2>\n<p>看完外传，我有感觉是新海诚在自己的作品中是很孤独又善良的。这个在访谈中也可以有感觉，感觉他希望在冰冷的环境中找出令人感动的一两个有人情味的点，开始是展示给自己，现在是展示给观众，与泷在应聘时提出的观念如出一辙。</p>\n<p>我个人是挺喜欢的，并且觉得对人情的渲染的和对人性的思考一样都能经历时间考验。希望新海诚能够带来更好的作品，无论从观影体验上而言，还是夹杂私活上而言。</p>\n<h2>杂</h2>\n<p>宫水爸爸真是惨。妻子不明不白就去世了，失去了最珍惜的东西，而自己的女儿也不理解自己的心情。努力十多年破除迷信，最后得知：这都是神的引导？</p>\n<p>俊树：我有句…\n神：不能</p>\n<p>再者，小镇毁灭后，宫水爸爸的使命也就完成了，与妻子的联系也就此断绝。我估计他很难再和三叶恢复关系吧，这个男人真的是一无所有了，他还有什么活下去的动力呢？</p>\n<hr />\n<p>三叶成功用绳子缠住了龍 (literally)，并从陨石下拯救了村民，和她妈妈一样，体内住着神明啊…</p>\n<hr />\n<p>恭喜妈妈二叶成功晋升本作大 Boss，奶奶退居二线。</p>\n<hr />\n<p>大年三十，漫画要更最后一话了，过年真好。</p>\n<hr />\n<p>文言版<a href=\"https://zh-classical.wikipedia.org/wiki/%E5%90%9B%E5%90%8D\">君名</a>维基百科，十分服气。</p>\n<hr />\n<p>这个人 -&gt; <a href=\"http://www.pixiv.net/member.php?id=6096868\">feelition</a> 作品发糖很多</p>\n<hr />\n<p><a href=\"https://www.zhihu.com/question/51652164/answer/140593674\">电影《你的名字。》有哪些不易发现的小细节？ - striderzhang的回答</a></p>\n<p>老哥，稳</p>\n<h2>好了你们什么都不要说了</h2>\n<p>说着我就跑去看声之形了。</p>\n","plain":"把君名的外传看完了，感觉新海诚监督这个人啊，简直没有变，夹杂的私货太含蓄。\n\n我要客观\n君名的问题很显著，看了很多遍以后愈发的明显：人物塑造挺失败的，看完漫画和外传之后才丰满起来。再者剧情也没什么新意，宣传又单一而缺乏深度，Fanbase 也太激进。但是要说到立意，虽说弄明白是挺麻烦的，现在给我的感觉还是挺丰富的。\n一是命运感，主角二人的相遇、相爱、再相遇，妈妈和爸爸的相遇、相爱、分离，爸爸的从政，千年来宫水家族的传承，都是为了在千年后拯救这一村子人。大多宣传专注于主角之间的重逢，而忽视了妈妈口中“每个人都在神明的指引下找到自己的位置”这一层意思，引了不少黑。\n二是日常的美。可能新海监督想表达的更多是乡愁这个概念，但是给我这个城市人的感觉是在表现身边熟悉事物的美妙罢了。在你是谁里扯了太多，不再说。这大概是吸引我跑去一遍又一遍看电影的主要原因：现实很骨感，我还是更喜欢那边的世界。\n三是人与人之间的联系，地域和其上的传统将不同时空的人们联系起来。三叶和泷的联系说的是依恋、勇气和决心，宫水家族巫女之间的联系说的是希望和坚守，而三叶和村民的联系对她可能就是一种累赘了。四叶说：“我们不孤独呢”，三叶却听不进去——处于关系网中心的她太累了。顺便看宫水爸爸对支撑村子的关系网的描述，忽然有种《乡土中国》感觉，一个人的存在取决于周遭人对她的共同认知，背负责任至死，对我而言是挺悲哀的一件事情。奶奶已经习惯这种生活了，于是习以为常，倒是苦了高中生三叶。\n说实话，这方面之中除了三叶和泷的羁绊以外，在电影中表达力度严重不足。和父亲的矛盾啊，和奶奶、妹妹的生活日常啊，和朋友、同学之间的交往之类的，一笔带过。于是有质疑，三叶有朋友有家人，怎么就寂寞了，然后莫名其妙异地恋？有个关系不好的镇长老爸最多有点尴尬吧。这是电影的一大漏洞。\n四，也是我觉得是新海监督想表达的本质，是遗忘。\n新海诚监督在访谈中谈及君名灵感来源于11年地震（之前写成了东京大地震，抱歉），说：\n人会忘记许多事情，包括“喜欢”这样一种情感，但我们要挣扎着努力不要忘记，然后坚强地活下去。\n\n而影片中主角忘记了换身拯救小镇的经历，爸爸冻结了对于宫水一家的归属感和爱意，巫女忘记了祭祀的意义，连小镇的人们被拯救后，住进了大城市，大概把已经被摧毁的小镇子给遗忘了吧。加纳新太借平安时代的宫水巫女之口，也表达了这种遗忘的必然性。可以看出，新海诚对于此是持有很悲观的态度的。\n与之对比的，是即使陨石落下也坚守乡土的平安时代糸守镇的镇民，和为了保护未来镇民而设计复杂祭祀步骤的第一代宫水巫女。就我的（利用小脑袋做出的过度）理解，这是在说对错误、苦难的坚守、反思以及在此之上的进步。对于不知道是不是新海诚这个 seemingly young man 在表达对这种快餐化时代还是什么什么的批评。\n恰逢APA酒店店主之“人们会很快忘记”，放在一起不知是相合还是说有反讽意味。\n所以说，我觉得，这是个P HE，只是这次新海监督打了打商业算盘，并且算是填填坑，里子还是那个整天给你带来抑郁的新海诚。\n\n说说三叶\n正传没读，据说是围绕泷的。漫画更多针对二人之间的情感发展，外传是完全围绕三叶的。\n漫画和外传里的三叶是怎样一个人呢？\n在别人面前，品行端庄，安分守己，有点过度拘谨的大小姐。\n在妹妹面前，担当起了母亲的责任，却没有脱离姐姐的身份。\n在泷面前，恩，就是个比最普通的高中妹子还爱撒娇的人。\n这样的三叶带入剧情才对头，电影中表现的村姑形象太单薄了。新海诚监督的人物塑造还欠火候，奈何环境渲染这种大招没用出来，可惜了。\n* 外传里三叶可爱至极，尤其是和妹妹的互动，一定要看外传。\n\n对于新海诚\n看完外传，我有感觉是新海诚在自己的作品中是很孤独又善良的。这个在访谈中也可以有感觉，感觉他希望在冰冷的环境中找出令人感动的一两个有人情味的点，开始是展示给自己，现在是展示给观众，与泷在应聘时提出的观念如出一辙。\n我个人是挺喜欢的，并且觉得对人情的渲染的和对人性的思考一样都能经历时间考验。希望新海诚能够带来更好的作品，无论从观影体验上而言，还是夹杂私活上而言。\n\n杂\n宫水爸爸真是惨。妻子不明不白就去世了，失去了最珍惜的东西，而自己的女儿也不理解自己的心情。努力十多年破除迷信，最后得知：这都是神的引导？\n俊树：我有句… 神：不能\n再者，小镇毁灭后，宫水爸爸的使命也就完成了，与妻子的联系也就此断绝。我估计他很难再和三叶恢复关系吧，这个男人真的是一无所有了，他还有什么活下去的动力呢？\n---\n三叶成功用绳子缠住了龍 (literally)，并从陨石下拯救了村民，和她妈妈一样，体内住着神明啊…\n---\n恭喜妈妈二叶成功晋升本作大 Boss，奶奶退居二线。\n---\n大年三十，漫画要更最后一话了，过年真好。\n---\n文言版君名维基百科，十分服气。\n---\n这个人 -> feelition 作品发糖很多\n---\n电影《你的名字。》有哪些不易发现的小细节？ - striderzhang的回答\n老哥，稳\n\n好了你们什么都不要说了\n说着我就跑去看声之形了。\n"},{"metadata":{"id":"entering-2017","lang":"zh-CN","title":"再见，你好","tags":["扯淡"],"publish_time":"2016-12-31T16:25:53.931Z","update_time":"2017-01-02T13:43:01.938Z","title_outline":{"groups":[{"chars":[{"char":"再","components":[["M 21 -232L 29 -204L 962 -204C 976 -204 986 -209 989 -220C 953 -259 889 -317 889 -317L 832 -232Z",[0.932,0.029]],["M 57 -756L 65 -728L 918 -728C 932 -728 944 -733 947 -744C 893 -788 805 -852 805 -852L 728 -756Z",[0.852,0.028]],["M 143 -598L 143 94L 170 94C 244 94 288 61 288 51L 288 -598L 302 -598L 143 -656Z",[-0.002,0.798]],["M 233 -419L 233 -391L 761 -391L 761 -419Z",[-0.864,0.009]],["M 233 -598L 233 -570L 761 -570L 761 -598Z",[-0.779,0.012]],["M 416 -743L 416 -225L 563 -225L 563 -743Z",[0.002,0.711]],["M 699 -598L 699 -88C 699 -75 695 -67 678 -67C 655 -67 545 -74 545 -74L 545 -61C 600 -51 621 -35 638 -13C 656 9 661 43 665 91C 824 77 846 24 846 -71L 846 -543C 869 -548 883 -558 891 -568L 754 -673L 688 -598Z",[0.059,0.752]]],"bbox":{"top":-852,"bottom":94,"left":21,"right":989},"hadv":1000}],"text":"再","hadv":1000,"breakAfter":true},{"chars":[{"char":"见","components":[["M 604 -674L 419 -691C 417 -375 433 -123 24 81L 32 94C 558 -63 556 -329 568 -647C 592 -650 602 -660 604 -674Z",[0.304,0.679]],["M 162 -846L 162 -227L 190 -227C 267 -227 313 -253 313 -263L 313 -759L 701 -759L 701 -242L 729 -242C 811 -242 860 -270 860 -278L 860 -747C 884 -751 894 -759 901 -769L 770 -871L 696 -787L 324 -787Z",[0.353,0.021]],["M 680 -385L 509 -399L 509 -49C 509 45 537 67 651 67L 753 67C 925 67 978 40 978 -18C 978 -44 970 -60 934 -75L 931 -246L 921 -246C 895 -166 876 -107 862 -83C 855 -70 851 -66 835 -65C 822 -64 797 -64 769 -64L 681 -64C 653 -64 647 -69 647 -85L 647 -359C 669 -362 678 -372 680 -385Z",[-0.289,0.252]]],"bbox":{"top":-871,"bottom":94,"left":24,"right":978},"hadv":1000}],"text":"见","hadv":1000,"breakAfter":false},{"chars":[{"char":"，","components":[["M 163 54C 118 38 39 11 39 -64C 39 -113 78 -157 135 -157C 190 -157 237 -117 237 -41C 237 60 187 180 56 236L 39 203C 122 162 155 101 163 54Z",[0.017,0.495]]],"bbox":{"top":-157,"bottom":236,"left":39,"right":237},"hadv":1000}],"text":"，","hadv":1000,"breakAfter":true},{"chars":[{"char":"你","components":[["M 204 -856C 169 -661 90 -460 11 -332L 22 -325C 165 -426 276 -572 355 -778C 378 -777 391 -786 396 -799Z",[0.328,0.656]],["M 139 -519L 139 92L 166 92C 223 92 282 62 284 52L 284 -524C 304 -528 312 -535 315 -544L 192 -589Z",[0.011,0.778]],["M 420 -469C 397 -331 349 -185 300 -92L 312 -84C 410 -154 493 -259 554 -395C 577 -395 590 -403 594 -416Z",[0.312,0.593]],["M 464 -853C 433 -698 370 -536 308 -435L 319 -427C 437 -503 534 -614 606 -766C 629 -764 643 -772 648 -785Z",[0.336,0.605]],["M 580 -616L 580 -80C 580 -69 575 -64 560 -64C 538 -64 430 -70 430 -70L 430 -57C 483 -47 504 -32 521 -9C 538 13 543 47 547 94C 702 80 723 27 723 -70L 723 -573C 746 -577 756 -586 758 -601Z",[0.061,0.749]],["M 453 -653L 453 -625L 866 -625L 866 -653Z",[-0.772,0.022]],["M 756 -457L 746 -452C 788 -356 831 -240 840 -132C 975 -9 1096 -292 756 -457Z",[-0.194,0.461]],["M 806 -653C 804 -606 796 -528 787 -476L 794 -470C 847 -501 912 -555 950 -595C 972 -596 982 -599 990 -608L 866 -725L 794 -653Z",[0.249,0.392]]],"bbox":{"top":-856,"bottom":94,"left":11,"right":1096},"hadv":1000}],"text":"你","hadv":1000,"breakAfter":true},{"chars":[{"char":"好","components":[["M 309 -612L 321 -612C 301 -339 234 -76 16 82L 25 92C 341 -42 421 -294 455 -560C 478 -564 488 -568 495 -579L 376 -683Z",[0.295,0.74]],["M 395 -612L 20 -612L 29 -584L 395 -584Z",[-0.849,0.012]],["M 73 -302L 52 -284C 162 -219 289 -107 347 -3C 462 72 652 -151 73 -302Z",[-0.561,0.43]],["M 52 -284L 168 -248C 229 -419 296 -700 321 -816L 303 -801C 347 -800 355 -813 358 -826L 186 -856C 172 -739 100 -426 52 -284Z",[0.196,0.754]],["M 830 -758L 412 -758L 421 -730L 830 -730Z",[0.609,0.024]],["M 866 -500L 796 -403L 429 -403L 437 -375L 963 -375C 978 -375 989 -380 992 -391C 946 -435 866 -500 866 -500Z",[0.789,0.085]],["M 780 -556L 604 -571L 604 -71C 604 -61 599 -56 585 -56C 565 -56 465 -62 465 -62L 465 -49C 516 -40 535 -25 551 -3C 566 18 571 51 574 96C 724 83 745 32 745 -63L 745 -529C 768 -532 778 -541 780 -556Z",[0.059,0.749]],["M 771 -758L 783 -758C 760 -705 709 -595 670 -535L 681 -535C 762 -579 863 -655 928 -707C 951 -708 961 -711 969 -720L 846 -830Z",[0.408,0.397]]],"bbox":{"top":-856,"bottom":96,"left":16,"right":992},"hadv":1000}],"text":"好","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>刚刚跑去看了本年最后一场《你的名字》（沉迷三叶不能自拔），看着电影院都纷纷把它下线了，应该是我最后一次在电影院里看了，于是把<a href=\"your-name\">你是谁？</a>结了尾。顺便提一句，双安对面的 UME 音响不错。</p>\n<p>于是又是一年过去，到了下次换年份的时候，我已经是大学生了，真是唏嘘。这一年里，秉持着以玩为主，学习为辅的宗旨，我又把自己的智力和心理年龄减小了几岁，现在回到了小学生的水平。和朋友在一起，生活每天很幸福，很满足，是本年度最大收获。重新玩了一年的 osu，现在可以在学校里吹比，算是第二。十年 OI 一场空，今年送分只送了 120 分没送够，意外拿到了省一，算是第三。</p>\n<p>然而渐渐地开始想，做了很多的事情，有些希望为别人做出一些贡献，有些希望给自己积累一点经验，最后总归只是用于玩乐了。在实验室里扯些似是非是的课，到底是在给他们展示更大的世界呢，还是在他们身上强加我自己的乐趣和理想呢？他们不过是孩子而已啊。原来的班主任，现高一学部主任嘱咐了整整一个年级的人不要学我，倒是出名了，不过也莫名其妙背负了些责任呢。从初中开始，社团，创客，实验室里，那些莫名其妙，或是倍感无聊的表情，还历历在目啊。而我却要毕业了，没什么时间去补救了。</p>\n<p>但是生活要继续，我还要去寻找那个命中注定的人，寻找我自己的幸福。还有充满青春的梦想作为活下去的动力，其实是挺幸福的一件事，不知道我还能享受多久呢。</p>\n<p>电脑的时钟已经跳到 2017/1/1 了，就写到这里吧。</p>\n<p><em>妈蛋，本来想整点发的，结果服务器崩了，还要上去 Hotfix，服气服气。</em></p>\n<p><em>服务器在日本，时间还是在昨天… WTF?</em></p>\n<p><em>其实不是，是我按照 UTC 解析了…</em></p>\n<p><em>修好了，嘻嘻</em></p>\n","plain":"刚刚跑去看了本年最后一场《你的名字》（沉迷三叶不能自拔），看着电影院都纷纷把它下线了，应该是我最后一次在电影院里看了，于是把你是谁？结了尾。顺便提一句，双安对面的 UME 音响不错。\n于是又是一年过去，到了下次换年份的时候，我已经是大学生了，真是唏嘘。这一年里，秉持着以玩为主，学习为辅的宗旨，我又把自己的智力和心理年龄减小了几岁，现在回到了小学生的水平。和朋友在一起，生活每天很幸福，很满足，是本年度最大收获。重新玩了一年的 osu，现在可以在学校里吹比，算是第二。十年 OI 一场空，今年送分只送了 120 分没送够，意外拿到了省一，算是第三。\n然而渐渐地开始想，做了很多的事情，有些希望为别人做出一些贡献，有些希望给自己积累一点经验，最后总归只是用于玩乐了。在实验室里扯些似是非是的课，到底是在给他们展示更大的世界呢，还是在他们身上强加我自己的乐趣和理想呢？他们不过是孩子而已啊。原来的班主任，现高一学部主任嘱咐了整整一个年级的人不要学我，倒是出名了，不过也莫名其妙背负了些责任呢。从初中开始，社团，创客，实验室里，那些莫名其妙，或是倍感无聊的表情，还历历在目啊。而我却要毕业了，没什么时间去补救了。\n但是生活要继续，我还要去寻找那个命中注定的人，寻找我自己的幸福。还有充满青春的梦想作为活下去的动力，其实是挺幸福的一件事，不知道我还能享受多久呢。\n电脑的时钟已经跳到 2017/1/1 了，就写到这里吧。\n妈蛋，本来想整点发的，结果服务器崩了，还要上去 Hotfix，服气服气。\n服务器在日本，时间还是在昨天… WTF?\n其实不是，是我按照 UTC 解析了…\n修好了，嘻嘻\n"},{"metadata":{"id":"your-name","lang":"zh-CN","title":"你是谁？","tags":["中二病治疗","君の名は。"],"publish_time":"2016-12-03T15:11:21.351Z","update_time":"2017-01-27T12:34:46.658Z","title_outline":{"groups":[{"chars":[{"char":"你","components":[["M 204 -856C 169 -661 90 -460 11 -332L 22 -325C 165 -426 276 -572 355 -778C 378 -777 391 -786 396 -799Z",[0.328,0.656]],["M 139 -519L 139 92L 166 92C 223 92 282 62 284 52L 284 -524C 304 -528 312 -535 315 -544L 192 -589Z",[0.011,0.778]],["M 420 -469C 397 -331 349 -185 300 -92L 312 -84C 410 -154 493 -259 554 -395C 577 -395 590 -403 594 -416Z",[0.312,0.593]],["M 464 -853C 433 -698 370 -536 308 -435L 319 -427C 437 -503 534 -614 606 -766C 629 -764 643 -772 648 -785Z",[0.336,0.605]],["M 580 -616L 580 -80C 580 -69 575 -64 560 -64C 538 -64 430 -70 430 -70L 430 -57C 483 -47 504 -32 521 -9C 538 13 543 47 547 94C 702 80 723 27 723 -70L 723 -573C 746 -577 756 -586 758 -601Z",[0.061,0.749]],["M 453 -653L 453 -625L 866 -625L 866 -653Z",[-0.772,0.022]],["M 756 -457L 746 -452C 788 -356 831 -240 840 -132C 975 -9 1096 -292 756 -457Z",[-0.194,0.461]],["M 806 -653C 804 -606 796 -528 787 -476L 794 -470C 847 -501 912 -555 950 -595C 972 -596 982 -599 990 -608L 866 -725L 794 -653Z",[0.249,0.392]]],"bbox":{"top":-856,"bottom":94,"left":11,"right":1096},"hadv":1000}],"text":"你","hadv":1000,"breakAfter":true},{"chars":[{"char":"是","components":[["M 205 -314C 199 -187 158 -27 13 84L 19 93C 239 16 326 -118 360 -256C 386 -256 396 -266 399 -281Z",[0.363,0.569]],["M 27 -385L 35 -357L 946 -357C 961 -357 972 -362 975 -373C 928 -417 848 -483 848 -483L 777 -385Z",[0.967,0.034]],["M 188 -778L 188 -409L 210 -409C 273 -409 341 -442 341 -456L 341 -750L 726 -750L 726 -778L 349 -778L 188 -839Z",[0.231,0.244]],["M 262 -646L 262 -618L 732 -618L 732 -646Z",[-0.813,0.013]],["M 262 -512L 262 -484L 732 -484L 732 -512Z",[-0.786,0.018]],["M 293 -192L 285 -188C 332 25 429 78 628 78C 691 78 849 78 911 78C 911 24 931 -25 975 -36L 975 -47C 894 -45 706 -45 630 -45C 446 -45 354 -63 293 -192Z",[-0.759,0.089]],["M 435 -385L 435 -22L 589 13L 589 -385Z",[-0.009,0.587]],["M 501 -220L 501 -192L 859 -192C 874 -192 886 -197 889 -208C 837 -255 749 -325 749 -325L 672 -220Z",[0.681,0.092]],["M 663 -778L 663 -429L 690 -429C 739 -429 816 -454 817 -461L 817 -726C 838 -730 850 -740 856 -748L 719 -851L 653 -778Z",[0.037,0.572]]],"bbox":{"top":-851,"bottom":93,"left":13,"right":975},"hadv":1000}],"text":"是","hadv":1000,"breakAfter":true},{"chars":[{"char":"谁","components":[["M 212 -575L 19 -575L 28 -547L 212 -547Z",[-0.654,0.01]],["M 86 -844L 78 -839C 112 -793 152 -726 166 -664C 288 -582 392 -812 86 -844Z",[-0.223,0.321]],["M 253 -549L 155 -549L 155 -139C 155 -116 147 -105 95 -75L 194 70C 223 50 255 -5 227 -90L 162 -36L 286 -88L 286 -530Z",[0.048,0.765]],["M 115 -75L 196 51C 286 -56 354 -159 385 -209L 380 -217C 273 -156 161 -96 115 -75Z",[0.439,0.407]],["M 157 -575L 155 -575L 155 -495L 286 -495L 286 -532L 277 -523C 311 -526 324 -535 331 -543L 219 -636Z",[0.044,0.079]],["M 633 -804L 444 -855C 428 -717 379 -502 301 -357L 310 -350C 452 -464 546 -645 597 -781C 623 -783 631 -793 633 -804Z",[0.293,0.668]],["M 530 55L 530 -643L 544 -643L 456 -675L 395 -565L 395 95L 420 95C 489 95 530 65 530 55Z",[0.009,0.828]],["M 831 -736L 764 -643L 448 -643L 448 -615L 923 -615C 938 -615 949 -620 951 -631C 907 -673 831 -736 831 -736Z",[0.676,0.104]],["M 854 -114L 785 -18L 455 -18L 455 10L 951 10C 965 10 977 5 979 -6C 933 -49 854 -114 854 -114Z",[0.827,0.069]],["M 814 -321L 751 -231L 459 -231L 459 -203L 898 -203C 912 -203 922 -208 925 -219C 885 -260 814 -321 814 -321Z",[0.811,0.074]],["M 814 -529L 751 -439L 459 -439L 459 -411L 898 -411C 912 -411 922 -416 925 -427C 885 -468 814 -529 814 -529Z",[0.772,0.081]],["M 603 -860L 595 -856C 619 -810 635 -746 630 -686C 746 -573 905 -798 603 -860Z",[0.002,0.332]],["M 748 -643L 615 -643L 615 4L 748 4Z",[0.005,0.775]]],"bbox":{"top":-860,"bottom":95,"left":19,"right":979},"hadv":1000}],"text":"谁","hadv":1000,"breakAfter":false},{"chars":[{"char":"？","components":[["M 183 -229L 221 -229L 225 -286C 228 -343 253 -360 330 -410C 428 -473 469 -525 469 -597C 469 -705 397 -771 245 -771C 105 -771 15 -698 13 -587C 27 -558 50 -549 79 -549C 134 -549 159 -564 186 -755L 120 -721C 161 -734 173 -735 207 -735C 271 -735 307 -688 307 -605C 307 -558 295 -521 245 -476C 186 -421 172 -385 172 -333C 172 -301 177 -261 183 -229Z",[-0.009,0.085]],["M 201 14C 249 14 286 -22 286 -68C 286 -114 249 -152 201 -152C 153 -152 117 -114 117 -68C 117 -22 153 14 201 14Z",[0.018,0.0]]],"bbox":{"top":-771,"bottom":14,"left":13,"right":469},"hadv":1000}],"text":"？","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.green {\n  color: rgba(0,75,0, 0.7);\n}\n.green-strikethrough {\n  color: rgb(0,150,0);\n  text-decoration: line-through;\n}\n.green-strikethrough > .black {\n  color: rgba(0,0,0,.3);\n}\n\n.red {\n  color: rgba(180, 0, 0, 0.7);\n}\n\n.red strong {\n  color: rgb(180, 0, 0);\n}\n\n.yellow {\n  color: rgba(150, 150, 0, 0.9);\n}\n\n.blue, .blue-list + li {\n  color: rgba(0, 75, 180, 0.7);\n}\n\n.gray {\n  color: rgba(0,0,0,.3);\n}\n</style>\n<p>月考过后去看了《你的名字。》，全程气喘吁吁，面色潮红，心跳加速，走出电影院还晕晕乎乎的，简直比看动作大片还刺激，十分的奇怪。虽然刚看完就想写点东西，无奈身上只带了一个 Kindle，等到公交车到了家，已经是半个小时之后的事情了，贤者模式早就消失不见，想写的东西也冷了下来，一点热乎气不剩了。想起了暑期学校那会，总想自己一定要写些什么，脑子里转来转去的，最后写下来，只剩下那点干巴巴的东西，感情什么的早就没了。现在和那时候感觉差不多。</p>\n<p>然而还是要写，要不睡不好觉的。</p>\n<p>当然，以下肯定会有剧透的，请适量食用。如果你是来找关于作画，声优，剧情之类评论的，那就去豆瓣吧，我毛都不懂，这里只有胡言乱语。</p>\n<p><span class=\"green\">过了一天又去看了一遍，看出了一些新东西，还遇到了一些新事情，用绿色标出的都是在第二次看完后的更新。</span></p>\n<p><span class=\"red\">今天12月10号，又去看了一遍，简直<strong>着魔</strong>。小说也已经定了，正好期末考完试到货，嘻嘻。</span></p>\n<p><span class=\"yellow\">12月25号，圣诞节四刷。想定繁中的外传和设定集了。听说有个学弟 12 刷，不得不佩服。</span></p>\n<p><span class=\"blue\">12月31号，最后去影院看一次。晚场从九点到十一点，人还是满的，也听得出来有很多很多看过再来的人。天闻角川的小说是在 Amazon 上买的，居然要到15号才发货。淘宝订的朋友有不少已经收到货了，我可是二号就订货的第一批顾客啊！而且外传说是拿了版权，出版还不见影子，等不及了，31号中午还是下了决心买了繁中的小说和外传，就等送到了。OST CD 正在从上海飞往北京的过程中。</span></p>\n<p><span class=\"blue\">蓝色字的，都是我在看完电影后，想说的最后一点话了。</span></p>\n<p><span class=\"gray\">嘛，其实最后十五号（考试后）和二十七号（除夕）又去看了两次，嘿嘿嘿…又写了一点东西在<a href=\"your-name-earthbound\">关于君名外传</a>里。</span></p>\n<h2>少女心</h2>\n<p>不知怎么地，就是很喜欢新海诚这种套路。明明白白的催泪弹，说甩就甩，毫不墨迹。虽然不讨厌欧美英雄大片，同时也不喜欢欧美的爱情片，有点太露骨。《你的名字》正正好，激发了我的少女心。</p>\n<p>想起了《秒五》，之前在老家看的，一个人坐在炕上拿个笔记本，看完了《秒五》看完了《花名》，然后水土不服吐了一晚上没睡着觉。倒是这次不需要炸火车，反而应该感谢东京发达的轨道交通系统，让二人有机会碰一下面。就是没看清楚，碰面的时候三叶有没有戴上戒指呢。看 P 站的风气大概没有。</p>\n<p><span class=\"green\">的确没有。</span></p>\n<p>还有，按照剧情来说，三叶应该比泷要大三岁呢。大姐姐的魅力，在三叶身上不会有吧，永远的十七岁。</p>\n<h2>拯救世界</h2>\n<p>泷拯救世界的方法也是蛮孩子气的。炸电站，偷广播，做法像敌后特工队，随心所欲的感觉让我想到了哆啦A梦，或者革命机。</p>\n<p>至于动机呢，因为“不能忘记之人”。某著名科幻电影《The 矩阵》中著名计算机大佬 <em>那一人</em>，被他所在公司的架构师称赞为 <em>为了小爱，而不是大爱的救世主</em>，真的有点类似。</p>\n<p>欧美英雄大片当中，要是出现这种场景，三叶大概是难逃一死了，泷还要忍痛继续为糸守町的村民们谋福利，最后成功，然后要深藏功与名。看了这个电影，感觉 Woc 真帅我也要当超级英雄，然而却不知道能不能承受这种痛苦，最后决定还是把他们当做崇拜的对象好了，这是给最血气方刚的男同胞们写的童话。</p>\n<p>其实我挺想知道的，在村民们逃过一劫后，三叶是怎么跟他爹解释自己超凡脱俗的预知能力，然后安静地生活下去呢？</p>\n<p>I’m Batman?</p>\n<p>倒是像因为这件事情而不得不逃离村子而前往东京一样。</p>\n<h2>看彗星</h2>\n<p>坐公交车回家的路上，一直看着前面排队的车后车窗反射的 201 字样。站在我旁边的人每到一站，就一定要喊一句话，类似</p>\n<blockquote>\n<p>中关园到了，请从后门下车er~</p>\n<p>中关园北到了，请从后门下车er~</p>\n<p>清华园西门到了，请从后门下车er~</p>\n</blockquote>\n<p>直到我从后门儿下车为止。终于，我走到后门附近的时候他转过身，让我有机会看到了他身后衣服上 <code>车辆调度员</code> 的字样。</p>\n<p>原来是下班回家坐在平常自己调度的公交车上，也不知道是不是为了博人发笑而说出这样的话，毕竟说是职业习惯有点牵强。倒是他的存在让我这一路感受到了车厢中快活的空气，感受到了这个城市一点可爱的地方。从别人的痛苦和寂寞中抽取快乐这一传统，看来一直没有消失，遗传到了我的身上，然后以另一种方式表现出来。</p>\n<p>所以说，到底是不同的人在不同的时间为这个世界承担了寂寞，还是特定的人在为其他人承担寂寞呢？</p>\n<p>很喜欢在晚上一个人瞎溜达，到天桥上看连绵不断的路灯组成的山峰山谷，到没有灯没有人的地方抬头看星星，感受白天感受不到的东西。白天的北京不是烟雾萦绕，就是阳光刺眼。春天到处都是絮，令人舒服的日子只有在初秋有，再晚一些就要挂冷风了，但是北京的秋天又短到不能再短。</p>\n<p>所以喜欢晚上。要是有雾霾，可以复习丁达尔现象，看城市在一片光晕里面，只是不能跑步了，不是很爽快。晴朗的日子能看月亮——前几天的月亮就很好看，细溜溜一个月牙，不早不晚正好随着夜晚转到北京上空，又在我放学的后一刻挂在地平线上。更平常的时候能看星星，钻到一个角落里，虽然看不到太多，但是还是能认出来星座的。泷和三叶能够跨过时间相遇，在远处发光的那个东西，也穿过了时间向我们展示它的存在，发出的那几个光子正好飞到了我的眼睛里面，与我相遇，挺有趣的。</p>\n<p>偶尔的，在晚上还能看到一些特别的场景。半夜三点在中关村北大街辅路上滑滑板的大哥哥，刚刚下班的初创公司员工，呼啸而过根本不看红绿灯的急救车，这些都在展示这个城市中人的少数，说这个城市是自己活着的，不是拥拥挤挤的，像被胁迫的。</p>\n<p>我的感觉，这些黑暗中的东西，キラキラ的，就像那颗彗星一样，真漂亮，虽然黑暗也会意外地带来死亡。<span class=\"green-strikethrough\"><span class=\"black\">谁知到呢，一千四百年一次，每次都分裂开砸中同一个地方，也说不定是命中注定，宫水家的传统或许就是这么来的。</span></span></p>\n<p><span class=\"green\">十分服气，我已经瞎了，暗示了至少有三四次我都没看出来…还有关于黄昏之时，最后还十分蒙蔽，看第二遍才明白…</span></p>\n<h2>笑着</h2>\n<p>硬要分，《你的名字。》搞笑成分占 50%，电影院里坐我们前面的两个妹子嚼着爆米花，咯咯咯地笑，笑完了叽叽喳喳的说一通。</p>\n<p>三叶和泷最后相遇，故事结束了，把他们未来的幸福留给我自己去猜，算是制作组的一大恩惠。以及最后，村子里的人都找到了新的生活，那老一对居然能坚持下来，还起到了点化泷的作用，着实令人震惊。</p>\n<p>这是我对《你的名字。》总体的感想。杂杂乱乱的写了一堆，很多想抓住的还没抓住，估计以后还会继续加进来吧。</p>\n<h2 class=\"green\">（我在）胡说八道</h2>\n<p>第二遍看完，对一些剧情有了深一点的理解，也总算是冷静了冷静。彗星一千两百年回归一次，系守湖之前就是由同一颗彗星分裂砸出来的，一可以从一千两百这个敏感的数字看出，一可以从神殿天顶的绘画看出，一可以从泷摔晕的时候一副彗星分裂坠落的画面看出——那个时候彗星砸中的地方还没有湖呢，大概说的就是上一次坠落。</p>\n<p>照这么来看，要么这个彗星十分年轻，不足两千四百岁。两千四百年刚刚出现的这个通灵的彗星就被我们的三叶和泷碰见了，概率挺低的。那就是跟村子里的人有仇，盖一个村子砸一个村子。无论如何，都是缘分，命中注定，真好。</p>\n<p>扩展开来，既然宫水家的人都会有做梦与别人交换身体的体验，那说明也都是有这份缘分的了。三叶的爸爸，我们的好村长，居然一点都不知道，而且三叶奶奶一叶也说是全部忘记了，大概是因为都没有最后到一起吧，或许是因为就差这一颗彗星。</p>\n<p>当然，可以说是因为每次都有世界线的变更，而且他们也不是观测者，所以记不得。但是从一些细节可以看出，遗忘的原因也包含来源于自身的动摇，和作为梦的特性。泷小哥手机里的日记不也是在没有出去乱转之前一直没丢嘛，这过程中世界线肯定变了，反而是在看到了化为废墟的村子后才产生怀疑然后消失的。同样的，之前三叶这个名字也是记得很好，看到死者名册，怀疑那些经历是自己的幻觉之后才忘记的。三叶反而倒是一直没忘，都因为这件事跑到东京去了，但是最后还是忘了。但是站在山顶上的泷小哥啥都不想忘，意志坚定的不得了，然而也忘光了，于是说不清。</p>\n<p>或许也可以说，是因为长大了，所以梦醒了，但也不会那么突然。最后只能说，这一直是神冥冥之中的指引。神的事情，那就没什么好说的了，到了特定的时候就会有特定的事情发生，自然有道理，关我们什么事情。</p>\n<p>或者说，是两人不能相遇吧。当泷占到操场上的那一刻开始，遗忘就在进行中了。而三叶也是在黄昏之时见到（小弟弟）泷之后就开始忘事了。那还真是蛮惨的。</p>\n<p>太绝情了，既然怎么都说不通，不如说是皂滑弄人，等到二人相见相认后，这些记忆都会回来吧。</p>\n<p>豆瓣上某大神 citywetec 给出了一个合理的解答：</p>\n<blockquote>\n<p>一叶(奶奶)说跨越时空，要献给神明最珍贵的东西。因为泷偷喝了三叶的口嚼酒，神明从三叶与泷取走的了他们对彼此的记忆。</p>\n</blockquote>\n<p>然而还是不能说的特别明白…估计要等我把小说看完吧。</p>\n<h2 class=\"blue\">一些更多的胡说八道</h2>\n<p>五刷注意到了好多挺好玩的地方：</p>\n<ul>\n<li>泷在跟前辈说谎的时候手的动作和在黄昏之时说“只摸了一次”的动作一模一样。这小伙子还真是藏不住真心啊。</li>\n<li>在镇长做演说的时候，旁边停了辆车，是后来高山拉面店主开的车。高山观测站指高中。高山拉面店主很像最后早耶香 <em>被带走</em> 的时候身后的男老师。综上所述，应该是这个老师在高中躲过了彗星，后来成为店主。但是根据漫画，店主当天应该是因为堵车所以没回到镇子里，不知道是不是矛盾了，还是店主另有其人。</li>\n<li>泷在画村子全景的过程中换了数身衣服，从短袖校服到外套校服，到兜帽衫，最后穿上了冲风衣才出门。其他人也是从夏秋之交的衣服换成了冬天的衣服。由此看来，要不就是这幅画居然画了至少一个月（还是之前用三叶的身体画过一次以后），要不就是断断续续的一点一点画完的。总之，泷这一个多月都是心不在焉，上学不听课，沉迷三叶不能自拔。</li>\n<li>三叶你把泷的包丢在神体那里了啊！一天过后的泷也是什么都不记得了。所以耗费泷一个多月心血的画作们就这样遗失了。</li>\n</ul>\n<h2 class=\"blue\">关于我自己</h2>\n<p>于是进电影院一共看了五遍之多，演职员表也整整看着滚完了五次，到了最后一次依旧还是在兴奋中起身离开。</p>\n<p>究其原因，大概是因为向往，向往二人的相遇，相依，相恋。总之，少了什么就想要什么，得不到就好奇别人得到是什么样子，虽然其他人都在说，这很假，这太理想，这很可笑，但是还是固执的觉得很漂亮，而不能放手了。我大概还没有到那个看到少年少女的爱情能心静如水的年龄。我倒是很满足于现状，希望能够永远这么幼稚下去。</p>\n<p>爱情之外，日常之中，二人将对方作为自己的半身，这样的依靠和安全感，说不定才是我真正想要的东西吧。三叶曾经评价妹妹说“没到青春期的小孩子无忧无虑真好呢”，而身担重负的三叶自己在漫画里对泷和泷的爸爸才能表现出自己少女的一面。说不定我在他人眼里是和三叶一样的孤单呢。</p>\n<p>但是我却又羡慕泷的独立，还羡慕三叶那像画里的小镇，稍稍有点贪心了。我睡觉很少做梦，为了弥补，只能醒着做白日梦。在还是孩子的时候就有很多的梦想，说实话说不定比现在我的梦想还要切合实际，然而到现在也一个一个都不记得了。同样的，一些亲密无间的朋友已经不再联系，一些暗恋的女孩子也毫不关心了。组成我生活的一点一滴，都被时间一点一点掏空，直到现在的我回头重新寻找的时候，才能凭借一点点痕迹去想象当时感到的温暖。就像新海诚监督说的：</p>\n<blockquote>\n<p>人会忘记许多事情，包括’喜欢’这样一种情感，但我们要挣扎着努力不要忘记，然后坚强地活下去</p>\n</blockquote>\n<p>还有一点，就是在眼前的“非日常”带来的欣喜了。上面“看彗星”那一节虽说是胡扯，后来看来看去却越有一点这样的意思。仔细想来，两个人一个月中一半时间活在对方的世界里，那已经是他们真正的日常的一部分了，却在我们眼里是那样的惊艳，就像三叶对于泷早就以习为常的城市生活和朋友家人感到的惊艳一样。还有影片接近结尾，彗星落下的一段，最后一个播音员的声音却莫名其妙的让我有点泪目了。他的话大概是：“能有机会目睹这样的奇观，大概是生活在这个时代的我们的一种很大的幸运吧。”然而，毁灭的镇子和彗星的出现，在几年后已经被忙碌的人们淡忘了。我们的平凡生活，是不是在其他人的梦里才能出现呢？</p>\n<p>总之，我想说的是：</p>\n<blockquote>\n<p>我们在日常生活中度过的每一天，实际上也许是连续发生的奇迹也说不定呢。</p>\n</blockquote>\n<p>希望我们每个人都可以从自己身边挖掘出更多的幸福，并永远握在手心，不要忘记。</p>\n","plain":"月考过后去看了《你的名字。》，全程气喘吁吁，面色潮红，心跳加速，走出电影院还晕晕乎乎的，简直比看动作大片还刺激，十分的奇怪。虽然刚看完就想写点东西，无奈身上只带了一个 Kindle，等到公交车到了家，已经是半个小时之后的事情了，贤者模式早就消失不见，想写的东西也冷了下来，一点热乎气不剩了。想起了暑期学校那会，总想自己一定要写些什么，脑子里转来转去的，最后写下来，只剩下那点干巴巴的东西，感情什么的早就没了。现在和那时候感觉差不多。\n然而还是要写，要不睡不好觉的。\n当然，以下肯定会有剧透的，请适量食用。如果你是来找关于作画，声优，剧情之类评论的，那就去豆瓣吧，我毛都不懂，这里只有胡言乱语。\n过了一天又去看了一遍，看出了一些新东西，还遇到了一些新事情，用绿色标出的都是在第二次看完后的更新。\n今天12月10号，又去看了一遍，简直着魔。小说也已经定了，正好期末考完试到货，嘻嘻。\n12月25号，圣诞节四刷。想定繁中的外传和设定集了。听说有个学弟 12 刷，不得不佩服。\n12月31号，最后去影院看一次。晚场从九点到十一点，人还是满的，也听得出来有很多很多看过再来的人。天闻角川的小说是在 Amazon 上买的，居然要到15号才发货。淘宝订的朋友有不少已经收到货了，我可是二号就订货的第一批顾客啊！而且外传说是拿了版权，出版还不见影子，等不及了，31号中午还是下了决心买了繁中的小说和外传，就等送到了。OST CD 正在从上海飞往北京的过程中。\n蓝色字的，都是我在看完电影后，想说的最后一点话了。\n嘛，其实最后十五号（考试后）和二十七号（除夕）又去看了两次，嘿嘿嘿…又写了一点东西在关于君名外传里。\n\n少女心\n不知怎么地，就是很喜欢新海诚这种套路。明明白白的催泪弹，说甩就甩，毫不墨迹。虽然不讨厌欧美英雄大片，同时也不喜欢欧美的爱情片，有点太露骨。《你的名字》正正好，激发了我的少女心。\n想起了《秒五》，之前在老家看的，一个人坐在炕上拿个笔记本，看完了《秒五》看完了《花名》，然后水土不服吐了一晚上没睡着觉。倒是这次不需要炸火车，反而应该感谢东京发达的轨道交通系统，让二人有机会碰一下面。就是没看清楚，碰面的时候三叶有没有戴上戒指呢。看 P 站的风气大概没有。\n的确没有。\n还有，按照剧情来说，三叶应该比泷要大三岁呢。大姐姐的魅力，在三叶身上不会有吧，永远的十七岁。\n\n拯救世界\n泷拯救世界的方法也是蛮孩子气的。炸电站，偷广播，做法像敌后特工队，随心所欲的感觉让我想到了哆啦A梦，或者革命机。\n至于动机呢，因为“不能忘记之人”。某著名科幻电影《The 矩阵》中著名计算机大佬 那一人，被他所在公司的架构师称赞为 为了小爱，而不是大爱的救世主，真的有点类似。\n欧美英雄大片当中，要是出现这种场景，三叶大概是难逃一死了，泷还要忍痛继续为糸守町的村民们谋福利，最后成功，然后要深藏功与名。看了这个电影，感觉 Woc 真帅我也要当超级英雄，然而却不知道能不能承受这种痛苦，最后决定还是把他们当做崇拜的对象好了，这是给最血气方刚的男同胞们写的童话。\n其实我挺想知道的，在村民们逃过一劫后，三叶是怎么跟他爹解释自己超凡脱俗的预知能力，然后安静地生活下去呢？\nI’m Batman?\n倒是像因为这件事情而不得不逃离村子而前往东京一样。\n\n看彗星\n坐公交车回家的路上，一直看着前面排队的车后车窗反射的 201 字样。站在我旁边的人每到一站，就一定要喊一句话，类似\n中关园到了，请从后门下车er~\n中关园北到了，请从后门下车er~\n清华园西门到了，请从后门下车er~\n\n直到我从后门儿下车为止。终于，我走到后门附近的时候他转过身，让我有机会看到了他身后衣服上 车辆调度员 的字样。\n原来是下班回家坐在平常自己调度的公交车上，也不知道是不是为了博人发笑而说出这样的话，毕竟说是职业习惯有点牵强。倒是他的存在让我这一路感受到了车厢中快活的空气，感受到了这个城市一点可爱的地方。从别人的痛苦和寂寞中抽取快乐这一传统，看来一直没有消失，遗传到了我的身上，然后以另一种方式表现出来。\n所以说，到底是不同的人在不同的时间为这个世界承担了寂寞，还是特定的人在为其他人承担寂寞呢？\n很喜欢在晚上一个人瞎溜达，到天桥上看连绵不断的路灯组成的山峰山谷，到没有灯没有人的地方抬头看星星，感受白天感受不到的东西。白天的北京不是烟雾萦绕，就是阳光刺眼。春天到处都是絮，令人舒服的日子只有在初秋有，再晚一些就要挂冷风了，但是北京的秋天又短到不能再短。\n所以喜欢晚上。要是有雾霾，可以复习丁达尔现象，看城市在一片光晕里面，只是不能跑步了，不是很爽快。晴朗的日子能看月亮——前几天的月亮就很好看，细溜溜一个月牙，不早不晚正好随着夜晚转到北京上空，又在我放学的后一刻挂在地平线上。更平常的时候能看星星，钻到一个角落里，虽然看不到太多，但是还是能认出来星座的。泷和三叶能够跨过时间相遇，在远处发光的那个东西，也穿过了时间向我们展示它的存在，发出的那几个光子正好飞到了我的眼睛里面，与我相遇，挺有趣的。\n偶尔的，在晚上还能看到一些特别的场景。半夜三点在中关村北大街辅路上滑滑板的大哥哥，刚刚下班的初创公司员工，呼啸而过根本不看红绿灯的急救车，这些都在展示这个城市中人的少数，说这个城市是自己活着的，不是拥拥挤挤的，像被胁迫的。\n我的感觉，这些黑暗中的东西，キラキラ的，就像那颗彗星一样，真漂亮，虽然黑暗也会意外地带来死亡。谁知到呢，一千四百年一次，每次都分裂开砸中同一个地方，也说不定是命中注定，宫水家的传统或许就是这么来的。\n十分服气，我已经瞎了，暗示了至少有三四次我都没看出来…还有关于黄昏之时，最后还十分蒙蔽，看第二遍才明白…\n\n笑着\n硬要分，《你的名字。》搞笑成分占 50%，电影院里坐我们前面的两个妹子嚼着爆米花，咯咯咯地笑，笑完了叽叽喳喳的说一通。\n三叶和泷最后相遇，故事结束了，把他们未来的幸福留给我自己去猜，算是制作组的一大恩惠。以及最后，村子里的人都找到了新的生活，那老一对居然能坚持下来，还起到了点化泷的作用，着实令人震惊。\n这是我对《你的名字。》总体的感想。杂杂乱乱的写了一堆，很多想抓住的还没抓住，估计以后还会继续加进来吧。\n第二遍看完，对一些剧情有了深一点的理解，也总算是冷静了冷静。彗星一千两百年回归一次，系守湖之前就是由同一颗彗星分裂砸出来的，一可以从一千两百这个敏感的数字看出，一可以从神殿天顶的绘画看出，一可以从泷摔晕的时候一副彗星分裂坠落的画面看出——那个时候彗星砸中的地方还没有湖呢，大概说的就是上一次坠落。\n照这么来看，要么这个彗星十分年轻，不足两千四百岁。两千四百年刚刚出现的这个通灵的彗星就被我们的三叶和泷碰见了，概率挺低的。那就是跟村子里的人有仇，盖一个村子砸一个村子。无论如何，都是缘分，命中注定，真好。\n扩展开来，既然宫水家的人都会有做梦与别人交换身体的体验，那说明也都是有这份缘分的了。三叶的爸爸，我们的好村长，居然一点都不知道，而且三叶奶奶一叶也说是全部忘记了，大概是因为都没有最后到一起吧，或许是因为就差这一颗彗星。\n当然，可以说是因为每次都有世界线的变更，而且他们也不是观测者，所以记不得。但是从一些细节可以看出，遗忘的原因也包含来源于自身的动摇，和作为梦的特性。泷小哥手机里的日记不也是在没有出去乱转之前一直没丢嘛，这过程中世界线肯定变了，反而是在看到了化为废墟的村子后才产生怀疑然后消失的。同样的，之前三叶这个名字也是记得很好，看到死者名册，怀疑那些经历是自己的幻觉之后才忘记的。三叶反而倒是一直没忘，都因为这件事跑到东京去了，但是最后还是忘了。但是站在山顶上的泷小哥啥都不想忘，意志坚定的不得了，然而也忘光了，于是说不清。\n或许也可以说，是因为长大了，所以梦醒了，但也不会那么突然。最后只能说，这一直是神冥冥之中的指引。神的事情，那就没什么好说的了，到了特定的时候就会有特定的事情发生，自然有道理，关我们什么事情。\n或者说，是两人不能相遇吧。当泷占到操场上的那一刻开始，遗忘就在进行中了。而三叶也是在黄昏之时见到（小弟弟）泷之后就开始忘事了。那还真是蛮惨的。\n太绝情了，既然怎么都说不通，不如说是皂滑弄人，等到二人相见相认后，这些记忆都会回来吧。\n豆瓣上某大神 citywetec 给出了一个合理的解答：\n一叶(奶奶)说跨越时空，要献给神明最珍贵的东西。因为泷偷喝了三叶的口嚼酒，神明从三叶与泷取走的了他们对彼此的记忆。\n\n然而还是不能说的特别明白…估计要等我把小说看完吧。\n五刷注意到了好多挺好玩的地方：\n- 泷在跟前辈说谎的时候手的动作和在黄昏之时说“只摸了一次”的动作一模一样。这小伙子还真是藏不住真心啊。\n- 在镇长做演说的时候，旁边停了辆车，是后来高山拉面店主开的车。高山观测站指高中。高山拉面店主很像最后早耶香 被带走 的时候身后的男老师。综上所述，应该是这个老师在高中躲过了彗星，后来成为店主。但是根据漫画，店主当天应该是因为堵车所以没回到镇子里，不知道是不是矛盾了，还是店主另有其人。\n- 泷在画村子全景的过程中换了数身衣服，从短袖校服到外套校服，到兜帽衫，最后穿上了冲风衣才出门。其他人也是从夏秋之交的衣服换成了冬天的衣服。由此看来，要不就是这幅画居然画了至少一个月（还是之前用三叶的身体画过一次以后），要不就是断断续续的一点一点画完的。总之，泷这一个多月都是心不在焉，上学不听课，沉迷三叶不能自拔。\n- 三叶你把泷的包丢在神体那里了啊！一天过后的泷也是什么都不记得了。所以耗费泷一个多月心血的画作们就这样遗失了。\n于是进电影院一共看了五遍之多，演职员表也整整看着滚完了五次，到了最后一次依旧还是在兴奋中起身离开。\n究其原因，大概是因为向往，向往二人的相遇，相依，相恋。总之，少了什么就想要什么，得不到就好奇别人得到是什么样子，虽然其他人都在说，这很假，这太理想，这很可笑，但是还是固执的觉得很漂亮，而不能放手了。我大概还没有到那个看到少年少女的爱情能心静如水的年龄。我倒是很满足于现状，希望能够永远这么幼稚下去。\n爱情之外，日常之中，二人将对方作为自己的半身，这样的依靠和安全感，说不定才是我真正想要的东西吧。三叶曾经评价妹妹说“没到青春期的小孩子无忧无虑真好呢”，而身担重负的三叶自己在漫画里对泷和泷的爸爸才能表现出自己少女的一面。说不定我在他人眼里是和三叶一样的孤单呢。\n但是我却又羡慕泷的独立，还羡慕三叶那像画里的小镇，稍稍有点贪心了。我睡觉很少做梦，为了弥补，只能醒着做白日梦。在还是孩子的时候就有很多的梦想，说实话说不定比现在我的梦想还要切合实际，然而到现在也一个一个都不记得了。同样的，一些亲密无间的朋友已经不再联系，一些暗恋的女孩子也毫不关心了。组成我生活的一点一滴，都被时间一点一点掏空，直到现在的我回头重新寻找的时候，才能凭借一点点痕迹去想象当时感到的温暖。就像新海诚监督说的：\n人会忘记许多事情，包括’喜欢’这样一种情感，但我们要挣扎着努力不要忘记，然后坚强地活下去\n\n还有一点，就是在眼前的“非日常”带来的欣喜了。上面“看彗星”那一节虽说是胡扯，后来看来看去却越有一点这样的意思。仔细想来，两个人一个月中一半时间活在对方的世界里，那已经是他们真正的日常的一部分了，却在我们眼里是那样的惊艳，就像三叶对于泷早就以习为常的城市生活和朋友家人感到的惊艳一样。还有影片接近结尾，彗星落下的一段，最后一个播音员的声音却莫名其妙的让我有点泪目了。他的话大概是：“能有机会目睹这样的奇观，大概是生活在这个时代的我们的一种很大的幸运吧。”然而，毁灭的镇子和彗星的出现，在几年后已经被忙碌的人们淡忘了。我们的平凡生活，是不是在其他人的梦里才能出现呢？\n总之，我想说的是：\n我们在日常生活中度过的每一天，实际上也许是连续发生的奇迹也说不定呢。\n\n希望我们每个人都可以从自己身边挖掘出更多的幸福，并永远握在手心，不要忘记。\n"},{"metadata":{"id":"switched-to-rapidjson","lang":"zh-CN","title":"使用 RapidJSON","tags":["Meta"],"publish_time":"2016-11-29T13:38:24.333Z","update_time":"2016-12-15T13:09:24.801Z","title_outline":{"groups":[{"chars":[{"char":"使","components":[["M 198 -856C 163 -661 84 -460 5 -332L 16 -325C 159 -426 270 -572 349 -778C 372 -777 385 -786 390 -799Z",[0.328,0.655]],["M 127 -524L 127 95L 153 95C 208 95 265 65 266 55L 266 -528C 286 -532 294 -538 298 -548L 178 -592Z",[0.011,0.79]],["M 559 -852L 559 -326C 559 -123 471 -1 261 85L 266 95C 578 38 698 -94 701 -326L 701 -807C 727 -811 735 -821 737 -835Z",[0.134,0.765]],["M 324 -697L 332 -669L 948 -669C 962 -669 974 -674 977 -685C 925 -731 838 -798 838 -798L 761 -697Z",[0.901,0.068]],["M 335 -568L 335 -256L 354 -256C 411 -256 472 -285 472 -297L 472 -540L 799 -540L 799 -568L 478 -568L 335 -623Z",[0.248,0.231]],["M 431 -259L 421 -254C 490 -42 627 51 880 92C 890 19 935 -34 990 -52L 991 -64C 751 -61 519 -115 431 -259Z",[-0.643,0.24]],["M 437 -348L 437 -320L 821 -320L 821 -348Z",[-0.929,0.009]],["M 787 -568L 787 -269L 811 -269C 858 -269 927 -296 927 -304L 927 -517C 948 -522 961 -531 967 -539L 839 -636L 777 -568Z",[0.001,0.585]]],"bbox":{"top":-856,"bottom":95,"left":5,"right":991},"hadv":1000}],"text":"使","hadv":1000,"breakAfter":true},{"chars":[{"char":"用","components":[["M 136 -773L 136 -461C 136 -273 129 -77 25 76L 34 83C 266 -58 278 -276 278 -462L 278 -773L 299 -773L 136 -828L 136 -783Z",[0.078,0.811]],["M 217 -540L 217 -512L 792 -512L 792 -540Z",[-0.834,0.008]],["M 217 -773L 217 -745L 792 -745L 792 -773Z",[-0.626,0.018]],["M 217 -297L 217 -269L 792 -269L 792 -297Z",[-0.951,0.003]],["M 427 -763L 427 80L 453 80C 527 80 569 51 569 42L 569 -763Z",[0.004,0.824]],["M 740 -773L 740 -90C 740 -78 736 -70 720 -70C 700 -70 607 -76 607 -76L 607 -63C 657 -54 675 -39 690 -18C 704 2 709 35 712 80C 864 67 885 17 885 -76L 885 -719C 908 -724 921 -734 929 -743L 795 -849L 729 -773Z",[0.041,0.817]]],"bbox":{"top":-849,"bottom":83,"left":25,"right":929},"hadv":1000}],"text":"用","hadv":1000,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"p","components":[["M 101 259L 267 259C 265 167 264 77 264 6L 264 -60L 266 -74L 266 -468L 265 -474L 255 -552L 242 -562L 27 -499L 27 -475L 101 -467C 103 -419 104 -385 104 -320L 104 7C 104 77 103 167 101 259Z",[-0.01,0.792]],["M 35 259L 343 259L 343 230L 244 219L 143 219L 35 230Z",[-0.86,0.001]],["M 410 17C 543 17 654 -94 654 -276C 654 -461 557 -563 434 -563C 352 -563 280 -527 231 -444L 224 -444L 241 -433C 286 -485 318 -494 355 -494C 434 -494 480 -438 480 -275C 480 -108 427 -54 349 -54C 308 -54 280 -62 249 -94L 228 -85L 240 -85C 286 -14 343 17 410 17Z",[0.006,0.478]]],"bbox":{"top":-563,"bottom":259,"left":27,"right":654},"hadv":689},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"d","components":[["M 269 17C 343 17 404 -20 448 -80L 459 -80L 437 -96C 408 -66 377 -54 342 -54C 265 -54 208 -112 208 -275C 208 -443 271 -494 347 -494C 378 -494 409 -482 440 -450L 459 -462L 450 -462C 406 -530 355 -563 283 -563C 150 -563 35 -451 35 -269C 35 -88 138 17 269 17Z",[0.007,0.475]],["M 432 12L 646 -0L 646 -31L 582 -35L 582 -657L 585 -817L 571 -826L 344 -783L 344 -756L 426 -749L 426 -483L 420 -471L 420 -77Z",[-0.017,0.798]]],"bbox":{"top":-826,"bottom":17,"left":35,"right":646},"hadv":673},{"char":"J","components":[["M 74 162C 131 162 194 140 248 75C 295 18 317 -49 317 -201L 317 -404C 317 -520 317 -636 321 -747L 151 -747C 154 -423 155 -298 155 -208C 155 -60 159 43 142 134L 142 142L 157 142L 157 136L 111 79C 76 40 58 33 23 33C -14 33 -42 49 -51 93C -44 142 -1 162 74 162Z",[0.111,0.745]],["M 43 -713L 204 -698L 246 -698L 409 -713L 409 -747L 43 -747Z",[-0.888,0.008]]],"bbox":{"top":-747,"bottom":162,"left":-51,"right":409},"hadv":442},{"char":"S","components":[["M 284 20C 472 20 574 -71 574 -204C 574 -317 519 -377 369 -444L 317 -468C 246 -500 208 -537 208 -606C 208 -681 266 -725 353 -725C 407 -725 438 -709 497 -663L 487 -707L 411 -738L 469 -546L 527 -546L 535 -710C 482 -746 411 -767 332 -767C 169 -767 59 -690 59 -555C 59 -435 130 -368 264 -307L 312 -286C 392 -250 420 -215 420 -148C 420 -70 366 -23 267 -23C 201 -23 159 -34 93 -79L 107 -39L 177 -10L 116 -212L 58 -212L 51 -40C 111 -1 202 20 284 20Z",[-0.042,0.343]]],"bbox":{"top":-767,"bottom":20,"left":51,"right":574},"hadv":612},{"char":"O","components":[["M 398 20C 587 20 752 -114 752 -374C 752 -633 586 -767 398 -767C 210 -767 43 -632 43 -374C 43 -113 210 20 398 20ZM 398 -18C 276 -18 221 -168 221 -374C 221 -578 276 -729 398 -729C 520 -729 574 -578 574 -374C 574 -168 520 -18 398 -18Z",[0.075,0.0]]],"bbox":{"top":-767,"bottom":20,"left":43,"right":752},"hadv":795},{"char":"N","components":[["M 35 -0L 312 -0L 312 -34L 171 -50L 140 -50L 35 -34Z",[-0.83,0.004]],["M 605 2L 693 2L 693 -747L 649 -747L 649 -478L 653 -182L 673 -189L 287 -747L 41 -747L 41 -713L 117 -705L 156 -646L 159 -642Z",[-0.336,0.457]],["M 133 -0L 185 -0L 185 -230L 171 -718L 133 -718Z",[-0.012,0.934]],["M 514 -713L 657 -698L 687 -698L 792 -713L 792 -747L 514 -747Z",[-0.294,0.05]]],"bbox":{"top":-747,"bottom":2,"left":35,"right":792},"hadv":825}],"text":"RapidJSON","hadv":5763,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>花了一个周末的时间从 <code>JsonCpp</code> 换到了 <code>RapidJSON</code>，后端的 RPS 飙升，增加了大概 40%（其实主要是因为换成了 SAX 风格的序列化），以列出帖子为例，大概从 50K 升到了 70K。在这里吹一波 <code>RapidJSON</code>，也不知道有没有人会看。</p>\n<p><a href=\"https://github.com/miloyip/rapidjson\">https://github.com/miloyip/rapidjson</a></p>\n<p>但是 70K RPS 离 <code>LevelDB</code> 的理论上限还差得远，不知道我哪里写崩了，估计又要花上一个周末时间检查。在那之前可能考虑把 <code>tinyxml2</code> 换成 <code>RapidXML</code>，为了保持库文件命名一致性。</p>\n<p>顺便，有一次用 wrk 测试的时候 URL 写错了，全都是返回 404，直接搞出来个 1.8M RPS，吓得我差点尿裤子…</p>\n<p>还有几个功能没有实现，一个是搜索，后端已经写完了，前段不知道怎么设计。至于评论是完全没有动，估计最后就是上 Disqus 了。</p>\n<p>接下来一段时间，可能这就是我唯一一个能获得一点乐趣的项目了，剩下的也都没什么时间。竞赛成绩出了以后，简直印证了那句老话：九年 OI 一场空。要是我还有心情的话另外写一写吧。</p>\n<hr />\n<p><strong>2016 / 12 / 15 更新</strong></p>\n<p>研究了一下，发现是自己写的比较器写崩了…居然还用了字符串分割，分配内存。真不知道自己当时是怎么想的了…\n还做了一个比较小的优化：用 SAX 风格的解析器解析 JSON，这个做完以后在 DEBUG 下在我们学校电脑飞到了 100K 了，嘻嘻。</p>\n<p>在下一步如果还要优化的话估计只能直接在解析以后立刻往缓冲区里面写，或者直接在 SAX 部分忘缓冲里面写了。这就涉及修改 API 了，放假再写。到时候还要在列出帖子的时候加个总页数，因为要改一下换页的操作。现在只能一页一页翻，简直 SB。</p>\n","plain":"花了一个周末的时间从 JsonCpp 换到了 RapidJSON，后端的 RPS 飙升，增加了大概 40%（其实主要是因为换成了 SAX 风格的序列化），以列出帖子为例，大概从 50K 升到了 70K。在这里吹一波 RapidJSON，也不知道有没有人会看。\nhttps://github.com/miloyip/rapidjson\n但是 70K RPS 离 LevelDB 的理论上限还差得远，不知道我哪里写崩了，估计又要花上一个周末时间检查。在那之前可能考虑把 tinyxml2 换成 RapidXML，为了保持库文件命名一致性。\n顺便，有一次用 wrk 测试的时候 URL 写错了，全都是返回 404，直接搞出来个 1.8M RPS，吓得我差点尿裤子…\n还有几个功能没有实现，一个是搜索，后端已经写完了，前段不知道怎么设计。至于评论是完全没有动，估计最后就是上 Disqus 了。\n接下来一段时间，可能这就是我唯一一个能获得一点乐趣的项目了，剩下的也都没什么时间。竞赛成绩出了以后，简直印证了那句老话：九年 OI 一场空。要是我还有心情的话另外写一写吧。\n---\n2016 / 12 / 15 更新\n研究了一下，发现是自己写的比较器写崩了…居然还用了字符串分割，分配内存。真不知道自己当时是怎么想的了… 还做了一个比较小的优化：用 SAX 风格的解析器解析 JSON，这个做完以后在 DEBUG 下在我们学校电脑飞到了 100K 了，嘻嘻。\n在下一步如果还要优化的话估计只能直接在解析以后立刻往缓冲区里面写，或者直接在 SAX 部分忘缓冲里面写了。这就涉及修改 API 了，放假再写。到时候还要在列出帖子的时候加个总页数，因为要改一下换页的操作。现在只能一页一页翻，简直 SB。\n"},{"metadata":{"id":"meow","lang":"zh-CN","title":"喵","tags":["卖萌"],"publish_time":"2016-10-03T15:47:35.615Z","update_time":"2019-01-02T14:26:51.077Z","title_outline":{"groups":[{"chars":[{"char":"喵","components":[["M 178 -97L 178 -692L 321 -692L 321 -720L 182 -720L 61 -771L 61 -55L 80 -55C 132 -55 178 -83 178 -97Z",[0.034,0.786]],["M 326 -218L 128 -218L 128 -190L 326 -190Z",[-0.931,0.01]],["M 214 -720L 224 -720L 224 -119L 244 -119C 287 -119 343 -148 344 -158L 344 -672C 364 -676 378 -685 384 -693L 271 -782Z",[0.01,0.806]],["M 485 -686L 365 -686L 372 -658L 485 -658L 485 -531L 508 -531C 582 -531 606 -549 606 -555L 606 -658L 687 -658L 687 -534L 708 -534C 783 -534 808 -551 808 -558L 808 -658L 942 -658C 955 -658 965 -663 967 -674C 934 -710 877 -761 877 -761L 827 -686L 808 -686L 808 -798C 831 -802 838 -813 839 -825L 687 -838L 687 -686L 606 -686L 606 -798C 628 -803 634 -813 636 -825L 485 -838Z",[0.367,0.039]],["M 388 -523L 388 87L 411 87C 478 87 517 64 517 55L 517 -443L 772 -443L 772 76L 796 76C 865 76 908 51 908 44L 908 -432C 931 -436 942 -444 949 -453L 832 -545L 767 -471L 529 -471ZM 849 -37L 450 -37L 450 -9L 849 -9ZM 849 -274L 450 -274L 450 -246L 849 -246Z",[0.101,0.021]],["M 706 -471L 584 -471L 584 -19L 706 -19Z",[0.006,0.718]]],"bbox":{"top":-838,"bottom":87,"left":61,"right":967},"hadv":1000}],"text":"喵","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.row-hidden {\n  opacity: 0.12;\n  padding: 10px 0;\n  text-align: center;\n}\n\ndiv.img-container {\n  width: 100%;\n  box-sizing: border-box;\n  position: relative;\n  margin-top: 40px;\n}\n\ndiv.img-container img {\n  width: 100%;\n  box-shadow: rgba(0,0,0,.36) 0 4px 6px;\n  \n  border-radius: 4px;\n}\n\ndiv.img-container .img-border {\n  position: absolute;\n  top: 0;\n  bottom: 4px;\n  right: 0;\n  left: 0;\n  box-sizing: border-box;\n  border: white 20px solid;\n  opacity: 0.4;\n  z-index: 1;\n  \n  border-radius: 4px;\n}\n</style>\n<!--\n<div class=\"img-container\">\n  <img src=\"//storage.c-3.moe/meow/jing.out.jpg\"></img>\n  <div class=\"img-border\"></div>\n</div>\n-->\n<p>照骗没得了！</p>\n<div class=\"row-hidden\">\n喵\n</div>","plain":"照骗没得了！\n"},{"metadata":{"id":"crushed-by-cpp","lang":"zh-CN","title":"感受到了力量","tags":["Meta","扯淡"],"publish_time":"2016-09-11T12:48:12.720Z","update_time":"2016-12-26T11:48:38.500Z","title_outline":{"groups":[{"chars":[{"char":"感","components":[["M 171 -224L 158 -224C 159 -162 114 -109 73 -90C 39 -74 15 -44 27 -4C 41 37 91 50 129 28C 186 -2 225 -93 171 -224Z",[0.265,0.425]],["M 105 -731L 105 -575C 105 -446 102 -284 31 -157L 39 -150C 222 -262 238 -452 238 -576L 238 -721L 257 -721L 105 -773Z",[0.098,0.754]],["M 877 -804L 820 -721L 177 -721L 177 -693L 952 -693C 966 -693 976 -698 979 -709C 942 -747 877 -804 877 -804Z",[0.801,0.041]],["M 470 -673L 407 -593L 232 -593L 240 -565L 556 -565C 570 -565 581 -570 584 -581C 541 -619 470 -673 470 -673Z",[0.754,0.093]],["M 371 -307L 371 -470L 483 -470L 483 -498L 375 -498L 248 -547L 248 -270L 265 -270C 316 -270 371 -297 371 -307Z",[0.084,0.338]],["M 435 -229L 258 -242L 258 -47C 258 41 288 62 413 62L 534 62C 731 62 787 49 787 -10C 787 -34 777 -49 736 -64L 733 -177L 724 -177C 698 -119 680 -84 666 -67C 658 -57 651 -54 634 -53C 618 -52 583 -52 552 -52L 439 -52C 407 -52 403 -56 403 -69L 403 -204C 424 -207 433 -215 435 -229Z",[-0.545,0.139]],["M 481 -360L 307 -360L 307 -332L 481 -332Z",[-0.739,0.047]],["M 426 -498L 435 -498L 435 -291L 457 -291C 497 -291 560 -312 561 -320L 561 -455C 577 -458 588 -466 592 -472L 480 -555Z",[0.005,0.43]],["M 435 -273L 427 -267C 467 -224 507 -156 517 -94C 636 -14 737 -245 435 -273Z",[-0.283,0.332]],["M 703 -843L 532 -856C 538 -612 586 -390 795 -242C 842 -210 931 -178 973 -232C 988 -253 984 -281 945 -334L 963 -472L 954 -475C 937 -437 911 -391 896 -369C 887 -356 879 -356 864 -366C 714 -463 674 -641 670 -815C 693 -819 702 -830 703 -843Z",[-0.363,0.614]],["M 953 -610L 785 -671C 748 -494 652 -352 543 -267L 552 -257C 708 -313 831 -407 912 -592C 935 -590 948 -598 953 -610Z",[0.443,0.59]],["M 700 -854L 692 -850C 705 -825 719 -785 718 -747C 808 -668 935 -832 700 -854Z",[0.156,0.516]],["M 718 -222L 710 -216C 772 -159 827 -68 843 15C 979 109 1083 -171 718 -222Z",[-0.318,0.382]]],"bbox":{"top":-856,"bottom":109,"left":15,"right":1083},"hadv":1000}],"text":"感","hadv":1000,"breakAfter":true},{"chars":[{"char":"受","components":[["M 147 -579C 155 -524 122 -475 89 -456C 51 -440 24 -409 35 -364C 49 -319 99 -302 139 -323C 197 -350 229 -448 159 -580Z",[0.201,0.401]],["M 624 -356C 537 -144 321 6 33 84L 37 96C 395 60 639 -73 772 -296C 799 -299 809 -302 817 -314L 693 -430L 610 -356Z",[0.626,0.484]],["M 760 -857C 606 -804 307 -740 77 -711L 79 -695C 324 -692 623 -710 812 -735C 847 -721 871 -721 883 -731Z",[0.77,0.103]],["M 156 -508L 156 -480L 865 -480L 865 -508Z",[-0.845,0.008]],["M 183 -356L 192 -328L 711 -328L 711 -356Z",[-0.944,0.002]],["M 207 -697L 199 -692C 222 -652 242 -592 240 -537C 351 -437 492 -649 207 -697Z",[-0.094,0.304]],["M 298 -356L 287 -348C 377 -66 579 41 856 96C 873 23 912 -28 977 -45L 978 -58C 691 -74 406 -135 298 -356Z",[-0.673,0.294]],["M 423 -712L 415 -708C 437 -664 454 -603 451 -545C 560 -442 707 -651 423 -712Z",[-0.094,0.303]],["M 704 -718C 688 -651 658 -552 628 -486L 638 -486C 716 -530 803 -593 855 -637C 878 -635 889 -643 894 -655Z",[0.385,0.354]],["M 802 -508C 795 -470 779 -405 766 -365L 772 -359C 827 -380 901 -420 946 -450C 967 -452 977 -454 985 -463L 862 -579L 791 -508Z",[0.335,0.324]]],"bbox":{"top":-857,"bottom":96,"left":24,"right":985},"hadv":1000}],"text":"受","hadv":1000,"breakAfter":true},{"chars":[{"char":"到","components":[["M 34 -96L 100 72C 113 69 124 60 131 47C 352 -37 494 -101 584 -150L 582 -161C 354 -130 126 -103 34 -96Z",[0.717,0.184]],["M 467 -854L 400 -761L 42 -761L 50 -733L 559 -733C 574 -733 585 -738 588 -749C 543 -791 467 -854 467 -854Z",[0.734,0.072]],["M 457 -394L 392 -300L 48 -300L 56 -272L 545 -272C 559 -272 570 -277 573 -288C 531 -330 457 -394 457 -394Z",[0.827,0.069]],["M 390 -699L 210 -739C 194 -683 134 -576 88 -547C 78 -541 53 -536 53 -536L 116 -384C 147 -397 168 -447 172 -521L 107 -521L 107 -510C 189 -545 307 -622 368 -688L 332 -679C 369 -672 386 -684 390 -699Z",[0.408,0.52]],["M 89 -531L 131 -404C 292 -454 423 -506 494 -536L 493 -548C 325 -538 158 -531 89 -531Z",[0.773,0.127]],["M 402 -437L 230 -450L 230 -64L 370 -95L 370 -411C 395 -415 401 -424 402 -437Z",[0.021,0.612]],["M 376 -661L 367 -655C 412 -601 448 -518 450 -443C 569 -344 688 -590 376 -661Z",[-0.204,0.397]],["M 767 -759L 601 -774L 601 -133L 625 -133C 674 -133 731 -158 731 -168L 731 -731C 758 -735 765 -745 767 -759Z",[0.015,0.777]],["M 973 -830L 800 -846L 800 -69C 800 -57 795 -51 779 -51C 755 -51 642 -58 642 -58L 642 -45C 697 -35 719 -20 737 1C 754 22 760 54 764 98C 916 85 937 34 937 -59L 937 -801C 962 -805 972 -815 973 -830Z",[0.032,0.851]]],"bbox":{"top":-854,"bottom":98,"left":34,"right":973},"hadv":1000}],"text":"到","hadv":1000,"breakAfter":true},{"chars":[{"char":"了","components":[["M 99 -754L 108 -726L 808 -726L 808 -754Z",[-0.656,0.014]],["M 425 -558L 425 -86C 425 -73 419 -66 402 -66C 372 -66 208 -76 208 -76L 208 -64C 282 -51 310 -35 335 -12C 360 11 367 44 373 92C 551 77 578 23 578 -77L 578 -515C 600 -519 610 -527 612 -542Z",[0.094,0.669]],["M 728 -754C 681 -688 574 -567 490 -502L 502 -502C 633 -549 783 -631 891 -700C 914 -702 925 -705 934 -715L 799 -832L 716 -754Z",[0.563,0.392]]],"bbox":{"top":-832,"bottom":92,"left":99,"right":934},"hadv":1000}],"text":"了","hadv":1000,"breakAfter":true},{"chars":[{"char":"力","components":[["M 370 -852C 369 -482 391 -175 31 81L 40 94C 533 -105 521 -430 529 -806C 554 -809 564 -818 566 -834Z",[0.233,0.744]],["M 71 -593L 80 -565L 809 -565L 809 -593Z",[-0.946,0.001]],["M 737 -593C 727 -306 710 -119 672 -88C 662 -78 651 -75 633 -75C 602 -75 513 -80 449 -84L 449 -74C 510 -62 558 -41 581 -18C 604 4 612 40 611 86C 700 86 746 70 787 32C 851 -25 873 -199 885 -538C 909 -542 922 -549 931 -559L 804 -671L 725 -593Z",[0.171,0.689]]],"bbox":{"top":-852,"bottom":94,"left":31,"right":931},"hadv":1000}],"text":"力","hadv":1000,"breakAfter":true},{"chars":[{"char":"量","components":[["M 36 45L 44 73L 943 73C 958 73 969 68 972 57C 924 14 843 -48 843 -48L 772 45Z",[0.924,0.036]],["M 48 -488L 56 -460L 928 -460C 942 -460 953 -465 956 -476C 911 -516 836 -574 836 -574L 770 -488Z",[0.974,0.031]],["M 113 -71L 121 -43L 869 -43C 883 -43 894 -48 897 -59C 851 -100 773 -161 773 -161L 704 -71Z",[0.907,0.043]],["M 180 -395L 180 -95L 200 -95C 259 -95 325 -126 325 -139L 325 -367L 735 -367L 735 -395L 333 -395L 180 -453Z",[0.373,0.185]],["M 194 -788L 194 -504L 214 -504C 272 -504 336 -534 336 -547L 336 -760L 726 -760L 726 -788L 344 -788L 194 -845Z",[0.401,0.183]],["M 248 -288L 248 -260L 752 -260L 752 -288Z",[-0.961,0.003]],["M 248 -180L 248 -152L 752 -152L 752 -180Z",[-0.962,0.002]],["M 280 -688L 280 -660L 731 -660L 731 -688Z",[-0.688,0.022]],["M 280 -583L 280 -555L 731 -555L 731 -583Z",[-0.731,0.021]],["M 425 -395L 425 52L 565 52L 565 -395Z",[0.002,0.679]],["M 661 -788L 661 -527L 686 -527C 732 -527 805 -549 806 -556L 806 -737C 827 -741 839 -751 845 -759L 713 -857L 651 -788Z",[0.024,0.48]],["M 668 -395L 668 -125L 693 -125C 739 -125 813 -147 815 -154L 815 -340C 838 -345 852 -356 858 -365L 722 -467L 657 -395Z",[0.007,0.505]]],"bbox":{"top":-857,"bottom":73,"left":36,"right":972},"hadv":1000}],"text":"量","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>最近更新了一下博客，成功把并发弄到 10k+，还把 Sitemap 给搞好了。中间遇到了很多坑：</p>\n<ul>\n<li>C++ 标准库不要求容器的写操作是原子的，所以开多线程的时候 Session 存储瞬间崩</li>\n<li>Atom 标准里链接的关系是 Alternate。亲爱的我怎么记得这个用作形容词不是这个意思啊… 之前写成 Alternative，Feedly 不认，我还骂了一通。</li>\n<li>RFC3999 里面日期时间前面要补 0</li>\n<li>Google Search Console 里面 Sitemap 只能交当前域名下的。前后端分离瞬间爆炸。</li>\n<li>之前忘了把 Leveldb 的 Iterator 释放了，因为文档只给了中间一部分示例没有初始化没有删除。当时差点蒙圈，因为好多都是在循环中间 return 的。还好有 unique_ptr，我只能说 C++ 还是好。</li>\n<li>把 CMAKE_BUILD_TYPE 写死在 CMakeList 里了。后来在外面设成 Release 会被覆盖，导致一直是不带优化编译的。</li>\n</ul>\n<p>这样一看，简直跟我不会写 C++ 一样，真是惨</p>\n","plain":"最近更新了一下博客，成功把并发弄到 10k+，还把 Sitemap 给搞好了。中间遇到了很多坑：\n- C++ 标准库不要求容器的写操作是原子的，所以开多线程的时候 Session 存储瞬间崩\n- Atom 标准里链接的关系是 Alternate。亲爱的我怎么记得这个用作形容词不是这个意思啊… 之前写成 Alternative，Feedly 不认，我还骂了一通。\n- RFC3999 里面日期时间前面要补 0\n- Google Search Console 里面 Sitemap 只能交当前域名下的。前后端分离瞬间爆炸。\n- 之前忘了把 Leveldb 的 Iterator 释放了，因为文档只给了中间一部分示例没有初始化没有删除。当时差点蒙圈，因为好多都是在循环中间 return 的。还好有 unique_ptr，我只能说 C++ 还是好。\n- 把 CMAKE_BUILD_TYPE 写死在 CMakeList 里了。后来在外面设成 Release 会被覆盖，导致一直是不带优化编译的。\n这样一看，简直跟我不会写 C++ 一样，真是惨\n"},{"metadata":{"id":"towards-south","lang":"zh-CN","title":"一路向南","tags":["扯淡"],"publish_time":"2016-08-06T13:37:08.954Z","update_time":"2016-10-16T09:43:55.314Z","title_outline":{"groups":[{"chars":[{"char":"一","components":[["M 816 -550L 723 -418L 29 -418L 38 -386L 948 -386C 965 -386 977 -391 980 -402C 920 -459 816 -550 816 -550Z",[0.883,0.054]]],"bbox":{"top":-550,"bottom":-386,"left":29,"right":980},"hadv":1000}],"text":"一","hadv":1000,"breakAfter":true},{"chars":[{"char":"路","components":[["M 8 -54L 66 90C 78 87 89 76 94 63C 272 -20 393 -87 472 -135L 469 -146C 279 -104 85 -65 8 -54Z",[0.702,0.245]],["M 62 -423L 62 -46L 165 -69L 165 -395C 179 -397 184 -404 185 -412Z",[0.009,0.713]],["M 66 -779L 66 -470L 88 -470C 151 -470 189 -496 189 -504L 189 -779L 202 -779L 66 -830Z",[-0.009,0.624]],["M 130 -779L 130 -751L 357 -751L 357 -779Z",[0.571,0.004]],["M 130 -539L 130 -511L 357 -511L 357 -539Z",[0.688,0.009]],["M 196 -539L 196 -39L 319 -70L 319 -539Z",[0.008,0.746]],["M 246 -344L 246 -316L 442 -316C 456 -316 466 -321 469 -332C 436 -372 373 -434 373 -434L 318 -344Z",[0.44,0.111]],["M 293 -779L 293 -484L 315 -484C 355 -484 417 -506 418 -513L 418 -733C 437 -737 449 -745 454 -752L 339 -839L 283 -779Z",[0.006,0.583]],["M 752 -713C 698 -527 560 -363 360 -267L 366 -255C 634 -323 801 -471 887 -662C 911 -665 921 -668 928 -679L 811 -782L 740 -713Z",[0.512,0.581]],["M 560 -856C 533 -706 470 -564 399 -474L 409 -466C 530 -529 627 -626 694 -779C 718 -778 730 -787 735 -800Z",[0.375,0.6]],["M 453 -259L 453 95L 478 95C 547 95 588 74 588 65L 588 -231L 729 -231L 729 91L 755 91C 829 91 872 69 872 63L 872 -222C 895 -226 904 -232 911 -241L 790 -332L 725 -259L 599 -259L 453 -313ZM 514 -10L 514 18L 808 18L 808 -10Z",[0.209,0.021]],["M 547 -687L 538 -672C 598 -485 690 -343 895 -268C 904 -336 930 -378 987 -400L 989 -411C 766 -449 612 -539 547 -687Z",[-0.509,0.357]],["M 569 -713L 557 -685L 806 -685L 806 -713Z",[-0.635,0.131]]],"bbox":{"top":-856,"bottom":95,"left":8,"right":989},"hadv":1000}],"text":"路","hadv":1000,"breakAfter":true},{"chars":[{"char":"向","components":[["M 90 -656L 90 93L 113 93C 173 93 232 59 232 42L 232 -628L 819 -628L 819 -656L 243 -656L 90 -716Z",[0.161,0.468]],["M 312 -486L 312 -109L 331 -109C 385 -109 442 -137 442 -150L 442 -458L 628 -458L 628 -486L 446 -486L 312 -538Z",[0.098,0.51]],["M 411 -852C 402 -789 383 -693 366 -629L 404 -629C 469 -675 533 -740 581 -785C 605 -785 615 -793 619 -806Z",[0.33,0.267]],["M 382 -253L 382 -225L 623 -225L 623 -253Z",[-0.877,0.001]],["M 564 -486L 564 -137L 587 -137C 632 -137 696 -164 697 -172L 697 -436C 717 -441 730 -450 737 -458L 614 -551L 554 -486Z",[0.022,0.64]],["M 780 -656L 780 -80C 780 -66 775 -58 758 -58C 726 -58 604 -66 604 -66L 604 -53C 664 -43 688 -26 708 -5C 728 17 735 49 739 95C 900 81 922 29 922 -65L 922 -605C 943 -609 956 -619 962 -627L 833 -727L 770 -656Z",[0.061,0.771]]],"bbox":{"top":-852,"bottom":95,"left":90,"right":962},"hadv":1000}],"text":"向","hadv":1000,"breakAfter":true},{"chars":[{"char":"南","components":[["M 825 -805L 746 -706L 33 -706L 41 -678L 939 -678C 954 -678 966 -683 969 -694C 914 -739 825 -805 825 -805Z",[0.851,0.043]],["M 259 45L 259 -517L 808 -517L 808 -545L 269 -545L 112 -606L 112 95L 135 95C 196 95 259 61 259 45Z",[0.177,0.406]],["M 641 -258L 582 -185L 271 -185L 279 -157L 722 -157C 736 -157 746 -162 749 -173C 708 -208 641 -258 641 -258Z",[0.857,0.053]],["M 649 -394L 596 -331L 290 -331L 298 -303L 720 -303C 734 -303 744 -308 747 -319C 709 -351 649 -394 649 -394Z",[0.825,0.064]],["M 321 -502L 313 -497C 336 -462 356 -407 355 -357C 455 -270 579 -462 321 -502Z",[-0.145,0.274]],["M 568 31L 568 -331L 428 -331L 428 58L 454 58C 526 58 567 36 568 31Z",[0.007,0.635]],["M 612 -842L 429 -856L 429 -528L 576 -528L 576 -813C 604 -818 610 -828 612 -842Z",[0.043,0.55]],["M 702 -467L 549 -509C 541 -453 526 -371 512 -317L 529 -317C 577 -356 630 -410 664 -448C 686 -447 698 -455 702 -467Z",[0.26,0.286]],["M 746 -545L 756 -545L 756 -72C 756 -60 752 -52 736 -52C 708 -52 607 -59 607 -59L 607 -46C 661 -37 681 -20 698 -0C 715 21 720 53 723 99C 881 85 904 34 904 -58L 904 -494C 925 -498 937 -507 943 -515L 811 -617Z",[0.062,0.723]]],"bbox":{"top":-856,"bottom":99,"left":33,"right":969},"hadv":1000}],"text":"南","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>放假了，南下几百米到清华大学旅游参观了几圈，感觉十分不错。以此为记录，用于备忘。</p>\n<div style=\"opacity: 0.05; font-size: 12px; line-height: 16px; text-align: center;\">我就是暑期学校闷骚第一人</div>\n<h2>学姐真可爱</h2>\n<p>嘻嘻</p>\n<h2>衣食住行</h2>\n<p>报道第一天发了两件衣服，不透气，穿着跟塑料布一样，保温保水节约能源，不能不说清华不愧为有视野的高校。</p>\n<hr />\n<p>清华食堂多，还有小桥烧烤，所以吃东西很方便。但是很遗憾，我要不就是因为身体原因不能吃，要不就是因为集合时间太紧不想吃，所以大多数时间都是快餐（其实是因为没带饭卡嘻嘻）。给我印象最深的餐厅是时代咖啡厅，我等了一份传统肉酱面四十分钟，在距离集合五分钟的时候发现他们上错桌了（上到一个外国妹子桌上，妹子一脸迷茫）。</p>\n<p>于是他们淡定的拿回去用微波炉去热了。</p>\n<p><strong>时代咖啡，祝你们越办越好。</strong></p>\n<hr />\n<p>住进了紫荆，由于奇妙的原因六天里一共只洗了一次热水澡。凉水真是冷，获得了冬泳般的感觉。但是住在紫荆并不孤单，有蚊子相伴，每晚与我耳语至天明。在Day4晚上看到了松鼠类似物，也不知道是真的还是黄鼠狼而已，我倒是已经有几个年头没有在清华园里看到确凿的松鼠了。</p>\n<p>顺便，我第一次知道紫<strong>荆</strong>是后鼻音，照澜<strong>院</strong>读yuan2，等等，简直不能接受。</p>\n<hr />\n<p>清华最奇妙之处在于让人找不到北——虽然其他三个方向都是可以很明显找到的。跑腿很累，除了迷失方向以外，主要原因是天气太闷，毫无前几天刮台风的魄力。时代在前进，被风吹倒的树，无论是砸到了宝马还是掉进了河里，都消失不见了。</p>\n<p>修路的地方很多，社会主义的大工厂，于是不多说，我们运气不太好。</p>\n<h2>相爱相杀</h2>\n<p>每天的活动中，PKU是出场频率最高的概念。比如 <code>Phenylketonuria</code>，某培实验班之类的，THU和PKU这种深厚的友谊，溢于言表。</p>\n<h2>没啥感受</h2>\n<p>其实说来说去，感受也就这些了。六天在THU的日子，天天闷的要命，晚上也看不到星星，还有成群的游人，魅力少了大半。也就是Day 4早上三点还在操场上坐着三两成群聊天的同学的场景，能令我记忆最深。</p>\n","plain":"放假了，南下几百米到清华大学旅游参观了几圈，感觉十分不错。以此为记录，用于备忘。\n\n学姐真可爱\n嘻嘻\n\n衣食住行\n报道第一天发了两件衣服，不透气，穿着跟塑料布一样，保温保水节约能源，不能不说清华不愧为有视野的高校。\n---\n清华食堂多，还有小桥烧烤，所以吃东西很方便。但是很遗憾，我要不就是因为身体原因不能吃，要不就是因为集合时间太紧不想吃，所以大多数时间都是快餐（其实是因为没带饭卡嘻嘻）。给我印象最深的餐厅是时代咖啡厅，我等了一份传统肉酱面四十分钟，在距离集合五分钟的时候发现他们上错桌了（上到一个外国妹子桌上，妹子一脸迷茫）。\n于是他们淡定的拿回去用微波炉去热了。\n时代咖啡，祝你们越办越好。\n---\n住进了紫荆，由于奇妙的原因六天里一共只洗了一次热水澡。凉水真是冷，获得了冬泳般的感觉。但是住在紫荆并不孤单，有蚊子相伴，每晚与我耳语至天明。在Day4晚上看到了松鼠类似物，也不知道是真的还是黄鼠狼而已，我倒是已经有几个年头没有在清华园里看到确凿的松鼠了。\n顺便，我第一次知道紫荆是后鼻音，照澜院读yuan2，等等，简直不能接受。\n---\n清华最奇妙之处在于让人找不到北——虽然其他三个方向都是可以很明显找到的。跑腿很累，除了迷失方向以外，主要原因是天气太闷，毫无前几天刮台风的魄力。时代在前进，被风吹倒的树，无论是砸到了宝马还是掉进了河里，都消失不见了。\n修路的地方很多，社会主义的大工厂，于是不多说，我们运气不太好。\n\n相爱相杀\n每天的活动中，PKU是出场频率最高的概念。比如 Phenylketonuria，某培实验班之类的，THU和PKU这种深厚的友谊，溢于言表。\n\n没啥感受\n其实说来说去，感受也就这些了。六天在THU的日子，天天闷的要命，晚上也看不到星星，还有成群的游人，魅力少了大半。也就是Day 4早上三点还在操场上坐着三两成群聊天的同学的场景，能令我记忆最深。\n"},{"metadata":{"id":"favicons","lang":"zh-CN","title":"Favicons","tags":["扯淡","玩具"],"publish_time":"2016-07-31T06:31:18.291Z","update_time":"2017-03-19T05:35:50.812Z","title_outline":{"groups":[{"chars":[{"char":"F","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -360L 303 -391C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -363L 469 -363L 469 -399L 218 -399Z",[-0.863,0.002]],["M 562 -548L 619 -548L 621 -747L 218 -747L 218 -708L 591 -708L 505 -747Z",[-0.584,0.175]],["M 455 -255L 505 -255L 505 -505L 455 -505L 440 -398L 440 -367Z",[0.002,0.781]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":621},"hadv":657},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593},{"char":"i","components":[["M 101 -0L 270 -0C 267 -51 266 -168 266 -238L 266 -392L 270 -553L 257 -562L 27 -502L 27 -478L 101 -470C 103 -423 104 -384 104 -318L 104 -238C 104 -168 103 -51 101 -0Z",[-0.015,0.683]],["M 37 -0L 329 -0L 329 -31L 220 -41L 142 -41L 37 -31Z",[-0.864,0.0]],["M 181 -655C 229 -655 267 -689 267 -738C 267 -784 229 -819 181 -819C 134 -819 95 -784 95 -738C 95 -689 134 -655 181 -655Z",[0.006,0.015]]],"bbox":{"top":-819,"bottom":0,"left":27,"right":329},"hadv":358},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"o","components":[["M 318 17C 489 17 602 -97 602 -276C 602 -455 476 -563 318 -563C 161 -563 35 -453 35 -276C 35 -100 146 17 318 17ZM 318 -18C 247 -18 207 -100 207 -274C 207 -449 247 -528 318 -528C 390 -528 429 -449 429 -274C 429 -100 390 -18 318 -18Z",[0.11,0.0]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":602},"hadv":637},{"char":"n","components":[["M 97 -0L 266 -0C 264 -51 263 -168 263 -238L 263 -441L 255 -553L 242 -562L 24 -499L 24 -475L 97 -467C 100 -419 101 -386 101 -321L 101 -238C 101 -168 100 -51 97 -0Z",[-0.02,0.684]],["M 33 -0L 323 -0L 323 -31L 216 -41L 137 -41L 33 -31Z",[-0.863,0.0]],["M 443 -0L 612 -0C 610 -51 608 -165 608 -238L 608 -370C 608 -501 543 -563 448 -563C 374 -563 314 -534 238 -436L 220 -436L 223 -389C 278 -455 338 -488 377 -488C 424 -488 446 -460 446 -383L 446 -238C 446 -165 445 -51 443 -0Z",[-0.128,0.59]],["M 381 -0L 671 -0L 671 -31L 561 -41L 483 -41L 381 -31Z",[-0.86,0.003]]],"bbox":{"top":-563,"bottom":0,"left":24,"right":671},"hadv":697},{"char":"s","components":[["M 238 17C 390 17 482 -51 482 -168C 482 -250 436 -305 331 -337L 272 -355C 194 -378 174 -408 174 -444C 174 -494 214 -525 276 -525C 322 -525 347 -513 387 -487L 387 -517L 339 -535L 385 -392L 442 -392L 449 -518C 390 -547 339 -563 272 -563C 125 -563 43 -487 43 -382C 43 -297 96 -245 186 -218L 244 -199C 324 -176 343 -146 343 -104C 343 -49 301 -22 225 -22C 173 -22 137 -35 92 -65L 92 -29L 146 -22L 112 -169L 48 -169L 40 -33C 99 -0 160 17 238 17Z",[-0.033,0.222]]],"bbox":{"top":-563,"bottom":17,"left":40,"right":482},"hadv":512}],"text":"Favicons","hadv":4632,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.favicons {\n  text-align: center;\n  margin: 50px 0 200px 0;\n  padding: 100px 0;\n  \n  box-shadow: rgba(0,0,0,.12) 0 3px 5px;\n  background: white;\n  border-radius: 4px;\n}\n\n.favicons img {\n  height: 100px;\n  margin: 0 20px;\n}\n</style>\n<p>为了在Chrome上支持Add to homescreen，花了整整一个下午做了个Logo。各位，请欣赏：</p>\n<div class=\"favicons\">\n  <img src=\"//storage.c-3.moe/meow/favicon.svg\"></img>\n  <img src=\"//storage.c-3.moe/meow/touchicon.svg\"></img>\n</div>\n<hr />\n<p>有没有感受到震撼?</p>\n<p>这还是矢量的</p>\n","plain":"为了在Chrome上支持Add to homescreen，花了整整一个下午做了个Logo。各位，请欣赏：\n---\n有没有感受到震撼?\n这还是矢量的\n"},{"metadata":{"id":"hurt-each-other","lang":"zh-CN","title":"互相伤害","tags":["蒋公的面子","视频"],"publish_time":"2016-07-29T13:43:03.621Z","update_time":"2017-03-19T05:35:44.770Z","title_outline":{"groups":[{"chars":[{"char":"互","components":[["M 838 -96L 756 10L 25 10L 33 38L 956 38C 971 38 983 33 986 22C 931 -26 838 -96 838 -96Z",[0.913,0.042]],["M 791 -856L 710 -753L 58 -753L 66 -725L 908 -725C 923 -725 934 -730 937 -741C 882 -787 791 -856 791 -856Z",[0.81,0.05]],["M 440 -739L 283 -739C 277 -639 233 -354 199 -230L 236 -269C 213 -260 188 -243 173 -227L 310 -156L 358 -219L 351 -219C 378 -349 423 -625 440 -739Z",[0.132,0.727]],["M 689 -247L 266 -247L 266 -219L 689 -219Z",[-0.935,0.004]],["M 711 -539L 327 -539L 327 -511L 711 -511Z",[0.773,0.032]],["M 615 -539L 627 -539L 555 29L 710 29L 774 -483C 799 -487 808 -490 818 -501L 678 -615Z",[0.102,0.731]]],"bbox":{"top":-856,"bottom":38,"left":25,"right":986},"hadv":1000}],"text":"互","hadv":1000,"breakAfter":true},{"chars":[{"char":"相","components":[["M 160 -600C 137 -446 89 -273 12 -154L 24 -144C 162 -256 257 -405 298 -584L 298 -600Z",[0.306,0.686]],["M 37 -600L 45 -572L 432 -572C 446 -572 456 -577 459 -588C 426 -627 365 -689 365 -689L 310 -600Z",[0.951,0.086]],["M 167 -852L 167 96L 195 96C 248 96 307 68 307 57L 307 -806C 335 -810 342 -820 344 -835Z",[0.005,0.849]],["M 307 -486L 297 -481C 320 -436 342 -372 344 -315C 439 -228 558 -414 307 -486Z",[-0.18,0.365]],["M 460 -762L 460 89L 483 89C 547 89 602 54 602 35L 602 -735L 854 -735L 854 -762L 607 -762L 460 -822Z",[0.048,0.771]],["M 527 -48L 527 -20L 859 -20L 859 -48Z",[0.916,0.001]],["M 528 -528L 528 -500L 860 -500L 860 -528Z",[-0.78,0.023]],["M 528 -293L 528 -265L 860 -265L 860 -293Z",[-0.994,0.008]],["M 781 -762L 781 83L 804 83C 858 83 925 50 926 40L 926 -711C 947 -716 959 -724 966 -733L 838 -836L 771 -762Z",[0.008,0.842]]],"bbox":{"top":-852,"bottom":96,"left":12,"right":966},"hadv":1000}],"text":"相","hadv":1000,"breakAfter":true},{"chars":[{"char":"伤","components":[["M 405 -798L 210 -856C 172 -655 94 -435 21 -298L 32 -291C 173 -404 282 -566 364 -777C 388 -777 401 -785 405 -798Z",[0.317,0.674]],["M 321 -534L 198 -579L 145 -509L 145 80L 172 80C 229 80 288 50 290 40L 290 -514C 309 -518 318 -525 321 -534Z",[0.012,0.771]],["M 713 -583L 525 -606C 523 -310 520 -51 269 81L 276 94C 647 -11 662 -270 676 -557C 700 -559 710 -568 713 -583Z",[0.236,0.714]],["M 647 -802L 456 -855C 435 -692 377 -533 310 -428L 320 -421C 446 -495 542 -607 607 -780C 631 -780 643 -789 647 -802Z",[0.314,0.609]],["M 833 -424L 367 -424L 376 -396L 833 -396Z",[0.831,0.011]],["M 839 -771L 759 -669L 509 -669L 509 -641L 953 -641C 968 -641 980 -646 983 -657C 929 -703 839 -771 839 -771Z",[0.637,0.117]],["M 782 -424L 793 -424C 786 -203 773 -91 747 -68C 739 -62 731 -59 716 -59C 695 -59 639 -62 604 -65L 603 -53C 645 -43 673 -28 690 -7C 705 11 709 44 708 86C 772 86 814 73 849 45C 904 1 922 -102 932 -372C 953 -375 966 -382 973 -391L 854 -493Z",[0.162,0.652]]],"bbox":{"top":-856,"bottom":94,"left":21,"right":983},"hadv":1000}],"text":"伤","hadv":1000,"breakAfter":true},{"chars":[{"char":"害","components":[["M 172 -776L 160 -776C 160 -730 120 -688 87 -672C 51 -655 26 -624 37 -582C 52 -537 106 -523 142 -545C 192 -574 221 -659 172 -776Z",[0.218,0.379]],["M 839 -405L 774 -325L 42 -325L 50 -297L 929 -297C 943 -297 954 -302 957 -313C 912 -351 839 -405 839 -405Z",[0.921,0.031]],["M 846 -715L 156 -715L 156 -687L 846 -687Z",[0.741,0.015]],["M 709 -656L 646 -578L 167 -578L 175 -550L 797 -550C 811 -550 822 -555 825 -566C 781 -603 709 -656 709 -656Z",[0.91,0.044]],["M 716 -528L 655 -453L 176 -453L 184 -425L 799 -425C 814 -425 824 -430 827 -441C 785 -477 716 -528 716 -528Z",[0.84,0.047]],["M 324 51L 324 -179L 730 -179L 730 -207L 332 -207L 184 -263L 184 93L 204 93C 261 93 324 63 324 51Z",[0.37,0.19]],["M 724 -14L 258 -14L 258 14L 724 14Z",[0.94,0.0]],["M 390 -850L 384 -845C 417 -818 445 -769 449 -721C 580 -639 692 -887 390 -850Z",[-0.002,0.153]],["M 598 -657L 427 -672L 427 -224L 453 -224C 506 -224 570 -248 570 -258L 570 -635C 591 -638 597 -647 598 -657Z",[0.015,0.666]],["M 679 -207L 689 -207L 689 88L 714 88C 759 88 830 65 831 58L 831 -156C 852 -161 865 -170 871 -178L 741 -275Z",[0.014,0.566]],["M 784 -715L 795 -715C 796 -681 795 -622 792 -584L 799 -578C 843 -597 899 -632 932 -659C 953 -660 963 -663 971 -672L 852 -784Z",[0.164,0.253]]],"bbox":{"top":-887,"bottom":93,"left":26,"right":971},"hadv":1000}],"text":"害","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.jiangsface {\n  width: 100%;\n}\n</style>\n<p>翻找硬盘过程中发现了这个视频，不能多说，只能拿来互相伤害一波。</p>\n<video src=\"//storage.c-3.moe/meow/jiangsface.mp4\" class=\"jiangsface\" controls>\n  嘻嘻，你的浏览器播不来视频。\n</video>\n<p>看不来的人可以点<a href=\"//storage.c-3.moe/meow/jiangsface.mp4\">我</a>下载</p>\n","plain":"翻找硬盘过程中发现了这个视频，不能多说，只能拿来互相伤害一波。\n看不来的人可以点我下载\n"},{"metadata":{"id":"new-home","lang":"zh-CN","title":"我的新主页","tags":["扯淡","玩具"],"publish_time":"2016-07-28T13:01:49.012Z","update_time":"2016-08-09T17:42:35.637Z","title_outline":{"groups":[{"chars":[{"char":"我","components":[["M 25 -325L 86 -162C 98 -165 110 -174 116 -187C 325 -269 462 -332 549 -380L 548 -391C 331 -360 112 -332 25 -325Z",[0.708,0.19]],["M 397 -849C 317 -791 156 -709 25 -663L 27 -653C 184 -661 363 -687 474 -718C 510 -706 534 -708 547 -719Z",[0.643,0.171]],["M 26 -530L 34 -502L 951 -502C 965 -502 976 -507 979 -518C 929 -558 848 -616 848 -616L 776 -530Z",[0.93,0.034]],["M 243 -735L 243 -80C 243 -68 238 -60 222 -60C 197 -60 83 -67 83 -67L 83 -55C 142 -45 164 -29 181 -8C 198 13 205 48 207 94C 361 83 385 18 385 -75L 385 -735Z",[0.048,0.794]],["M 781 -482C 723 -297 589 -81 374 46L 381 57C 653 -31 815 -215 908 -391C 932 -388 942 -395 948 -406Z",[0.52,0.598]],["M 527 -836C 528 -479 551 -170 777 25C 825 66 917 110 969 57C 988 37 983 1 944 -65L 968 -238L 959 -241C 938 -196 907 -140 889 -113C 879 -97 871 -97 856 -110C 683 -245 665 -508 670 -790C 696 -794 704 -806 705 -819Z",[-0.279,0.72]],["M 722 -801L 714 -796C 747 -755 775 -691 776 -632C 891 -540 1014 -765 722 -801Z",[0.027,0.287]]],"bbox":{"top":-849,"bottom":110,"left":25,"right":1014},"hadv":1000}],"text":"我","hadv":1000,"breakAfter":true},{"chars":[{"char":"的","components":[["M 196 8L 196 -627L 352 -627L 352 -655L 200 -655L 66 -710L 66 54L 87 54C 145 54 196 23 196 8Z",[0.033,0.781]],["M 376 -379L 135 -379L 135 -351L 376 -351Z",[-0.885,0.012]],["M 376 -89L 135 -89L 135 -61L 376 -61Z",[-0.888,0.002]],["M 397 -804L 204 -850C 202 -785 195 -690 190 -636L 225 -636C 262 -675 319 -738 354 -779C 378 -779 392 -786 397 -804Z",[0.208,0.268]],["M 309 -655L 319 -655L 319 18L 341 18C 388 18 453 -10 454 -19L 454 -605C 474 -610 487 -618 494 -627L 371 -724Z",[0.007,0.807]],["M 757 -798L 571 -852C 548 -700 498 -533 449 -427L 460 -420C 566 -503 653 -623 717 -777C 740 -777 753 -785 757 -798Z",[0.309,0.632]],["M 526 -456L 518 -451C 553 -395 582 -317 584 -245C 707 -138 842 -383 526 -456Z",[-0.196,0.363]],["M 785 -659L 797 -659C 791 -301 783 -108 746 -75C 736 -66 726 -62 709 -62C 683 -62 615 -66 567 -70L 566 -58C 618 -47 655 -29 674 -7C 692 13 698 46 698 93C 773 93 819 76 858 37C 917 -24 929 -186 936 -606C 960 -610 973 -617 981 -627L 860 -735Z",[0.126,0.755]],["M 870 -659L 581 -659L 569 -631L 870 -631Z",[-0.294,0.07]]],"bbox":{"top":-852,"bottom":93,"left":66,"right":981},"hadv":1000}],"text":"的","hadv":1000,"breakAfter":true},{"chars":[{"char":"新","components":[["M 256 -234L 99 -303C 92 -217 67 -82 23 7L 32 17C 117 -46 179 -140 218 -218C 243 -217 252 -224 256 -234Z",[0.258,0.549]],["M 445 -566L 386 -483L 24 -483L 32 -455L 524 -455C 538 -455 548 -460 551 -471C 512 -509 445 -566 445 -566Z",[0.782,0.067]],["M 427 -417L 371 -338L 37 -338L 45 -310L 500 -310C 514 -310 524 -315 527 -326C 490 -363 427 -417 427 -417Z",[0.823,0.065]],["M 427 -778L 370 -699L 40 -699L 48 -671L 503 -671C 517 -671 527 -676 530 -687C 492 -724 427 -778 427 -778Z",[0.748,0.066]],["M 120 -675L 110 -671C 126 -625 142 -562 139 -506C 226 -415 353 -587 120 -675Z",[-0.193,0.394]],["M 347 -47L 347 -475L 210 -475L 210 -50C 210 -40 207 -33 194 -33C 177 -33 117 -37 117 -37L 117 -25C 156 -18 170 -4 180 12C 190 29 192 56 193 93C 328 83 347 36 347 -47Z",[0.042,0.732]],["M 190 -854L 183 -849C 206 -815 227 -762 227 -712C 338 -621 471 -830 190 -854Z",[-0.093,0.251]],["M 498 -631L 341 -679C 333 -616 316 -525 298 -464L 311 -464C 367 -509 425 -569 461 -613C 483 -611 494 -619 498 -631Z",[0.29,0.429]],["M 355 -284L 345 -279C 369 -232 388 -164 384 -104C 478 -11 605 -202 355 -284Z",[-0.174,0.39]],["M 702 -721L 534 -773L 534 -433C 534 -252 524 -64 412 84L 421 94C 658 -38 673 -251 673 -429L 673 -706C 688 -708 699 -713 702 -721Z",[0.094,0.799]],["M 855 -597L 783 -496L 598 -496L 598 -468L 956 -468C 970 -468 982 -473 984 -484C 937 -529 855 -597 855 -597Z",[0.63,0.138]],["M 969 -741L 824 -856C 781 -809 693 -738 619 -698L 622 -687C 723 -695 834 -715 902 -737C 936 -727 957 -730 969 -741Z",[0.439,0.284]],["M 882 56L 882 -496L 740 -496L 740 94L 766 94C 839 94 881 64 882 56Z",[-0.003,0.84]]],"bbox":{"top":-856,"bottom":94,"left":23,"right":984},"hadv":1000}],"text":"新","hadv":1000,"breakAfter":true},{"chars":[{"char":"主","components":[["M 26 17L 34 45L 943 45C 958 45 970 40 973 29C 917 -18 825 -87 825 -87L 743 17Z",[0.913,0.042]],["M 92 -600L 100 -572L 904 -572C 919 -572 931 -577 934 -588C 880 -634 790 -701 790 -701L 711 -600Z",[0.892,0.049]],["M 136 -317L 144 -289L 868 -289C 883 -289 895 -294 897 -305C 845 -350 758 -415 758 -415L 681 -317Z",[0.895,0.051]],["M 324 -846L 318 -840C 375 -790 435 -710 461 -634C 614 -551 707 -845 324 -846Z",[-0.441,0.358]],["M 416 -600L 416 25L 576 25L 576 -600Z",[0.002,0.738]]],"bbox":{"top":-846,"bottom":45,"left":26,"right":973},"hadv":1000}],"text":"主","hadv":1000,"breakAfter":true},{"chars":[{"char":"页","components":[["M 611 -495L 424 -510C 424 -208 448 -40 29 82L 35 95C 576 9 568 -163 576 -467C 598 -470 608 -479 611 -495Z",[0.333,0.585]],["M 831 -871L 754 -772L 50 -772L 58 -744L 942 -744C 957 -744 969 -749 972 -760C 919 -805 831 -871 831 -871Z",[0.81,0.049]],["M 322 -176L 322 -565L 742 -565L 742 -593L 331 -593L 171 -654L 171 -127L 193 -127C 256 -127 322 -161 322 -176Z",[0.183,0.329]],["M 577 -772L 387 -772C 387 -712 387 -624 386 -576L 402 -576C 458 -621 528 -704 577 -772Z",[0.257,0.338]],["M 488 -158L 482 -148C 596 -95 748 10 836 94C 1001 119 1002 -177 488 -158Z",[-0.593,0.313]],["M 669 -593L 678 -593L 678 -160L 704 -160C 754 -160 828 -187 829 -195L 829 -546C 847 -550 857 -557 863 -564L 733 -662Z",[0.02,0.651]]],"bbox":{"top":-871,"bottom":119,"left":29,"right":1002},"hadv":1000}],"text":"页","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>前几天业界<ruby>良心<rp>(</rp><rt>毒瘤</rt><rp>)</rp></ruby>Freenom把我的主域名给吊销了，我只能称赞一下他们认真负责的工作态度。还记得当时我把dot.tk的域名转到freenom的时候，两边的密码过滤策略不一样，结果我的账户登不上去，连密码都改不了，简直是顶尖科技。</p>\n<p>所以大概花了五分钟时间撸了个新主页，放在<a href=\"https://c-3.io\">https://c-3.io</a>上。原来的域名是<a href=\"http://circuitcoder.tk\">circuitcoder.tk</a>，已经重定向到了新域名。</p>\n","plain":"前几天业界良心(毒瘤)Freenom把我的主域名给吊销了，我只能称赞一下他们认真负责的工作态度。还记得当时我把dot.tk的域名转到freenom的时候，两边的密码过滤策略不一样，结果我的账户登不上去，连密码都改不了，简直是顶尖科技。\n所以大概花了五分钟时间撸了个新主页，放在https://c-3.io上。原来的域名是circuitcoder.tk，已经重定向到了新域名。\n"},{"metadata":{"id":"plus-one-second","lang":"zh-CN","title":"苟延残喘","tags":["扯淡"],"publish_time":"2016-07-23T12:49:45.196Z","update_time":"2017-03-19T05:35:27.917Z","title_outline":{"groups":[{"chars":[{"char":"苟","components":[["M 206 -640C 169 -483 94 -326 21 -229L 31 -221C 160 -291 270 -395 352 -552C 375 -550 389 -558 394 -571Z",[0.373,0.564]],["M 27 -726L 34 -698L 283 -698L 283 -588L 306 -588C 368 -588 424 -607 424 -619L 424 -698L 566 -698L 566 -595L 589 -595C 653 -595 710 -613 710 -625L 710 -698L 945 -698C 960 -698 971 -703 973 -714C 930 -756 854 -817 854 -817L 786 -726L 710 -726L 710 -814C 736 -817 745 -827 746 -840L 566 -855L 566 -726L 424 -726L 424 -814C 450 -818 458 -827 459 -840L 283 -855L 283 -726Z",[0.614,0.037]],["M 210 -388L 210 -43L 229 -43C 286 -43 345 -73 345 -85L 345 -360L 543 -360L 543 -388L 350 -388L 210 -442Z",[0.113,0.432]],["M 236 -522L 223 -494L 808 -494L 808 -522Z",[-0.822,0.017]],["M 281 -185L 281 -157L 551 -157L 551 -185Z",[0.894,0.0]],["M 475 -388L 475 -93L 499 -93C 545 -93 612 -121 612 -129L 612 -341C 631 -345 642 -353 648 -360L 525 -452L 465 -388Z",[0.024,0.559]],["M 751 -522C 744 -239 732 -97 701 -70C 693 -62 683 -59 668 -59C 646 -59 588 -62 549 -65L 549 -54C 593 -43 623 -26 641 -4C 656 15 661 48 660 94C 728 94 773 79 810 46C 869 -5 884 -127 893 -469C 916 -472 929 -480 937 -489L 814 -595L 739 -522Z",[0.142,0.698]]],"bbox":{"top":-855,"bottom":94,"left":21,"right":973},"hadv":1000}],"text":"苟","hadv":1000,"breakAfter":true},{"chars":[{"char":"延","components":[["M 253 -448L 264 -448C 248 -238 196 -40 24 81L 31 92C 279 -8 358 -195 391 -401C 413 -404 422 -408 428 -419L 315 -513Z",[0.305,0.707]],["M 281 -747L 40 -747L 49 -719L 281 -719Z",[-0.95,0.008]],["M 340 -705L 218 -747C 196 -679 128 -518 88 -446L 128 -479C 107 -475 80 -460 65 -447L 180 -378L 218 -420L 212 -420C 247 -490 314 -642 340 -705Z",[0.273,0.585]],["M 75 -376L 66 -372C 157 -2 341 68 746 68C 782 68 865 68 901 68C 904 12 931 -39 985 -52L 985 -63C 924 -62 806 -62 756 -62C 368 -62 178 -103 75 -376Z",[-0.754,0.173]],["M 314 -448L 148 -448L 134 -420L 314 -420Z",[-0.847,0.001]],["M 205 -747L 218 -747L 231 -691C 285 -682 352 -681 371 -702L 261 -803Z",[-0.446,0.157]],["M 950 -726L 815 -853C 725 -797 546 -729 395 -696L 397 -684C 565 -680 756 -698 879 -727C 914 -714 937 -716 950 -726Z",[0.736,0.128]],["M 528 -557L 431 -557L 431 -192L 453 -230C 436 -223 412 -201 399 -185L 529 -111L 567 -175L 559 -175L 559 -538Z",[0.009,0.681]],["M 595 -585L 431 -601L 431 -524L 559 -524L 559 -557C 584 -561 592 -570 595 -585Z",[-0.392,0.054]],["M 846 -301L 780 -203L 488 -203L 496 -175L 934 -175C 949 -175 959 -180 962 -191C 921 -235 846 -301 846 -301Z",[0.799,0.068]],["M 751 -188L 751 -759L 614 -733L 614 -188L 639 -188C 710 -188 751 -188 751 -188Z",[-0.014,0.84]],["M 825 -589L 767 -494L 699 -494L 699 -466L 900 -466C 914 -466 924 -471 927 -482C 891 -524 825 -589 825 -589Z",[0.44,0.115]]],"bbox":{"top":-853,"bottom":92,"left":24,"right":985},"hadv":1000}],"text":"延","hadv":1000,"breakAfter":true},{"chars":[{"char":"残","components":[["M 306 -751L 306 -767L 165 -767C 146 -596 104 -408 28 -277L 40 -268C 182 -392 270 -555 306 -751Z",[0.267,0.71]],["M 298 -574L 310 -574C 292 -322 232 -71 38 82L 47 93C 332 -39 409 -278 442 -524C 465 -527 474 -531 481 -542L 364 -644Z",[0.287,0.742]],["M 387 -855L 316 -767L 38 -767L 46 -739L 488 -739C 503 -739 514 -744 517 -755C 468 -796 387 -855 387 -855Z",[0.916,0.061]],["M 134 -437L 126 -432C 147 -392 159 -333 150 -280C 251 -176 401 -373 134 -437Z",[-0.13,0.296]],["M 367 -574L 173 -574L 166 -546L 367 -546Z",[-0.283,0.015]],["M 971 -305L 807 -398C 677 -163 501 -30 290 63L 294 76C 548 21 747 -79 925 -294C 950 -289 963 -293 971 -305Z",[0.63,0.496]],["M 843 -512L 777 -411L 429 -374L 439 -347L 963 -403C 976 -405 988 -412 989 -423C 933 -461 843 -512 843 -512Z",[0.827,0.15]],["M 815 -662L 749 -563L 458 -535L 468 -508L 932 -552C 946 -554 957 -561 959 -572C 903 -610 815 -662 815 -662Z",[0.718,0.161]],["M 708 -836L 531 -854C 532 -486 553 -166 774 38C 822 80 912 127 967 75C 986 56 981 19 942 -49L 968 -227L 958 -229C 937 -184 906 -127 888 -99C 877 -83 869 -83 855 -97C 682 -239 666 -515 672 -807C 698 -812 707 -823 708 -836Z",[-0.271,0.741]],["M 673 -814L 666 -809C 698 -774 733 -717 743 -665C 865 -588 966 -816 673 -814Z",[-0.132,0.154]]],"bbox":{"top":-855,"bottom":127,"left":28,"right":989},"hadv":1000}],"text":"残","hadv":1000,"breakAfter":true},{"chars":[{"char":"喘","components":[["M 173 -100L 173 -713L 288 -713L 288 -741L 177 -741L 60 -790L 60 -60L 78 -60C 129 -60 173 -87 173 -100Z",[0.025,0.811]],["M 282 -239L 127 -239L 127 -211L 282 -211Z",[-0.893,0.013]],["M 211 -741L 221 -741L 221 -123L 239 -123C 280 -123 332 -151 333 -161L 333 -694C 353 -698 367 -707 374 -715L 265 -800Z",[0.01,0.823]],["M 881 -559L 822 -482L 338 -482L 346 -454L 962 -454C 976 -454 986 -459 989 -470C 948 -506 881 -559 881 -559Z",[0.835,0.054]],["M 471 -725L 376 -725L 376 -578L 398 -616C 381 -609 357 -588 344 -572L 472 -498L 510 -561L 502 -561L 502 -706Z",[-0.006,0.321]],["M 494 58L 494 -321L 850 -321L 850 -349L 501 -349L 375 -399L 375 97L 393 97C 443 97 494 70 494 58Z",[0.181,0.389]],["M 538 -785L 376 -801L 376 -681C 479 -681 497 -681 502 -681L 502 -762C 527 -766 536 -774 538 -785Z",[-0.806,0.099]],["M 860 -589L 456 -589L 456 -561L 860 -561Z",[-0.871,0.036]],["M 731 -482L 552 -482C 551 -446 544 -377 537 -333L 571 -333C 622 -371 690 -438 731 -482Z",[0.37,0.338]],["M 630 15L 630 -348L 538 -348L 538 37L 554 37C 601 37 629 20 630 15Z",[0.003,0.765]],["M 749 -841L 591 -854L 591 -568L 717 -568L 717 -815C 741 -819 748 -828 749 -841Z",[0.082,0.549]],["M 767 -12L 767 -349L 675 -349L 675 9L 691 9C 738 9 766 -8 767 -12Z",[0.011,0.688]],["M 800 -349L 810 -349L 810 -54C 810 -45 808 -39 797 -39C 786 -39 760 -41 760 -41L 760 -27C 784 -21 792 -9 798 9C 804 27 805 57 805 96C 917 86 932 42 932 -41L 932 -302C 951 -306 964 -315 970 -322L 853 -409Z",[0.045,0.643]],["M 972 -784L 807 -798L 807 -529L 829 -529C 879 -529 935 -547 935 -554L 935 -756C 962 -760 970 -771 972 -784Z",[0.101,0.486]]],"bbox":{"top":-854,"bottom":97,"left":60,"right":989},"hadv":1000}],"text":"喘","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.image img {\nwidth: 200px;\nmargin: 20px auto;\ndisplay: block;\nmargin: 30px auto;\n}\n\n</style>\n<p>最近看到了一些年轻人的博客，感觉我已经是个苟延残喘，勉强续命的人了。</p>\n<p>真是长江后浪推前浪，看看我自己，一没实力，二没运气，三没女朋友，说到这里</p>\n<hr />\n<p><strong>朋友，为什么不来盘守望先锋呢？</strong></p>\n<div class=\"image\">\n  <img src=\"//storage.c-3.moe/meow/plusonesec.webp\">\n</div>","plain":"最近看到了一些年轻人的博客，感觉我已经是个苟延残喘，勉强续命的人了。\n真是长江后浪推前浪，看看我自己，一没实力，二没运气，三没女朋友，说到这里\n---\n朋友，为什么不来盘守望先锋呢？\n"},{"metadata":{"id":"g13-memorial","lang":"zh-CN","title":"纪念","tags":["玩具"],"publish_time":"2016-07-03T10:31:30.077Z","update_time":"2016-07-03T10:31:30.077Z","title_outline":{"groups":[{"chars":[{"char":"纪","components":[["M 19 -102L 82 70C 95 66 106 55 112 41C 274 -51 381 -125 447 -178L 445 -187C 275 -147 92 -112 19 -102Z",[0.611,0.25]],["M 384 -773L 206 -848C 187 -770 111 -626 58 -586C 46 -579 20 -573 20 -573L 85 -417C 116 -430 138 -478 143 -556L 75 -556L 75 -544C 168 -588 297 -691 359 -768L 325 -761C 359 -751 378 -759 384 -773Z",[0.397,0.566]],["M 494 -583L 325 -670C 287 -565 158 -381 74 -328C 61 -319 30 -313 30 -313L 94 -157C 126 -170 148 -216 154 -294L 87 -294L 88 -282C 216 -345 392 -485 465 -580L 432 -574C 467 -561 487 -570 494 -583Z",[0.514,0.586]],["M 37 -567L 88 -425C 213 -479 314 -534 365 -566L 364 -576C 230 -570 95 -566 37 -567Z",[0.637,0.126]],["M 62 -317L 110 -179C 258 -241 376 -304 438 -340L 437 -351C 282 -334 126 -320 62 -317Z",[0.639,0.17]],["M 828 -767L 420 -767L 429 -739L 828 -739Z",[-0.757,0.011]],["M 453 -517L 453 -51C 453 44 489 65 612 65L 733 65C 933 65 988 44 988 -14C 988 -38 977 -53 938 -68L 934 -198L 924 -198C 901 -136 881 -91 868 -73C 859 -62 850 -59 833 -58C 816 -56 782 -56 748 -56L 635 -56C 599 -56 590 -62 590 -81L 590 -463L 604 -463L 453 -519Z",[-0.304,0.331]],["M 846 -463L 543 -463L 543 -435L 846 -435Z",[0.736,0.045]],["M 755 -767L 767 -767L 767 -342L 790 -342C 835 -342 905 -365 906 -373L 906 -709C 933 -714 949 -726 957 -736L 820 -841Z",[0.045,0.649]]],"bbox":{"top":-848,"bottom":70,"left":19,"right":988},"hadv":1000}],"text":"纪","hadv":1000,"breakAfter":true},{"chars":[{"char":"念","components":[["M 527 -768C 602 -617 723 -506 890 -447C 900 -504 925 -570 985 -594L 985 -610C 807 -629 637 -690 540 -779C 578 -784 589 -791 593 -806L 388 -866C 338 -716 201 -538 28 -436L 32 -427C 263 -489 448 -644 527 -768Z",[-0.606,0.058]],["M 180 -251L 168 -250C 172 -192 133 -140 97 -121C 62 -104 37 -73 49 -32C 64 11 115 24 153 2C 207 -28 240 -121 180 -251Z",[0.229,0.423]],["M 681 -463L 196 -463L 205 -435L 681 -435Z",[0.864,0.006]],["M 440 -289L 263 -302L 263 -54C 263 39 295 60 420 60L 542 60C 743 60 798 40 798 -21C 798 -47 788 -63 747 -77L 744 -200L 734 -200C 709 -138 690 -99 676 -81C 667 -70 660 -67 643 -66C 626 -65 592 -65 560 -65L 446 -65C 413 -65 408 -69 408 -84L 408 -263C 429 -266 438 -275 440 -289Z",[-0.472,0.169]],["M 385 -637L 379 -632C 409 -600 432 -546 432 -495C 556 -401 687 -637 385 -637Z",[-0.18,0.184]],["M 419 -326L 411 -321C 445 -277 476 -211 481 -151C 595 -63 710 -285 419 -326Z",[-0.218,0.31]],["M 616 -463L 628 -463C 604 -417 558 -340 520 -282C 576 -253 624 -248 663 -255C 694 -300 735 -366 757 -405C 781 -408 795 -415 803 -423L 679 -530Z",[0.31,0.407]],["M 738 -242L 730 -236C 780 -183 822 -100 829 -24C 958 75 1074 -188 738 -242Z",[-0.268,0.368]]],"bbox":{"top":-866,"bottom":75,"left":28,"right":1074},"hadv":1000}],"text":"念","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.entry-container {\n  text-align: center;\n}\n.post-entry {\n  border: none;\n  outline: 0;\n  margin: 40px auto;\n  padding: 15px 30px;\n  \n  font-size: 18px;\n  line-height: 24px;\n  color: white;\n  font-weight: bolder;\n  \n  background-color: #455A64;\n  transition: box-shadow 0.5s ease;\n  box-shadow: rgba(0,0,0,.6) 0 2px 3px;\n  \n  border-radius: 2px;\n  \n  cursor: pointer;\n}\n\n.post-entry:hover {\n  box-shadow: rgba(0,0,0,.6) 0 4px 6px;\n}\n</style>\n<div class=\"entry-container\">\n  <a href=\"http://memorial.thsitg.org\" style=\"opacity: 1\">\n    <button class=\"post-entry\">献上祝福</button>\n  </a>\n</div>\n<blockquote>\n<p>有的时候，我们必须放手。</p>\n</blockquote>\n<p>在这金灿灿的季节，又有一群猛士永远地离开了我们。同志们的信仰，将与我们永远同在。</p>\n","plain":"有的时候，我们必须放手。\n\n在这金灿灿的季节，又有一群猛士永远地离开了我们。同志们的信仰，将与我们永远同在。\n"},{"metadata":{"id":"lprev-2-release","lang":"zh-CN","title":"LPack Rev.2 发布","tags":["LPack","Minecraft"],"publish_time":"2016-06-24T11:32:42.090Z","update_time":"2016-06-24T11:32:42.090Z","title_outline":{"groups":[{"chars":[{"char":"L","components":[["M 41 -0L 218 -0L 219 -50L 202 -50L 42 -34Z",[0.751,0.04]],["M 41 -713L 202 -698L 240 -698L 403 -713L 403 -747L 41 -747Z",[-0.878,0.008]],["M 130 -0L 306 -0C 303 -117 303 -235 303 -346L 303 -411C 303 -514 303 -632 306 -747L 130 -747C 133 -631 133 -513 133 -395L 133 -324C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -0L 619 -0L 617 -224L 562 -224L 503 -2L 588 -39L 219 -39Z",[0.547,0.208]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":619},"hadv":651},{"char":"P","components":[["M 41 -0L 412 -0L 412 -34L 250 -50L 202 -50L 41 -34Z",[-0.873,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 306 -0C 303 -117 303 -233 303 -325L 303 -395C 303 -514 303 -632 306 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[-0.0,0.772]],["M 218 -299L 341 -299C 579 -299 665 -400 665 -525C 665 -666 573 -747 344 -747L 218 -747L 218 -709L 344 -709C 450 -709 506 -647 506 -526C 506 -414 452 -337 337 -337L 218 -337Z",[0.002,0.221]]],"bbox":{"top":-747,"bottom":0,"left":41,"right":665},"hadv":690},{"char":"a","components":[["M 185 17C 269 17 307 -18 363 -80L 404 -80L 385 -136C 322 -65 289 -51 263 -51C 218 -51 188 -80 188 -140C 188 -213 227 -259 292 -287C 322 -298 380 -313 434 -327L 434 -353C 381 -340 303 -321 253 -306C 90 -261 39 -210 39 -119C 39 -35 99 17 185 17Z",[0.131,0.181]],["M 471 16C 536 16 574 -7 600 -62L 582 -75C 563 -45 552 -37 537 -37C 518 -37 508 -50 508 -88L 508 -357C 508 -502 449 -563 307 -563C 152 -563 65 -503 56 -410C 65 -376 90 -358 126 -358C 164 -358 198 -384 201 -453L 208 -529L 136 -505C 186 -522 218 -528 250 -528C 326 -528 350 -497 350 -393L 350 -91C 360 -25 398 16 471 16Z",[-0.245,0.424]]],"bbox":{"top":-563,"bottom":17,"left":39,"right":600},"hadv":599},{"char":"c","components":[["M 314 17C 427 17 495 -24 544 -116L 525 -129C 491 -82 444 -54 386 -54C 276 -54 206 -139 206 -286C 206 -440 271 -528 360 -528C 394 -528 424 -519 461 -499L 384 -545L 398 -449C 401 -375 436 -351 478 -351C 512 -351 534 -368 545 -404C 533 -493 449 -563 339 -563C 173 -563 35 -460 35 -264C 35 -82 162 17 314 17Z",[0.062,0.225]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":545},"hadv":579},{"char":"k","components":[["M 101 -0L 270 -0C 267 -44 266 -172 266 -246L 266 -656L 270 -817L 255 -826L 31 -783L 31 -756L 104 -750L 104 -238C 104 -172 103 -44 101 -0Z",[-0.008,0.795]],["M 35 -0L 331 -0L 331 -31L 219 -41L 139 -41L 35 -31Z",[-0.866,0.001]],["M 182 -177L 588 -546L 525 -546L 356 -383L 189 -221L 182 -221Z",[0.698,0.629]],["M 452 -0L 671 -0L 671 -31L 606 -37L 420 -403L 307 -301Z",[-0.316,0.537]],["M 381 -516L 503 -501L 525 -504L 641 -516L 641 -546L 381 -546Z",[-0.612,0.043]]],"bbox":{"top":-826,"bottom":0,"left":31,"right":671},"hadv":673}],"text":"LPack","hadv":3192,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"R","components":[["M 41 -0L 395 -0L 395 -34L 235 -50L 202 -50L 41 -34Z",[0.868,0.0]],["M 41 -713L 202 -698L 218 -698L 218 -747L 41 -747Z",[-0.58,0.037]],["M 130 -0L 304 -0C 300 -117 300 -235 300 -356L 300 -385C 300 -516 300 -632 304 -747L 130 -747C 133 -630 133 -513 133 -395L 133 -351C 133 -232 133 -114 130 -0Z",[0.0,0.776]],["M 645 15C 695 15 723 10 764 -0L 764 -34L 596 -45L 681 -9L 644 -204C 624 -318 580 -374 395 -381L 395 -369C 603 -381 673 -467 673 -559C 673 -678 577 -747 402 -747L 218 -747L 218 -709L 359 -709C 460 -709 513 -655 513 -556C 513 -465 470 -390 358 -390L 220 -390L 220 -353L 348 -353C 425 -353 449 -313 463 -231L 492 -93C 502 -12 553 15 645 15Z",[-0.108,0.588]]],"bbox":{"top":-747,"bottom":15,"left":41,"right":764},"hadv":770},{"char":"e","components":[["M 323 17C 427 17 505 -31 547 -118L 528 -131C 495 -84 451 -54 380 -54C 280 -54 206 -123 206 -290C 206 -461 253 -528 310 -528C 364 -528 401 -484 401 -395C 401 -333 387 -310 341 -310L 104 -310L 104 -274L 546 -274C 551 -293 553 -310 553 -335C 553 -462 472 -563 317 -563C 170 -563 35 -461 35 -275C 35 -88 154 17 323 17Z",[0.072,0.131]]],"bbox":{"top":-563,"bottom":17,"left":35,"right":553},"hadv":586},{"char":"v","components":[["M -10 -516L 87 -504L 194 -504L 297 -516L 297 -546L -10 -546Z",[0.866,0.006]],["M 253 2L 322 2L 531 -546L 483 -546L 346 -135L 340 -120L 363 -120L 204 -546L 28 -546Z",[-0.118,0.331]],["M 392 -516L 484 -504L 506 -504L 587 -516L 587 -546L 392 -546Z",[0.287,0.029]]],"bbox":{"top":-546,"bottom":2,"left":-10,"right":587},"hadv":593}],"text":"Rev","hadv":1949,"breakAfter":false},{"chars":[{"char":".","components":[["M 170 17C 222 17 262 -24 262 -74C 262 -125 222 -167 170 -167C 118 -167 78 -125 78 -74C 78 -24 118 17 170 17Z",[0.0,0.0]]],"bbox":{"top":-167,"bottom":17,"left":78,"right":262},"hadv":340}],"text":".","hadv":340,"breakAfter":false},{"chars":[{"char":"2","components":[["M 59 -0L 561 -0L 561 -123L 131 -123L 131 -143L 119 -105C 173 -152 228 -198 265 -228C 451 -374 543 -452 543 -560C 543 -679 470 -764 312 -764C 179 -764 63 -701 57 -582C 68 -556 93 -539 122 -539C 153 -539 186 -555 197 -623L 218 -731L 168 -709C 198 -723 228 -730 256 -730C 333 -730 380 -672 380 -570C 380 -461 331 -395 222 -272C 173 -216 117 -153 59 -90Z",[0.037,0.475]]],"bbox":{"top":-764,"bottom":0,"left":57,"right":561},"hadv":613}],"text":"2","hadv":613,"breakAfter":false},{"chars":[{"char":" ","components":[],"bbox":{"top":0,"bottom":0,"left":0,"right":0},"hadv":247}],"text":" ","hadv":247,"breakAfter":true},{"chars":[{"char":"发","components":[["M 576 -824L 377 -852C 359 -561 288 -209 24 26L 33 34C 383 -141 490 -463 537 -796C 562 -798 573 -808 576 -824Z",[0.304,0.751]],["M 354 -776L 173 -822C 162 -768 120 -626 93 -563L 137 -601C 113 -594 83 -576 67 -561L 199 -483L 249 -543L 242 -543C 263 -600 303 -726 318 -777L 306 -754C 337 -751 350 -763 354 -776Z",[0.192,0.469]],["M 675 -428L 689 -428C 611 -188 408 -9 108 84L 113 95C 496 45 722 -119 841 -368C 868 -370 878 -374 886 -386L 758 -505Z",[0.573,0.534]],["M 844 -669L 769 -571L 182 -571L 190 -543L 951 -543C 965 -543 977 -548 980 -559C 929 -603 844 -669 844 -669Z",[0.844,0.049]],["M 772 -428L 370 -428L 362 -400L 772 -400Z",[0.851,0.006]],["M 388 -413L 375 -410C 409 -220 510 -18 845 93C 854 10 899 -31 977 -45L 978 -58C 596 -124 429 -253 388 -413Z",[-0.599,0.371]],["M 609 -824L 601 -819C 631 -769 663 -700 672 -634C 797 -536 925 -774 609 -824Z",[-0.078,0.269]]],"bbox":{"top":-852,"bottom":95,"left":24,"right":980},"hadv":1000}],"text":"发","hadv":1000,"breakAfter":true},{"chars":[{"char":"布","components":[["M 343 -858C 306 -656 208 -401 18 -241L 26 -232C 291 -352 424 -578 497 -776C 523 -777 532 -785 536 -796Z",[0.399,0.665]],["M 35 -671L 43 -643L 943 -643C 958 -643 970 -648 973 -659C 918 -705 828 -773 828 -773L 748 -671Z",[0.916,0.035]],["M 364 -444L 378 -444L 276 -481L 222 -407L 222 18L 249 18C 321 18 364 -13 364 -23Z",[0.016,0.703]],["M 282 -444L 282 -416L 795 -416L 795 -444Z",[-0.87,0.01]],["M 474 -605L 474 96L 501 96C 554 96 616 67 616 55L 616 -564C 641 -567 647 -577 649 -589Z",[0.007,0.796]],["M 732 -444L 732 -160C 732 -149 729 -143 715 -143C 698 -143 629 -147 629 -147L 629 -134C 669 -126 684 -111 696 -90C 707 -69 711 -35 713 11C 855 -2 874 -53 874 -144L 874 -393C 895 -398 908 -407 914 -415L 783 -513L 722 -444Z",[0.068,0.643]]],"bbox":{"top":-858,"bottom":96,"left":18,"right":973},"hadv":1000}],"text":"布","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<style>\n.entry-container {\n  text-align: center;\n}\n.post-entry.lev-2 {\n  border: none;\n  outline: 0;\n  margin: 40px auto;\n  padding: 15px 30px;\n  \n  font-size: 18px;\n  line-height: 24px;\n  color: white;\n  font-weight: bolder;\n  \n  background-color: #006064;\n  transition: box-shadow 0.5s ease;\n  box-shadow: rgba(0,0,0,.6) 0 2px 3px;\n  \n  border-radius: 2px;\n  \n  cursor: pointer;\n}\n\n.post-entry:hover {\n  box-shadow: rgba(0,0,0,.6) 0 4px 6px;\n}\n</style>\n<div class=\"entry-container\">\n  <a href=\"https://www.dropbox.com/s/vscivjeox618x20/Lius%20Pack%20Rev%202.7z&dl=0\" style=\"opacity: 1\">\n    <button class=\"post-entry lev-2\">Dropbox</button>\n  </a>\n</div>\n<h2>使用指北</h2>\n<p>将Mods分别复制到 Client/.minecraft/mods 和 Server/mods 即可启动客户端和服务端。其中服务端需要删除 Optifine 和 JourneyMap 。</p>\n<p>由于奇妙的原因，启动的时候可能需要翻墙。当然如果你已经点开上面的链接了，你可能都发现不了这个问题。</p>\n<h2>Mod 列表</h2>\n<p><a href=\"https://gist.github.com/CircuitCoder/caa226a6b5dba2a0777c8315c3223780\">Gist</a></p>\n<p>为了保护农企用户不受到核攻击，本包中不包含 SEUS，如有需要请自行下载。</p>\n<h2>镜像</h2>\n<p>如果你真的翻不了墙，那么请使用如下镜像，顺便给我捐点钱：\n<a href=\"http://adf.ly/2237350/lpack-rev-2\">Baidu Pan</a></p>\n<h2>Rev.1 下载地址</h2>\n<p>我把Rev.1也传到了<a href=\"https://www.dropbox.com/s/a8h9xt87y9p01j8/Liu%27s%20Pack%20Rev%201.7z&amp;dl=0\">Dropbox</a>上。</p>\n","plain":"\n使用指北\n将Mods分别复制到 Client/.minecraft/mods 和 Server/mods 即可启动客户端和服务端。其中服务端需要删除 Optifine 和 JourneyMap 。\n由于奇妙的原因，启动的时候可能需要翻墙。当然如果你已经点开上面的链接了，你可能都发现不了这个问题。\n\nMod 列表\nGist\n为了保护农企用户不受到核攻击，本包中不包含 SEUS，如有需要请自行下载。\n\n镜像\n如果你真的翻不了墙，那么请使用如下镜像，顺便给我捐点钱： Baidu Pan\n\nRev.1 下载地址\n我把Rev.1也传到了Dropbox上。\n"},{"metadata":{"id":"takeoff","lang":"zh-CN","title":"震撼起飞","tags":["Meta","扯淡"],"publish_time":"2016-06-15T13:27:26.316Z","update_time":"2016-11-30T09:53:23.521Z","title_outline":{"groups":[{"chars":[{"char":"震","components":[["M 130 -445L 130 -299C 130 -179 121 -32 26 82L 33 90C 250 -8 270 -183 270 -299L 270 -435L 291 -435L 130 -489Z",[0.129,0.709]],["M 158 -736L 145 -735C 149 -702 120 -673 91 -662C 57 -650 31 -625 38 -585C 47 -544 89 -528 125 -540C 176 -558 207 -633 158 -736Z",[0.173,0.343]],["M 773 -868L 708 -790L 145 -790L 153 -762L 864 -762C 878 -762 889 -767 892 -778C 846 -816 773 -868 773 -868Z",[0.773,0.051]],["M 878 -697L 150 -697L 150 -669L 878 -669Z",[0.726,0.023]],["M 840 -338L 772 -255L 181 -255L 189 -227L 934 -227C 949 -227 960 -232 963 -243C 916 -282 840 -338 840 -338Z",[0.908,0.041]],["M 808 -530L 737 -435L 192 -435L 192 -407L 909 -407C 923 -407 934 -412 937 -423C 889 -466 808 -530 808 -530Z",[0.852,0.054]],["M 396 -536L 198 -536L 198 -508L 396 -508Z",[-0.843,0.026]],["M 394 -612L 229 -612L 229 -584L 394 -584Z",[-0.454,0.038]],["M 429 -250L 324 -250L 324 -103C 324 -83 315 -71 256 -46L 323 97C 354 83 390 40 378 -44L 316 -0L 464 -49L 464 -229Z",[0.172,0.522]],["M 268 -43L 337 78C 445 16 531 -44 574 -77L 573 -88C 448 -67 323 -49 268 -43Z",[0.584,0.195]],["M 730 -427L 665 -346L 279 -346L 287 -318L 822 -318C 837 -318 847 -323 850 -334C 805 -373 730 -427 730 -427Z",[0.878,0.048]],["M 566 -484L 566 -790L 426 -790L 426 -459L 452 -459C 524 -459 566 -480 566 -484Z",[0.017,0.572]],["M 529 -251L 518 -244C 574 -41 693 37 878 87C 891 22 924 -23 977 -40L 977 -52C 783 -64 601 -103 529 -251Z",[-0.596,0.291]],["M 770 -535L 591 -535L 591 -507L 770 -507Z",[-0.386,0.089]],["M 752 -611L 592 -611L 592 -583L 752 -583Z",[-0.252,0.065]],["M 889 -141L 757 -233C 736 -194 688 -128 649 -86L 659 -75C 724 -89 799 -111 850 -131C 873 -126 883 -131 889 -141Z",[0.445,0.165]],["M 802 -697L 813 -697C 811 -663 806 -604 799 -567L 808 -561C 850 -581 904 -617 936 -644C 956 -646 966 -648 974 -657L 864 -760Z",[0.147,0.154]]],"bbox":{"top":-868,"bottom":97,"left":26,"right":977},"hadv":1000}],"text":"震","hadv":1000,"breakAfter":true},{"chars":[{"char":"撼","components":[["M 19 -382L 63 -230C 75 -234 86 -246 90 -260C 211 -344 297 -416 350 -462L 347 -471C 214 -431 71 -393 19 -382Z",[0.548,0.303]],["M 295 -696L 249 -615L 22 -615L 30 -587L 348 -587C 362 -587 371 -592 374 -603C 347 -639 295 -696 295 -696Z",[0.934,0.093]],["M 288 -839L 125 -855L 125 -70C 125 -60 121 -56 108 -56C 93 -56 31 -60 31 -60L 31 -46C 66 -38 81 -24 92 -3C 102 19 106 51 107 96C 235 84 251 33 251 -58L 251 -811C 276 -815 286 -825 288 -839Z",[0.024,0.854]],["M 409 -212L 396 -213C 397 -169 357 -119 330 -99C 297 -80 277 -45 292 -7C 310 36 371 44 399 16C 437 -22 450 -103 409 -212Z",[0.187,0.425]],["M 346 -725L 346 -532C 346 -410 346 -270 291 -160L 300 -152C 451 -254 462 -414 462 -532L 462 -715L 480 -715L 346 -763Z",[0.076,0.778]],["M 899 -776L 853 -715L 420 -715L 420 -687L 958 -687C 971 -687 981 -692 984 -703C 952 -733 899 -776 899 -776Z",[0.795,0.049]],["M 610 -219L 458 -231L 458 -35C 458 40 475 62 572 62L 655 62C 794 62 839 42 839 -6C 839 -27 832 -41 801 -54L 798 -142L 788 -142C 771 -99 756 -68 746 -56C 740 -48 733 -46 722 -46C 712 -45 691 -45 669 -45L 605 -45C 583 -45 580 -49 580 -60L 580 -194C 599 -197 608 -206 610 -219Z",[-0.39,0.183]],["M 623 -667L 582 -606L 472 -606L 480 -578L 671 -578C 685 -578 694 -583 696 -594C 670 -624 623 -667 623 -667Z",[0.66,0.023]],["M 559 -291L 559 -469L 639 -469L 639 -497L 563 -497L 475 -533L 475 -265L 487 -265C 522 -265 559 -284 559 -291Z",[0.085,0.539]],["M 627 -351L 524 -351L 524 -323L 627 -323Z",[-0.592,0.134]],["M 593 -497L 599 -497L 599 -291L 613 -291C 641 -291 683 -308 683 -315L 683 -467C 693 -469 700 -473 703 -477L 630 -533Z",[-0.093,0.702]],["M 605 -266L 595 -261C 620 -217 640 -151 636 -93C 731 -2 855 -192 605 -266Z",[-0.163,0.327]],["M 816 -841L 667 -854C 669 -593 685 -368 831 -225C 865 -193 935 -160 973 -203C 988 -221 983 -247 955 -296L 970 -433L 960 -435C 946 -400 927 -356 915 -335C 907 -321 901 -320 891 -331C 792 -428 780 -617 782 -813C 806 -817 814 -828 816 -841Z",[-0.239,0.711]],["M 981 -598L 833 -642C 815 -481 756 -341 679 -249L 690 -239C 809 -306 892 -413 942 -577C 965 -576 977 -585 981 -598Z",[0.375,0.662]],["M 803 -855L 793 -850C 810 -827 822 -788 818 -754C 892 -686 997 -826 803 -855Z",[0.36,0.63]],["M 806 -210L 796 -205C 827 -151 854 -73 852 -5C 953 89 1072 -119 806 -210Z",[-0.189,0.353]]],"bbox":{"top":-855,"bottom":96,"left":19,"right":1072},"hadv":1000}],"text":"撼","hadv":1000,"breakAfter":true},{"chars":[{"char":"起","components":[["M 81 -417C 94 -263 84 -54 15 86L 25 96C 166 -19 195 -200 207 -361C 231 -362 242 -372 246 -387Z",[0.151,0.747]],["M 30 -509L 38 -481L 522 -481C 536 -481 547 -486 550 -497C 508 -537 437 -596 437 -596L 374 -509Z",[0.98,0.068]],["M 65 -690L 73 -662L 507 -662C 521 -662 532 -667 535 -678C 493 -717 423 -773 423 -773L 362 -690Z",[0.773,0.046]],["M 157 -262L 149 -258C 192 3 294 65 519 65C 606 65 827 65 913 65C 914 13 937 -36 987 -48L 987 -60C 880 -57 623 -57 520 -57C 314 -57 220 -78 157 -262Z",[-0.785,0.087]],["M 217 -855L 217 -490L 354 -490L 354 -817C 377 -821 383 -829 384 -841Z",[0.01,0.615]],["M 245 -474L 245 -61L 375 -5L 375 -429C 402 -433 410 -444 412 -457Z",[-0.006,0.696]],["M 289 -289L 289 -261L 515 -261C 529 -261 540 -266 542 -277C 503 -319 433 -383 433 -383L 371 -289Z",[0.532,0.064]],["M 520 -776L 529 -748L 857 -748L 857 -776Z",[-0.639,0.015]],["M 545 -532L 545 -229C 545 -142 567 -119 672 -119L 763 -119C 917 -119 966 -148 966 -200C 966 -224 959 -239 926 -253L 923 -386L 912 -386C 891 -324 874 -277 862 -259C 856 -248 850 -246 837 -245C 826 -244 803 -244 779 -244L 705 -244C 680 -244 675 -248 675 -262L 675 -532L 689 -532L 545 -586L 545 -584Z",[-0.269,0.283]],["M 605 -532L 605 -504L 841 -504L 841 -532Z",[-0.81,0.002]],["M 764 -776L 764 -452L 787 -452C 830 -452 898 -474 899 -481L 899 -724C 921 -728 935 -738 942 -747L 814 -843L 753 -776Z",[0.043,0.595]]],"bbox":{"top":-855,"bottom":96,"left":15,"right":987},"hadv":1000}],"text":"起","hadv":1000,"breakAfter":true},{"chars":[{"char":"飞","components":[["M 528 -762L 43 -762L 52 -734L 528 -734Z",[0.699,0.005]],["M 422 -762L 435 -762C 433 -353 451 -12 779 77C 866 103 940 109 973 50C 987 25 981 -10 932 -62L 934 -242L 925 -242C 910 -188 895 -140 875 -105C 865 -88 855 -85 827 -91C 590 -136 576 -421 588 -710C 613 -715 628 -723 635 -731L 497 -846Z",[-0.297,0.633]],["M 537 -481L 531 -473C 634 -421 760 -322 829 -234C 995 -191 1020 -503 537 -481Z",[-0.51,0.304]],["M 965 -627L 820 -752C 771 -678 666 -538 594 -459L 601 -449C 700 -493 855 -571 925 -623C 947 -616 959 -619 965 -627Z",[0.473,0.408]]],"bbox":{"top":-846,"bottom":109,"left":43,"right":1020},"hadv":1000}],"text":"飞","hadv":1000,"breakAfter":true}],"asc":1151,"des":-286,"em":1000},"hidden":false,"wip":false,"legacy":true,"img":null},"html":"<p>于是，在前任博客突然死亡近三年以后，我的新博客终于搭起来了。</p>\n<p>虽说这是个博客，但是很显然，这只是我的一个玩具，目前来看和那些成熟的西方博客平台差到不知道哪里去：没有评论，没有媒体寄存，用户体验颓的要命，没有PushState，也许永远也不会有了。况且我对她的态度也是想写就写，所以请不要指望我对她有什么责任感。她会一直在这里，我也许在。</p>\n<p>如果我真的在这里写东西，那么大多数情况下目的都和这个博客本身存在目的相同，就是<strong>装逼</strong>。原来苦于在知乎上装逼容易被大佬识破，在微博空间里又显得太Low，于是终于有了这个玩意，可以把我的一些想法给或有或无的一些人看一看，算是一个念想。</p>\n<p>还有另一个原因就是满足我的 NIH 综合症。这个博客从底至顶，只有一个目标，就是作<strong>最大的死</strong>。后端用C++，前端单页化，前端渲染，等等，就是朝着自虐去的。之于我，年轻就是应该跟喝最冷的水，跟最新的潮流，用最(看上去) NB 的技术，追求最不能达到的目标。</p>\n<p>那么如果运气好的话，这个网站也许会慢慢的长高长大，结出许多歪瓜裂枣，作为给我自己的礼物，我也满足了。</p>\n<p>她的源码在：</p>\n<ul>\n<li>前端 <a href=\"https://github.com/CircuitCoder/C3Meow\">https://github.com/CircuitCoder/C3Meow</a></li>\n<li>后端 <a href=\"https://github.com/CircuitCoder/C3Blog\">https://github.com/CircuitCoder/C3Blog</a></li>\n</ul>\n","plain":"于是，在前任博客突然死亡近三年以后，我的新博客终于搭起来了。\n虽说这是个博客，但是很显然，这只是我的一个玩具，目前来看和那些成熟的西方博客平台差到不知道哪里去：没有评论，没有媒体寄存，用户体验颓的要命，没有PushState，也许永远也不会有了。况且我对她的态度也是想写就写，所以请不要指望我对她有什么责任感。她会一直在这里，我也许在。\n如果我真的在这里写东西，那么大多数情况下目的都和这个博客本身存在目的相同，就是装逼。原来苦于在知乎上装逼容易被大佬识破，在微博空间里又显得太Low，于是终于有了这个玩意，可以把我的一些想法给或有或无的一些人看一看，算是一个念想。\n还有另一个原因就是满足我的 NIH 综合症。这个博客从底至顶，只有一个目标，就是作最大的死。后端用C++，前端单页化，前端渲染，等等，就是朝着自虐去的。之于我，年轻就是应该跟喝最冷的水，跟最新的潮流，用最(看上去) NB 的技术，追求最不能达到的目标。\n那么如果运气好的话，这个网站也许会慢慢的长高长大，结出许多歪瓜裂枣，作为给我自己的礼物，我也满足了。\n她的源码在：\n- 前端 https://github.com/CircuitCoder/C3Meow\n- 后端 https://github.com/CircuitCoder/C3Blog\n"}]