HackMD
  • New!
    New!  “Bookmark” and save your note
    Find a note that's worth keeping or want reading it later? “Bookmark” it to your personal reading list.
    Got it
      • Create new note
      • Create a note from template
    • New!  “Bookmark” and save your note
      New!  “Bookmark” and save your note
      Find a note that's worth keeping or want reading it later? “Bookmark” it to your personal reading list.
      Got it
      • Options
      • Versions and GitHub Sync
      • Transfer ownership
      • Delete this note
      • Template
      • Save as template
      • Insert from template
      • Export
      • Dropbox
      • Google Drive
      • Gist
      • Import
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
      • Download
      • Markdown
      • HTML
      • Raw HTML
      • ODF (Beta)
      • Sharing Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • More (Comment, Invitee)
      • Publishing
        Everyone on the web can find and read all notes of this public team.
        After the note is published, everyone on the web can find and read this note.
        See all published notes on profile page.
      • Commenting Enable
        Disabled Forbidden Owners Signed-in users Everyone
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Invitee
      • No invitee
    Menu Sharing Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Versions and GitHub Sync Transfer ownership Delete this note
    Export
    Dropbox Google Drive Gist
    Import
    Dropbox Google Drive Gist Clipboard
    Download
    Markdown HTML Raw HTML ODF (Beta)
    Back
    Sharing
    Sharing Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Note Permission
    Read
    Owners
    • Owners
    • Signed-in users
    • Everyone
    Owners Signed-in users Everyone
    Write
    Owners
    • Owners
    • Signed-in users
    • Everyone
    Owners Signed-in users Everyone
    More (Comment, Invitee)
    Publishing
    Everyone on the web can find and read all notes of this public team.
    After the note is published, everyone on the web can find and read this note.
    See all published notes on profile page.
    More (Comment, Invitee)
    Commenting Enable
    Disabled Forbidden Owners Signed-in users Everyone
    Permission
    Owners
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Invitee
    No invitee
       owned this note    owned this note    
    Published Linked with
    Like BookmarkBookmarked
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # ISUCON10 本選当日マニュアル ## 課題アプリケーション XSUCON について 20XX 年、人類はオーガナイザー X41 氏の主催するパフォーマンスチューニングコンテスト「XSUCON」に夢中になっていた。しかし開催直前となったある日、最新版の XSUCON ポータルサイトにはパフォーマンスに問題があることが発覚。このままでは多くの人にとって不満の残る大会になってしまうだろう。あなたは XSUCON 運営チームの一人としてパフォーマンスを改善しつつ、また大会を大いに盛り上げ、選手およびオーディエンスを満足させなければならない。 ### 課題アプリケーション仕様 課題アプリケーション XSUCON の仕様については、[XSUCON アプリケーションマニュアル](https://hackmd.io/Ip71mfq8TH2fECehU8RaTg)を参照してください。 ## ISUCON10 本選 ポータルサイト ISUCON10 本選の競技 (実競技) は下記ポータルサイトを利用します。 事前に登録した情報を用いてログインしてください。 なお、このページは競技開始時刻までアクセスすることはできません。 ポータルサイトでは、ベンチマークの実行・結果確認、質問/サポート依頼の送信、リーダーボードの確認ができます。 https://portal.isucon.net/contestant ### リーダーボードの更新について ポータルサイト上のリーダーボードのスコアは、競技終了前の 1 時間は他チームのスコアが更新されなくなり、自チームのスコアのみ確認が可能になります。 ### Discord の利用について ISUCON 10 サポート Discord サーバは競技時間前後はすべてのチャンネルが発言不可となります。 ポータルサイトを通して質問やサポート依頼を送信することができますので、そちらを利用してください。 ただし、選手は Discord の確認が可能な状態、通知が受け取れる状態を維持してください。 これはポータルで送信した質問/サポート依頼の内容を運営が確認した上で、リアルタイムでのチャットが必要だと判断した場合、こちらから Discord 上でプライベートチャンネルを作成し、mention の上よびかけを行う場合があるためです。 また、アナウンス等も Discord で実施されます。 ## サーバ、ネットワーク構成について 事前に用意されたサーバは 3 台あり、これらのサーバに SSH を用いて接続し競技を行います。 ポータル右上に表示されているチーム ID を元に、以下の gist より割り当てられている「踏み台用 IP アドレス」と「チームサブネット」を確認してください。 https://gist.github.com/whywaita/b253737c5fdadbe6cfab86c3a2a3d861 競技に用いる 3 台のサーバはチームのサブネットに対してそれぞれ 101 ~ 103 が第 4 オクテットとなります。具体的な IP アドレスはポータルにて確認することができます。 上記のサーバに接続するために踏み台を経由して SSH 接続を行います。 [ssh_config(5)](https://man.openbsd.org/ssh_config.5) の例を以下に示します。なお、あくまで例示であり必ず以下の設定を利用する必要はありません。 ``` Host isucon-bastion HostName <踏み台用IPアドレス> Port 20340 User isucon Host isucon-server ProxyJump isucon-bastion User isucon HostName <自チームサーバのIPアドレス> ``` なお、踏み台用のサーバはポート番号 `20340` でログインすることができます。 ### 重要事項 **競技終了後は、ベンチマーク走行成績の追試を行いますので、Discord サーバ および http://isucon.net/ にて運営からお知らせをするまで、サーバの操作はしないでください。** 競技終了後の作業は禁止行為にあたります。 **競技に利用できる計算機資源は運営側が用意した 3 台のインスタンスのみです。** 外部のメトリクス計測サービスの使用のみ特例として許可しますが、スコアを向上させるいかなる効果も持つものであってはいけません。 ## 作業手順 以下の順序で作業を開始してください。 ### 1. サーバーへのログイン 上記に記載したサーバーに対して SSH 接続してください。 ログインには参加登録に利用した ( = ポータルのログインに利用している) GitHub アカウントに登録されている SSH 鍵を利用します。 SSH ログインのユーザ名は `isucon` です。 **[重要]`isucon` 以外のユーザーに関して、ユーザー削除や既存の公開鍵の削除、その他 sshd の設定変更等を行ったことにより運営による追試をおこなうことができない場合は、失格とします。** ### 2. アプリケーションの動作確認 アプリケーションは Web ブラウザから利用することができます。 踏み台を経由したブラウザアクセスには、 [SSH におけるローカルポートフォワーディング](https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding#Local_Port_Forwarding) などを用いて表示することができます。 これ以外の方法で動作確認してもかまいません。 なお、初期状態ではアプリケーションの動作に必要なデータが不足しているため、アプリケーションをブラウザから動作確認するためには、一度負荷走行を実行してください (後述)。 以下に Team001 におけるローカルポートフォワーディングを実行するコマンドを例示します。 これは「リモートホスト `isucon-server` に SSH 接続をした上で」「ローカルの `localhost:10443` への TCP 接続を」「リモートホストを通して `10.160.1.101:443` へ転送する」というコマンドです。 ```shell $ ssh -L localhost:10443:10.160.1.101:443 isucon-server ``` サーバーへ配置されている TLS 証明書の subject name は `*.t.isucon.dev` となっています。 `*.t.isucon.dev` の DNS レコードは `127.0.0.1`, `::1` が設定されているため、 `t.isucon.dev` のサブドメインを利用して `localhost` のポートへアクセスすることで、TLS 証明書検証エラーを回避することができます。 以上を踏まえると、上記のコマンド例を実行している場合、 https://xsuportal.t.isucon.dev:10443 でアプリケーションへアクセスすることができます。 #### アプリケーションへのログイン方法 以下は https://xsuportal.t.isucon.dev:10443 でアプリケーションへアクセスできるように設定した場合の例です。 - 仮想オーディエンス向けページ - https://xsuportal.t.isucon.dev:10443/ - 仮想選手向けページ(要ログイン) - https://xsuportal.t.isucon.dev:10443/contestant - 仮想運営向けページ(要ログイン) - https://xsuportal.t.isucon.dev:10443/admin - 仮想運営ユーザ(admin)でのログインが必要です。 負荷走行が正常に実行された場合下記の 4 ユーザが登録されるので、動作確認にご利用ください。ログインはトップページ(仮想オーディエンス向けページ)から行うことができます。 | ログイン ID (contestant_id) | パスワード | 備考 | | --------------------------- | ---------- | ---------- | | admin | admin | 仮想運営 | | isucon1 | isucon1 | 仮想選手 | | isucon2 | isucon2 | 仮想選手 | | isucon3 | isucon3 | 仮想選手 | #### データベースの初期化方法 初期状態のアプリケーションでは、初期化処理(`POST /initialize`)においてデータベースのレコードは削除しますがスキーマは初期化されません。スキーマを初期状態に戻したい場合は、以下の SQL ファイルをご利用ください。 ``` ~isucon/webapp/sql/schema.sql ``` #### 動作確認に便利なスクリプト集 競技サーバーの `~isucon/webapp/tools` ディレクトリ以下には、アプリケーションの動作確認に利用できる下記のスクリプトが置いてあります。 詳しい使い方は `~isucon/webapp/tools/README.md` を参照してください。 | File | 説明 | | ---------------------- | ----------------------------------------------------------------------- | | `add_benchmark_job` | 仮想ベンチマークジョブのエンキューを行えます。 | | `finish_benchmark_job` | 仮想ベンチマークサーバから 1 件デキューし、仮想負荷走行を完了させます。 | | `show_notifications` | `notifications` テーブルの中身をデコードして表示します。 | ### 3. 負荷走行 (ベンチマーク) 負荷走行はポータルサイト上からリクエストします。 ポータルサイトの [競技参加者向けページ](https://portal.isucon.net/contestant) にアクセスし、 "Job Enqueue Form" から負荷走行対象のサーバーを選択、"Enqueue" をクリックで負荷走行のリクエストが行われ、順次開始されます。 なお、負荷走行が待機中 (PENDING) もしくは実行中 (RUNNING) の間は追加の Enqueue を行うことはできません。 ### 参考実装 下記の言語での実装が提供されています。 - Ruby - Rust - Go - Node.js ### 参考実装の切り替え方法 初期状態では Ruby による実装が起動しています。 各言語実装は systemd で管理されています。 例えば、参考実装を Ruby から Go に切り替えるには次のようにします。 ```shell sudo systemctl disable --now xsuportal-web-ruby.service sudo systemctl disable --now xsuportal-api-ruby.service sudo systemctl enable --now xsuportal-web-golang.service sudo systemctl enable --now xsuportal-api-golang.service ``` ### `/etc/hosts` および `*.t.isucon.dev` ドメインについて サーバーには初期状態で、割り当てられている 3 台のサーバーの IP アドレス + ベンチマーカーの IP アドレスが事前に `/etc/hosts` へ登録されています。これらのホスト名は自由に利用して構いません (これを利用しなくても構いません)。 例: ``` isu1.t.isucon.dev 10.160.1.101 isu2.t.isucon.dev 10.160.1.102 isu3.t.isucon.dev 10.160.1.103 isubench.t.isucon.dev 10.160.1.104 ``` 前述の通り、これ以外の `*.t.isucon.dev` の FQDN に関しては `127.0.0.1` (IPv6 は `::1`) の DNS レコードが登録されています。また、サーバーに配置されている TLS 証明書は subject name が `*.t.isucon.dev` であるため、この名前であれば TLS 証明書の検証が通る状態で HTTPS 接続等を行うことができるようになっています。 ベンチマーカーにも同様の `/etc/hosts` エントリが登録されています。負荷走行の際は、ベンチマーカーより負荷走行の対象となるサーバーに対応する `isu1` - `isu3.t.isucon.dev` のホスト名を利用した HTTPS 接続が行われます。その際、TLS 証明書検証が通る必要がある旨、留意してください。 また、ベンチマーカーの IP アドレスは `isubench.t.isucon.dev` として登録されています。この `/etc/hosts` エントリについて、編集しても構いませんが、その場合に負荷走行が正しく動作するかは運営は保証しません。 ### 時計について 運営が管理するベンチマーカーについては、Google Public NTP サーバー (time1.google.com, time2.google.com, time3.google.com, time4.google.com) と systemd-timesyncd を利用して時刻同期が設定されています。 選手へ提供されるサーバーについても、初期状態で同様の設定がされています。 ## 負荷走行について ベンチマーカーによる負荷走行は以下のように実施されます。 1. 初期化処理の実行 `POST /initialize` (20 秒でタイムアウト) 2. アプリケーション互換性チェック (数秒~数十秒) 3. 初期化処理の実行 `POST /initialize` (20 秒でタイムアウト) 4. 負荷走行 (60 秒) 5. 待ち時間 (5 秒) 6. 整合性チェック (数秒〜数十秒) 初期化処理は 2 回実行され、それぞれ 20 秒以内に完了する必要があります。これを超えた場合、負荷走行は失敗になります。 ベンチマーカーは負荷走行終了ののち、5 秒待ってから整合性チェックを行います。 ジョブキューによる遅延処理等を追加した場合は、このタイミングまでに処理の整合性をとってください。 負荷走行終了後、5 秒経ってもレスポンスが返ってきていないリクエストはすべて強制的に切断され、タイムアウトとして数えられます。 アプリケーション互換性チェックもしくは整合性チェックが通らなかった場合、その負荷走行は失敗となります。 ### キャッシュについて アプリケーションは下記の条件においてキャッシュが認められています。 - `GET /api/audience/dashboard` - アプリケーションは、データの更新から最大 1 秒古い情報を返すことができます。ただし、ベンチマーカーが検知しない限りはそれより古い情報を返しても構いません。 - 上記以外の HTTP リクエスト - データの更新が即時反映されていることを期待してベンチマーカーは検証を行います。ただし、ベンチマーカーが検知しない限りは古い情報を返しても構いません。 #### Conditional GET のサポートについて また、実ベンチマーカーは一般的なブラウザの挙動を模した [Conditional GET](https://tools.ietf.org/html/rfc7232) に対応しています。アプリケーションは、 `Cache-Control` やその他必要なレスポンスヘッダを返すことで、ベンチマーカーから Conditional GET リクエストを受けることができます。データが更新されていないことが期待されるリクエストにおいては、`304 Not Modified` を返したり、あるいはブラウザのキャッシュ有効期限の制御によってリクエストが発生していなかったりしても、ベンチマーカーはそれらのキャッシュを利用してレスポンスがあったものとみなします。 なお、ベンチマーカー内のユーザーは独立しているため、 `Cache-Control: public` 等が指定されていたとしても、ユーザー同士でキャッシュを共有することはありません。すなわち、ユーザー (仮想選手、仮想オーディエンス、仮想運営等) の間でブラウザキャッシュが使い回されることはありません。 ### タイムアウトについて 実ベンチマーカーにおいて設定されているタイムアウト値は下記の通りです。 - 仮想ポータル - `POST /initialize` - 20 秒以内にレスポンスを返す必要があります。これを超えた場合、負荷走行は即時失敗します。 - `GET /api/contestant/dashboard`, `GET /api/audience/dashboard` - 2 秒以内にレスポンスを返す必要があります。これを超えた場合、後述のスコア計算に従い減点の対象となります。 - 上記以外の HTTP リクエスト - 10 秒以内にレスポンスを返す必要があります。これを超えた場合、後述のスコア計算に従い減点の対象となります。 - 仮想ベンチマークサーバ - タイムアウトは規定しません。 なお、負荷走行終了から 5 秒経った時点でレスポンスを返していないリクエストについては強制的に切断され、上記のタイムアウト時間にかかわらずタイムアウトとして処理されます。 ## スコア計算 負荷走行のスコアは以下の計算式によって算出されます。 ``` スコア = (仮想選手スコア * 大会規模ボーナス) + 仮想オーディエンススコア - 減点 ``` - 仮想選手スコア - 仮想負荷走行が 1 回完了する (10 点) - 仮想選手の質問(Clarification)に対して仮想運営から回答が行われたとき、その回答を質問者の仮想チームが初めて確認する (10 点) - 仮想選手がダッシュボードを表示する (2 点) - 大会規模ボーナス - 仮想選手の参加数によるボーナス (後述) - 仮想オーディエンススコア - 仮想オーディエンスがダッシュボードを表示する (10 回ごとに 1 点) ### 大会規模ボーナス 大会規模ボーナスは、仮想コンテストに参加した仮想選手の数(team に所属している contestant の総数)によって、以下の表に従って算出されます。 | 参加した仮想選手の数 | 大会規模ボーナス(倍率) | | -------------------- | ------------------------ | | 1-59 | 1.0 | | 60-119 | 1.2 | | 120-179 | 1.4 | | 180-239 | 1.6 | | 240-299 | 1.8 | | 300- | 2.0 | ### 失敗 (fail) と減点について 負荷走行時に発生するエラーによっては、減点されたり、即時失敗(fail)したりします。条件は以下の通りです。 - アプリケーション互換性チェック、もしくは整合性チェックに失敗した - 1 回以上で即時失敗 - 負荷走行中にアプリケーション起因の致命的な問題が発生した - 1 回以上で即時失敗 - (例として、仮想チーム登録フェーズ中に、1仮想チームも登録ができなかった場合が該当します) - HTTP ステータスコードやレスポンス内容などに誤りがある - 1 回あたり減点 50 点 - 100 回を越えたら即時失敗 - リクエストがタイムアウトした場合 (条件は前項に記載) - 100 回あたり減点 100 点 - 即時失敗は無し 計算の結果、スコアが 0 点以下になった場合は失敗として扱われます。また、即時失敗となったケースについても、0 点と数えられます。 ### 特別賞 競技時間中のスコアが、最初に **20,000** を超えた 1 チームを特別賞とします。 ## 最終スコア 競技時間終了後、**再起動後に運営によって実行された負荷走行のスコア**を最終スコアとします。 ### 競技時間終了後に運営によって行う作業手順 1. 全チームのサーバーを再起動し、10 分以上待つ - 運営がサーバー上で `sudo systemctl poweroff` を実施し、サーバーのシャットダウンを確認した後、サーバーを起動します。 - __お願い:__ 再起動のテストのため、意図的に poweroff されたサーバーの起動依頼について、運営では対応する余力がなく、ベストエフォートでの対応になります。確実にシステムを再起動するため、再起動手順をこのように定義していますが、競技時間中に再起動をテストする場合、`sudo systemctl reboot` 等で実施してください 2. 全チームのベンチマークを運営より実行 - 各チームの、競技時間中最後の負荷走行の対象となったサーバーへ負荷走行を行う。 - 計測は各チーム 3 回ずつ実施する。 3. (2) で実施した最後の負荷走行が fail となっているチームに関しては、再度計測を実施する - この際、再度 fail となったチームは失格とする。 4. 全チームのサーバーを (1) と同手順で再起動し、ブラウザから動作確認を行う - 10 分を待たずにチェックを開始するが、動作が確認できなかった場合は 10 分経過を待つ。 - ここで正常な動作が確認できなかったチームは失格とする。 5. (2) の負荷走行で計測したスコアのうち、その中で最も高いスコアをそのチームの最終スコアとする - fail については 0 点と数える。 ### 競技終了後の注意事項 - 運営によるブラウザからの動作確認の際、運営は `POST /initialize` をリクエストしない旨留意すること。 - 競技時間終了後は、選手は与えられたサーバーにおいて一切の操作を行わないでください。競技時間終了後の操作は失格となります。 # レギュレーション ## ソフトウェア事項 選手は主催者から Web アプリケーション (問題) が与えられ、選手は競技時間内にその Web アプリケーションの高速化を行う。選手は高速化された実装 (回答) を作成する時、主催者より与えられたソフトウェア (初期実装) をベースに実装しても良いし、しなくても良い。 どのプログラミング言語で初期実装が提供されるかは主催者は事前にアナウンスするが、その各々の性能が一致することは保証されない。 高速化の際、主催者より問題として与えられた Web アプリケーションから、以下の部分は変更しないこと。 - アクセス先の URI、ただしサーバー側で生成する部分(ID など)は文字種([0-9] や [0-9a-zA-Z_] など)を変えない範囲で自由に生成しても良い - レスポンス (HTML の DOM, JSON オブジェクト等) の構造(表示に影響しない範囲での空白文字の増減は許可される) - JavaScript/CSS ファイルの内容 - 画像および動画等のメディアファイルの内容 各サーバにおけるソフトウェアの入れ替え、設定の変更、アプリケーションコードの変更および入れ替えなどは一切禁止しない。 ベンチマーク中にポータル・マニュアル・レギュレーションといった、主催者の指示以外で利用が認められたサーバー以外の外部リソースを使用する行為(他のインスタンスに処理を委譲するなど) は禁止する。 ただしモニタリングやテスト、開発などにおいては、PC や外部のサーバーを利用しても構わない。 許可される事項には、例として以下のような作業が含まれる。 - 複数台あるサーバーの役割の変更 - DB スキーマの変更やインデックスの作成・削除 - データベースに利用するミドルウェアの変更 - キャッシュ機構の追加、ジョブキュー機構の追加による遅延書き込み - Web Push 実装の追加(XSUCON アプリケーションマニュアルを参照) - HTTP レスポンスの圧縮 - 他の言語による再実装 ただし以下の事項に留意すること。 - コンテスト進行用のメンテナンスコマンドが正常に動作するよう互換性を保つこと - サーバ再起動後にすべてのアプリケーションコードが正常動作する状態を維持すること - ベンチマーク実行時にアプリケーションに書き込まれたデータは再起動後にも取得できること ## 質問 選手は主催者へ質問を送信することができる。競技時間中は原則としてポータルから、競技前後は Discord 上のサポートチャットを利用する。質問は競技内容・マニュアル・レギュレーション等に対する疑問点・明確にしたい事項の確認や、サーバー障害などのトラブル報告・サポート依頼に利用することができるが、これに限らない。主催者は質問された内容について競技の一環である場合は、回答できない旨返答することがある。 競技時間中の質問について、主催者からの回答は全選手へ公開、あるいは個別に回答される。全選手へ公開される場合、質問内容の原文、あるいは主催者による内容の要約が公開される。未回答の質問・未公開の回答については質問した選手およびそのチームメンバー、主催者のみが確認できる。質問への回答/更新はポータルサイト上にて選手へ通知される。 主催者は競技時間中の質問への回答について、原則として全選手へ公開する。ただし、重複する質問や、選手およびチーム個別の問題 (サーバ障害など) に対する対応の場合、この限りではない。 ## 禁止事項 以下の行為を特に禁止する。 - 競技終了時間までに、競技の内容に関するあらゆる事項 (問題内容・計測ツールの計測方法など)を公開・共有すること(内容を推察できる発言も含む) - 不特定多数への公開はもちろん、他チームの選手と連絡を取り、問題内容等を共有する事 (結託行為) も禁止とする。 - ただし主催者が Twitter, Web サイトにおいて公開している情報は除く。ポータルサイトにおけるログインを要するページにおいて記載されている内容は公開情報でない旨留意すること。 - 主催者が他チームへの妨害、競技への支障となるとみなす全ての行為 - 主催者が競技に不必要とみなす競技環境からのネットワークアクセス - 競技に必要なネットワーク利用としては、主催者の指示 (レギュレーション, マニュアル等含む) で許可・想定されている行為、提供されたインスタンスの初期状態で利用可能なサービスや、外部のバージョン管理システム (GitHub 等)、ソフトウェアパッケージのリポジトリ (apt, yum リポジトリや、docker, npm, RubyGems レジストリ, proxy.golang.org, crates.io 等) が例として挙げられる。 - 一方、提供されたインスタンスからインターネットまでの経路上にあるホスト等、選手がその選手へ提供されていないホストについて直接のアクセスを試みる行為や、外部への不正アクセスを試みる行為は、主催者により不必要と判断される場合がある。なお、例示のため、これに限らない。 本マニュアルにおいて禁止とされた行為 (禁止事項) への違反は、失格となる。

    Import from clipboard

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lost their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template is not available.
    All
    • All
    • Team
    No template found.

    Create a template

    Delete template

    Do you really want to delete this template?

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in via Google

    New to HackMD? Sign up

    Help

    Documents

    Tutorials
    YAML Metadata
    Slide Example
    Book Example

    Contacts

    Talk to us
    Report an issue
    Send us email

    Cheatsheet

    Example Syntax
    Header # Header
    • Unordered List
    - Unordered List
    1. Ordered List
    1. Ordered List
    • Todo List
    - [ ] Todo List
    Blockquote
    > Blockquote
    Bold font **Bold font**
    Italics font *Italics font*
    Strikethrough ~~Strikethrough~~
    19th 19^th^
    H2O H~2~O
    Inserted text ++Inserted text++
    Marked text ==Marked text==
    Link [link text](https:// "title")
    Image ![image alt](https:// "title")
    Code `Code`
    var i = 0;
    ```javascript
    var i = 0;
    ```
    :smile: :smile:
    Externals {%youtube youtube_id %}
    LaTeX $L^aT_eX$

    This is a alert area.

    :::info
    This is a alert area.
    :::

    Versions

    Versions and GitHub Sync

    Sign in to link this note to GitHub Learn more
    This note is not linked with GitHub Learn more
     
    Add badge Pull Push GitHub Link Settings

    Version named by    

    More Less
    • Edit
    • Delete

    Note content is identical to the latest version.
    Compare with
      Choose a version
      No search result
      Version not found

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub

        Please sign in to GitHub and install the HackMD app on your GitHub repo. Learn more

         Sign in to GitHub

        HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully