From 95f2b614a24401f84ab4b7befa00b3b1781f156f Mon Sep 17 00:00:00 2001 From: jack Date: Fri, 28 Aug 2026 02:51:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BB=B6=E8=BF=9F=E7=93=B6=E9=A2=88=E5=AE=9E?= =?UTF-8?q?=E6=B5=8B=E4=B8=BA=E6=9C=AC=E6=9C=BA=20CPU=20=E8=80=8C=E9=9D=9E?= =?UTF-8?q?=E6=9C=BA=E6=88=BF=E4=BD=8D=E7=BD=AE=EF=BC=8C=E8=B7=A8=E7=AB=99?= =?UTF-8?q?=E5=AF=B9=E6=AF=94=E4=B8=BB=E6=8C=87=E6=A0=87=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=20compute=5Fms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户指出本机选新加坡是因为 Bitget 机房在新加坡。查证下来 ws.bitget.com 解析 到的是 CloudFront(dxotqhr62n6z4.cloudfront.net),落在新加坡 AS16509 (Amazon),即连的是 AWS 的 CDN 边缘而非 Bitget 自有机房。 腾讯云 ap-singapore(AS132203)到该边缘实测:ICMP 往返 2.1ms、TCP 握手 3.3ms、TLS 完成 9.0ms、首字节 87.8ms。首字节减 TLS 那约 79ms 是 CloudFront 回源开销,与我们的位置无关。 延迟构成(33 根样本):数据到达中位 506ms、信号计算中位 646ms、合计 1315ms。 随机房位置变化的只有那 2ms 往返,占总延迟 0.15%。而 646ms 的信号计算是每根 在 2000 根 1m 加 800 根 5m 上重建缠论结构,本机 2 核、2 个计算进程,三币同时 收盘时第三个还要排队——这才是有改善空间的一项。 因此: - 新增 deploy/netprobe.sh,把网络那一段单独量出来并入运行元数据。用到达 延迟去比两个机房等于用公斤秤称克,必须把可变的那段拿出来单独看。 - compare_sites.py 主指标改为 compute_ms,lag_data_ms 降为自检项(两站应当 接近;若差很多,先怀疑时钟而非网络)。元数据表加 nproc/cpu_model/往返。 - README 改写:第二台机器该测 CPU 规格而非地理位置,WORKERS 按核数减一给, 币数多于 worker 数时排队时间直接计入 compute_ms。 另修正站点标签:本机是腾讯云而非 Hetzner,sg-hetzner → sg-tencent,标错的 33 行数据已清掉重采。 Co-authored-by: Cursor --- research/live/compare_sites.py | 41 +++++++++++++++---- research/live/deploy/README.md | 41 ++++++++++++++++--- research/live/deploy/netprobe.sh | 69 ++++++++++++++++++++++++++++++++ research/live/deploy/start.sh | 11 ++++- 4 files changed, 147 insertions(+), 15 deletions(-) create mode 100755 research/live/deploy/netprobe.sh diff --git a/research/live/compare_sites.py b/research/live/compare_sites.py index 8bf7add..618c2c5 100644 --- a/research/live/compare_sites.py +++ b/research/live/compare_sites.py @@ -1,8 +1,17 @@ """对比两个(或多个)采集站点的数据差异。 -部署第二台机器的目的就是这个:延迟是「本地接收 − 交易所 K 线收盘」,直接 -取决于机器到交易所的网络距离,换个地理位置这个数会变。而滑点里最大的一项 -是延迟漂移,所以站点选址本身就是一个可优化的参数。 +## 该比什么(2026-08-28 实测修正) + +原以为该比地理位置,实测下来不是。腾讯云新加坡的延迟构成: + + 数据到达 506ms 其中网络仅 2ms 往返(ws.bitget.com 是 CloudFront 边缘) + 信号计算 646ms 本机 2 核,三币同时收盘还要排队 + 合计 1315ms + +换机房只能动那 2ms。**主指标是 compute_ms,不是 lag_data_ms。** + +lag_data_ms 仍然要看,但作用是**自检**:两站应当几乎相同;若差很多,先怀疑 +时钟没对齐——那比网络差异的可能性大得多。 ## 判读前必须先看的两件事 @@ -68,10 +77,21 @@ def show_meta(out_dirs: list[Path]) -> None: if not rows: return df = pd.DataFrame(rows) - keep = [c for c in ("site", "clock_offset_ms", "git_commit", "git_dirty", - "image_digest", "nproc", "mem_gb", "tz", + # net 是嵌套 dict,摊平出关心的几项 + if "net" in df.columns: + for k in ("icmp_min_ms", "tcp_connect_min_ms", "ttfb_min_ms", + "self_org", "edge_org"): + df[k] = df["net"].apply( + lambda v, k=k: v.get(k) if isinstance(v, dict) else None) + keep = [c for c in ("site", "clock_offset_ms", "nproc", "cpu_model", + "icmp_min_ms", "ttfb_min_ms", "git_commit", + "git_dirty", "image_digest", "mem_gb", "tz", "started_utc") if c in df.columns] print(df[keep].to_string(index=False)) + if "icmp_min_ms" in df and df["icmp_min_ms"].notna().any(): + x = df["icmp_min_ms"].astype(float) + print(f"\n 到 Bitget 边缘的往返:{x.min():.1f}~{x.max():.1f}ms。" + f"站间极差 {x.max() - x.min():.1f}ms 就是换机房的全部空间") if "clock_offset_ms" in df and df["clock_offset_ms"].notna().any(): o = df["clock_offset_ms"].astype(float) spread = float(o.max() - o.min()) @@ -94,7 +114,10 @@ def compare_latency(df: pd.DataFrame, col: str = "lag_data_ms") -> None: f"等第二台机器的数据到齐") return - print(f"\n########## 二、到达延迟({col}) ##########") + label = {"compute_ms": "信号计算耗时(主指标,取决于 CPU)", + "lag_data_ms": "数据到达延迟(自检项,两站应当接近)", + "lag_signal_ms": "合计到可下单"}.get(col, col) + print(f"\n########## {label}({col}) ##########") print("\n 全量(各站各自的样本,时段可能不同)") for s in sites: x = df[df["site"] == s][col].dropna().astype(float) @@ -176,7 +199,11 @@ def main() -> None: show_meta([p for p in metas if p.is_dir()]) df = load(lat) - compare_latency(df) + # compute_ms 是主指标:它是延迟里唯一有大幅改善空间的一项(646ms vs + # 网络的 2ms)。lag_data_ms 放后面,作用是自检两站是否可比 + compare_latency(df, "compute_ms") + compare_latency(df, "lag_data_ms") + compare_latency(df, "lag_signal_ms") compare_drift(drf) diff --git a/research/live/deploy/README.md b/research/live/deploy/README.md index 898ccee..18c8889 100644 --- a/research/live/deploy/README.md +++ b/research/live/deploy/README.md @@ -2,13 +2,34 @@ 在第二台机器上跑一套完全相同的采集,用来看不同地理位置的数据差异。 -## 为什么要跨地采集 +## 先看这一节:延迟的瓶颈不在机房 -滑点里最大的一项是**延迟漂移**:从 K 线收盘到实际下单之间,价格已经走掉的 -那部分。而延迟 = 交易所出包 + 网络传输 + 本地处理。本机(新加坡)实测到达 -延迟中位 350~650ms,其中网络传输占多少、换个机房能压掉多少,只有实测。 +滑点里最大的一项是**延迟漂移**,所以延迟越低越好。但延迟拆开之后,可优化的 +地方和直觉不一样。腾讯云新加坡实测(2026-08-28): -延迟压下来直接等于滑点下降,所以机房选址是个可优化参数,不是固定成本。 +| 构成 | 中位 | 随机房位置变化吗 | +| --- | --- | --- | +| 数据到达(交易所推送 + 回源 + 网络) | 506ms | 只有网络那段,**2ms** | +| 信号计算(本机 CPU) | **646ms** | 不变,取决于 CPU | +| 合计到可下单 | 1315ms | | + +`ws.bitget.com` 解析出来是 **CloudFront**(`dxotqhr62n6z4.cloudfront.net`), +落在新加坡的 AS16509(Amazon)。所以我们连的是 AWS 的 CDN 边缘,不是 Bitget +自己的机房。从腾讯云新加坡到这个边缘: + + ICMP 往返 2.1ms + TCP 握手 3.3ms + TLS 完成 9.0ms + 首字节 87.8ms ← 减去 TLS 的 9ms,约 79ms 是 CloudFront 回源开销 + +回源那 79ms 和交易所自己的推送节奏,不管我们坐在哪都一样。而随位置变化的 +只有那 2ms 往返。**换机房的全部空间是 1~2ms,占总延迟 1315ms 的 0.1%。** + +真正的大头是本机 646ms 的信号计算:每根 K 线要在 2000 根 1m 加 800 根 5m 上 +重建缠论结构,三个币同时收盘而本机只有 2 核、2 个计算进程,第三个币还要排队。 + +**所以第二台机器该测的是 CPU 规格,不是地理位置。** 看 `compute_ms`,不是 +`lag_data_ms`。3 个币至少要 3 个 worker,`--workers` 给到核数减一。 ## 三个必须一致,一个必须不同 @@ -41,9 +62,14 @@ git clone ssh://jack@git.jackyu66.com:2222/jack/chan.git cd chan && git checkout chan bash research/live/deploy/setup.sh # 装 docker + chrony,拉镜像 -SHADOW_SITE=aws-tokyo bash research/live/deploy/start.sh + +# 站点名带上机型,因为要比的是 CPU 而不是位置 +SHADOW_SITE=aws-sg-c7a4x WORKERS=3 bash research/live/deploy/start.sh ``` +`WORKERS` 按核数减一给。3 个币同时收盘,worker 少于 3 就会排队,而排队时间 +直接计入 `compute_ms`。本机 2 核只能给 2,这本身就是 646ms 里的一部分。 + 确认健康: ```bash @@ -88,6 +114,9 @@ python research/live/compare_sites.py \ 市场性质,与机器位置无关。若漂移也差很多,先怀疑时钟或时段没对齐,而不是 急着下结论。 +同理,`lag_data_ms` 两站也应当几乎相同(网络那段只有 2ms 空间)。真正该出现 +差异的是 `compute_ms`。如果 `lag_data_ms` 差很多,先查时钟——比查网络更可能。 + ## 资源占用 本机实测:内存约 1.5GB(两个计算进程 + 盘口缓冲),CPU 单核不满。 diff --git a/research/live/deploy/netprobe.sh b/research/live/deploy/netprobe.sh new file mode 100755 index 0000000..356f8e7 --- /dev/null +++ b/research/live/deploy/netprobe.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# 量本机到 Bitget 端点的网络距离,输出 JSON。start.sh 会把它并进运行元数据。 +# +# 为什么要单独量:K 线到达延迟(lag_data_ms)是「交易所推送节奏 + 回源 + 网络」 +# 三者之和,中位 506ms。其中只有最后一段随机房位置变化,而实测它只有 2ms +# 往返——用到达延迟去比两个机房,等于用公斤秤称克。这个探测把可变的那一段 +# 单独拿出来。 +# +# 还有一件事值得知道:ws.bitget.com 解析出来是 CloudFront(AWS 的 CDN 边缘), +# 不是 Bitget 自己的机房。所以「离交易所近」实际是「离 CloudFront 边缘近」。 +set -uo pipefail + +WS_HOST="${WS_HOST:-ws.bitget.com}" +N="${N:-10}" + +resolved="$(getent hosts "$WS_HOST" 2>/dev/null | head -1 || true)" +edge_ip="$(awk '{print $1}' <<<"$resolved")" +cname="$(awk '{print $2}' <<<"$resolved")" + +icmp_min=null; icmp_avg=null +if out="$(ping -c "$N" -q -W 2 "$WS_HOST" 2>/dev/null)"; then + stats="$(grep -oE 'rtt min/avg/max/mdev = [0-9./]+' <<<"$out" | awk '{print $NF}')" + if [[ -n "$stats" ]]; then + icmp_min="$(cut -d/ -f1 <<<"$stats")" + icmp_avg="$(cut -d/ -f2 <<<"$stats")" + fi +fi + +# TCP 握手是一个完整往返,比 ICMP 更能代表实际连接路径(有些网络对 ICMP 降级) +tcp_min=null; tls_min=null; ttfb_min=null +if command -v curl >/dev/null 2>&1; then + vals="$(for _ in $(seq "$N"); do + curl -s -o /dev/null --max-time 8 \ + -w '%{time_connect} %{time_appconnect} %{time_starttransfer}\n' \ + "https://$WS_HOST/v2/ws/public" 2>/dev/null + done)" + if [[ -n "$vals" ]]; then + tcp_min="$(awk '{print $1*1000}' <<<"$vals" | sort -n | head -1)" + tls_min="$(awk '{print $2*1000}' <<<"$vals" | sort -n | head -1)" + ttfb_min="$(awk '{print $3*1000}' <<<"$vals" | sort -n | head -1)" + fi +fi + +org="unknown" +if [[ -n "$edge_ip" ]]; then + org="$(curl -s --max-time 6 "https://ipinfo.io/$edge_ip/json" 2>/dev/null \ + | awk -F'"' '/"org"/{print $4}')" + [[ -n "$org" ]] || org="unknown" +fi +self_org="$(curl -s --max-time 6 https://ipinfo.io/json 2>/dev/null \ + | awk -F'"' '/"org"/{print $4}')" +self_city="$(curl -s --max-time 6 https://ipinfo.io/json 2>/dev/null \ + | awk -F'"' '/"city"/{print $4}')" + +cat </dev/null 2>&1 || true mkdir -p "$OUT" +say "量网络距离" +netprobe="$(bash "$(dirname "${BASH_SOURCE[0]}")/netprobe.sh" 2>/dev/null || echo '{}')" +echo "$netprobe" | grep -E 'edge_org|self_org|self_city|icmp_min_ms|tcp_connect' || true + # 运行元数据。两地数据对不上时,先看这个文件——镜像摘要、代码版本、时钟偏移 -# 三者任一不同都足以解释差异,不必去猜。 +# 三者任一不同都足以解释差异,不必去猜。网络探测并在这里,因为「换机房能省 +# 多少」这个问题只有它能回答(到达延迟里网络只占约 2ms,用它比等于用公斤秤称克)。 meta="$OUT/run_meta_${SHADOW_SITE}.json" cat >"$meta" <"$meta" </dev/null || echo unknown)", + "mem_gb": $(free -g | awk '/^Mem:/{print $2}'), + "net": $netprobe } EOF echo "元数据已写 $meta"