今日已更新 339 条资讯 | 累计 19899 条内容
关于我们

标签:#performance

找到 115 篇相关文章

AI 资讯

TawTerminal — a macOS terminal built for the AI coding era.

Video demo link : https://youtu.be/vSjeTkrou1s?si=qTcrWyz0HSWDiWSF If you run Claude Code, Codex, or other AI agents, you know the pain: the terminal floods with generated output while you're still typing — and your keystrokes lag, characters "drag." TawTerminal fixes that. Your keystrokes go straight to the screen on a separate path from shell output, so typing stays instant even while an AI agent streams thousands of lines. What you get: ⚡ Zero input lag — GPU-accelerated (WebGL) rendering at 60fps, multi-process so heavy output never blocks your typing 📁 Workspace folders — pin folders in the sidebar, spawn a shell rooted in any directory in one click, with live git branch + status 🤖 One-click AI agents — launch Claude Code, Codex, PI, or tawx directly from the sidebar, sessions auto-restored 🪟 Split panes & tabs — Cmd+D to split, Cmd+T for tabs 🖼️ Paste images — drag-drop or Cmd+V images straight into the terminal 🎨 4 beautiful themes — Tokyo Night, Catppuccin Mocha, Dracula, Rosé Pine 📊 Live AI usage footer — see today's Claude Code / Codex token + cost estimate 🍎 Native macOS feel — clean hidden title bar, clickable URLs, custom fonts Requirements: macOS, Apple Silicon (M1 or newer). Signed & notarized by Apple — installs clean, no security warnings.

2026-06-28 原文 →
AI 资讯

I switched 23 sites from JPEG to WebP/AVIF last month — here's what I learned

I spent last month migrating 23 client sites from JPEG/PNG to WebP and AVIF. Here's what I wish someone told me before I started. AVIF vs WebP: the real numbers AVIF is about 30% smaller than WebP at the same quality level. But Safari support is still patchy — if your traffic is 40%+ iOS, you need <picture> tags with WebP fallback. No way around it. The biggest win wasn't the format The single biggest reduction came from capping max image width at 1200px and setting quality to 80. One site went from 9.4MB to 318KB per page — a 97% reduction — just from those two settings plus lazy loading. The format switch was the cherry on top, not the cake. Tools I used daily SmartImgKit — quick batch conversions in the browser. No uploads, no signup, drag and drop. Handles the 80% case where you don't need a CLI pipeline. Supports JPG, PNG, WebP, AVIF, GIF, BMP, TIFF. ImageMagick — server-side batch jobs for when you need automation. Squoosh — one-off fine-tuning with visual comparison. Sharp (Node.js) — build pipeline integration. The HEIC surprise Every iPhone user's photos are HEIC. Most web tools crash on them. You need a converter that handles them before the pipeline — SmartImgKit's HEIC converter works locally in-browser, no uploads. The 80/20 rule Format + max width + lazy loading = 80% of the gain. Everything else is diminishing returns. Don't over-engineer it.

2026-06-28 原文 →
AI 资讯

DeepSeek's DSpark Brings Speculative Decoding Back Into the Spotlight — Here's What Developers Need to Know

Introduction Speculative decoding is one of those techniques that has been "almost ready for production" for the better part of three years. A small draft model proposes tokens; a larger target model verifies them in a single forward pass. In theory, you get 2–4× throughput. In practice, the draft model has to be cheap, fast, and good enough at mimicking the target's distribution, which is a much harder combination than it sounds. Yesterday, a new paper from DeepSeek quietly climbed to the top of Hacker News (714+ points, 290+ comments at the time of writing). It's called DSpark , and it reframes speculative decoding in a way that looks like it could finally make the technique drop-in rather than bolt-on. The paper is here: github.com/deepseek-ai/DeepSpec/blob/main/DSpark_paper.pdf The Core Idea Instead of training a separate, smaller draft model from scratch (the classic approach), DSpark grafts the speculative head directly onto the target model. The intuition is simple: if the target model already knows which tokens are likely to follow, why not reuse its own intermediate representations rather than maintaining a parallel network? From the discussion on HN, this approach has a concrete architectural benefit — it reduces layer duplication that you'd otherwise have to maintain with a standalone draft model. In the DeepSeek experiments, the technique was applied on top of Step and Qwen 3.6 , which are themselves MTP-capable. How It Fits With MTP One of the more interesting practical points raised by HN commenters: DSpark is complementary to Multi-Token Prediction (MTP) , not a replacement for it. MTP — where the model predicts several future tokens at every step using auxiliary heads — has already been shown to give 50–100% speedups on hardware like the NVIDIA DGX Spark. DSpark adds another layer on top: even with MTP, the validation step is still a single forward pass through the main model, and the speculative tokens that get accepted come "for free." A useful men

2026-06-28 原文 →
AI 资讯

How to optimize IO in C++

Preface Link to the repository containing all examples Back when I was at my first class of Data Structures and Algorithms, I started to solve competitive programming questions in judges like CodeForces, I didn't know why my code was slower if my solution was efficient (at least in theory), my professor explain to the class the reason why our programs were slow, because of I/O is an expensive task for computers. To start working with the examples in this article just clone the repository and play with it as long the article explains how to run the code. git clone https://github.com/MiztonCodes/OptimizeIO.git Why std::cout and std::cin are slow? In C++ by default, both std::cin and std::cout streams are synchronized with standard C scanf and printf streams and at the same time every single call to std::cin flushes the std::cout buffer, because std::cin before reading input, wants to output any pending prompt to the user, which can cause performance issues because reading and writing are expensive tasks due to the need to make calls to the operating system, the solution is to disable all of this synchronizations and manually flushing the output buffer whenever it is needed. Note: For convenience in all examples I'll use #include<bits/stdc++.h> header to simplify the imports, this header includes everything we'll need and this header only works on GCC compiler. What is input and output? When you run your program, it is like an isolated box inside your computer, ready to do some work, the input process involves moving raw data from an external source like a keyboard, a file or even the network to your program (reading) , the output process involves moving data from your program to an external destination like a monitor, the console, a file, the network or even an external device (writing) , for both processes your program does not read or write directly to the input and output sources, because each source has its own way to transfer data, C++ provides a uniform interfac

2026-06-27 原文 →
AI 资讯

Record of Site Issues #2 - Playback / GOP

Environment And Situation Control room of an apartment Number of installed product : 3 (PC-based NVR, dual-LAN supported) Remote support : X (I actually went to the site and diagnosed) Reported Issue In viewer, when user changes play speed while playing back the recorded data, it randomly plays the data in hyper speed(almost 30x~60x) For example: 4x play means 4 seconds in video per a second. But in the site, it played 30~60 seconds per a seconds, showing the video stutturing. Diagnosis Checked the overall environment. System(CPU / RAM usage), network environment(bandwidth), resoulution, stream configurations, etc. -> Nothing suspicious. Some of the installed cameras had unusual fps and gop values Normally, fps and gop values are set to be equal(for exmaple, if fps is 30 then gop is also 30 so that iframe can appear every second) But the cameras' set up values were fps 15, gop 60(iframe per 4 seconds) Assumption Somehow the viewer keeps failing to find iframe to play. And it's maybe because iframe appears with a long gap. Quick note: iframe is kind of a key-frame. Since the viewer starts decoding from an iframe, it's necessary when it comes to playback. What I Tried Set all the cameras' gop value to 15(same as fps) Result Ran a test with data before changing the gop values and after. During interval before changing the gop, the issue occurred almost every time I tried. But after chaning the gop, the issue no longer occurred. Concolusion The issue was triggered by large GOP value (GOP 60 with FPS 15). With only one iframe every four seconds, the viewer sometimes failed to find an appropriate iframe after changing the playback speed, causing abnormal playback behavior. According to the viewer developer, this is likely related to the viewer's iframe searching logic, which is still under investigation. Keep This In Mind Check camera settings(especially gop and fps) first when it comes to playback issue. Always check before/after data to confirm assumption.

2026-06-26 原文 →
AI 资讯

How to Stream & Flatten 1GB+ JSON to CSV in the Browser Without Memory Leaks

As developers, data engineers, or analysts, we’ve all been there: you download a massive database export, a logging stack dump, or a transaction archive, only to find it's a multi-gigabyte JSON file. You try to import it into a spreadsheet or run it through a standard online converter, and boom—your browser tab freezes, crashes, or shows the dreaded "Out of Memory" screen. Even worse, if you try to use standard cloud-based online tools, you might have to wait for a 500MB upload to complete, only to hit a rigid file-size cap or, worse, compromise sensitive data privacy by uploading corporate logs or database records to a third-party server. In this guide, we will explore: Why large JSON files crash standard parsers (the V8 heap limit problem). How streaming architectures solve this by reading data chunk-by-chunk. NDJSON (JSON Lines) vs. JSON Arrays and how to stream them. A browser-native, 100% offline tool to convert large JSON to CSV instantly: Parsify's Large JSON Stream Converter . How to implement your own basic browser-based JSON streaming parser in JavaScript. 1. The Anatomy of a Memory Crash (Why JSON.parse Fails) If you are using JavaScript or Node.js, the simplest way to read and parse a JSON file is to load the file into memory and run JSON.parse(). const fs = require ( ' fs ' ); // Naive approach: Will crash on a 1GB+ file fs . readFile ( ' database-dump.json ' , ' utf8 ' , ( err , data ) => { if ( err ) throw err ; // POINT OF FAILURE: V8 Heap Out of Memory const records = JSON . parse ( data ); records . forEach ( record => { // Process record... }); }); This works fine for small config files. But once your JSON file reaches 100MB, 500MB, or 1GB+, this approach is guaranteed to trigger a fatal crash: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory Why does this happen? The String Duplication Overhead: When you load a 1GB file into memory, you first allocate ~1GB of RAM for the raw text string. The

2026-06-26 原文 →
AI 资讯

Optimizing Geofence Transitions: Battery Efficient Background Logic in Android

We have all been there: a meeting starts, and suddenly your phone rings. I built Muffle to automate silent profiles, but the biggest hurdle wasn't the UI—it was making sure the app didn't destroy the user's battery while monitoring GPS coordinates. The Trap of Continuous Location Updates Early prototypes used LocationManager with frequent updates. This is the fastest way to get your app uninstalled. Keeping the GPS radio active in the background forces the device to wake the CPU constantly, leading to significant battery drain. To solve this, I moved away from active polling and shifted to the GeofencingClient API. Leveraging GeofencingClient for Passive Monitoring Instead of calculating distance from a point every few seconds, I transitioned to system-level geofencing. By defining circular regions around locations like the office or a mosque, the OS handles the monitoring at the hardware abstraction layer. kotlin val geofencingRequest = GeofencingRequest.Builder() .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofences(geofenceList) .build() This approach allows the OS to do the heavy lifting. The app stays in a dormant state until the location provider signals a transition. The kernel only wakes the app when the device enters or exits the radius. The Trade-off: Precision vs. Power Using GeofencingClient means accepting a slightly slower trigger time compared to raw GPS polling. Sometimes, there is a delay of a few seconds as the device wakes from a deep sleep state. For a utility like Muffle, this is a fair trade-off. Users prefer their phone to silence five seconds after entering a building rather than finding their battery dead by noon. To mitigate the delay, I combined geofencing with a secondary intent service that performs a final check once the geofence trigger hits, ensuring that we aren't just reacting to a momentary GPS jitter. Final Thoughts By offloading the monitoring to the platform's native geofencing API, I was able to keep Muffle

2026-06-25 原文 →
AI 资讯

Apache Spark Query Optimization on Databricks: Catalyst, AQE, and Photon Engine

A deep dive into how Spark transforms your SQL into a physical execution plan — and how Databricks layers Adaptive Query Execution and the Photon vectorized engine on top to squeeze out maximum performance. Table of Contents Why Query Optimization Matters The Catalyst Optimizer Pipeline Stage 1: Parsing — From SQL to Unresolved Logical Plan Stage 2: Analysis — Binding to the Catalog Stage 3: Logical Optimization — Rule-Based Rewrites Stage 4: Physical Planning — Strategies and Cost Models Adaptive Query Execution (AQE) The Photon Engine Reading Explain Plans Tuning Reference Table References Why Query Optimization Matters A Spark query written by a human and a Spark query executed by the engine are often very different things. The gap between them — the optimization — is what separates a job that runs in 3 minutes from one that runs in 3 hours on identical hardware. Databricks compounds Spark's native Catalyst optimizer with two additional layers: Adaptive Query Execution (AQE) — re-optimizes the query at runtime using actual statistics collected mid-job Photon — a C++ vectorized execution engine that replaces the JVM-based Spark executor for eligible operators Understanding all three lets you write queries that cooperate with the engine rather than fight it. The Catalyst Optimizer Pipeline Catalyst is Spark's rule-based and cost-based query optimizer. Every query — whether written in SQL, DataFrame API, or Dataset API — passes through the same four-stage pipeline before a single byte of data is read. Stage 1: Parsing — From SQL to Unresolved Logical Plan # ── Catalyst Stage 1: Parsing ───────────────────────────────────────────────── # Spark uses ANTLR4 to parse SQL into an Abstract Syntax Tree (AST). # At this point column names are NOT validated — the plan is "unresolved". from pyspark.sql import SparkSession spark = SparkSession . builder . appName ( " catalyst-demo " ). getOrCreate () # Both of these produce identical internal representations df_api = ( spark .

2026-06-24 原文 →
AI 资讯

A Day of Performance Hardening: Hunting N+1s and Killing Wasted Queries in Laravel

Performance work has a reputation for being glamorous — the heroic "we cut latency by 80%" story. Most days it's not that. Most days it's a janitorial pass: you go looking for the queries you're firing without realizing it, and you quietly delete them. That was today. One sustained sweep across an app and the package that backs it, chasing the same theme everywhere: stop asking the database for things you don't use. Let me walk through the patterns, because they generalize to any Laravel app of a certain age. First, make the invisible visible You can't fix N+1s you can't see. The first move was wiring up an N+1 detector in the local/dev environment only — beyondcode/laravel-query-detector . It hooks into the request lifecycle, watches your Eloquent relationship loads, and screams (in the console, or as an exception if you want it strict) when it spots the classic loop-and-lazy-load pattern. The "dev-only" part matters. You never want a query detector running in production — it adds overhead and it's a developer aid, not a runtime guard. So it goes in behind an environment check, registered only when the app isn't in production: public function register (): void { if ( $this -> app -> environment ( 'local' , 'testing' )) { $this -> app -> register ( \BeyondCode\QueryDetector\QueryDetectorServiceProvider :: class ); } } Think of it like a smoke detector you only arm while you're cooking. It's noisy by design — that's the point. The noise is a to-do list. Eager loads you don't actually use are just N+1s wearing a disguise Here's the counterintuitive one. We're all trained to fix N+1s by adding with() . But the opposite bug is just as common and almost never gets caught: you eager-load a relationship, and then... never touch it in the view. Index screens are the worst offenders. Someone builds a listing, eager-loads creator and approver so the table can show names, then a redesign drops those columns — but the with(['creator', 'approver']) stays. Now every page load hyd

2026-06-23 原文 →
AI 资讯

Data-Oriented Design in C#: Why Objects Are Slowing You Down

Data-Oriented Design in C#: Why Objects Are Slowing You Down In my previous article, we talked about starving the Garbage Collector by moving away from heap-allocated class types and leaning heavily into struct , Span<T> , and ArrayPool<T> . That’s a critical first step, but it only solves half the problem. You’ve stopped the GC from pausing your app, but you might still be leaving massive amounts of CPU performance on the table. Why? Because of how your data is structured. It’s time to talk about Data-Oriented Design (DoD) . The Object-Oriented Trap We are taught from day one to model our code after the real world. If you are building a social network graph, you might write something like this: public class UserNode { public int Id { get ; set ; } public string Name { get ; set ; } public List < Edge > Connections { get ; set ; } } public class Edge { public UserNode Target { get ; set ; } public int Weight { get ; set ; } } This makes perfect logical sense. A user has connections, and those connections point to other users. But modern CPUs don't care about your logical models. A CPU only cares about reading data from memory into its L1/L2 caches as fast as possible. When a CPU reads a byte from RAM, it doesn't just read that one byte; it pulls a whole 64-byte "cache line" under the assumption that you will probably want the neighboring bytes next. When you loop through a List<UserNode> , traversing from object to object, you are jumping randomly across the heap. The CPU pulls a cache line, reads your data, and then has to go fetch a completely different block of RAM for the next node. This is called pointer chasing , and the resulting cache misses are devastating to performance. Enter Data-Oriented Design: Struct of Arrays (SoA) Data-Oriented Design says: Stop modeling the real world. Model the data the way the hardware wants to consume it. Instead of an Array of Structs (AoS) (or an array of objects), we invert the architecture to a Struct of Arrays (SoA) . If we

2026-06-23 原文 →
AI 资讯

Why Payment Data Pipelines Break Under Real-Time Load (And How Banks Fix the Latency Problem)

Payment data pipelines fail in ways that ruin a payments engineer’s week, and the failures rhyme. The dashboards froze. Fraud scores arrived after the transaction had already cleared. Settlement reports came in stale. Nobody slept. The frustrating part is that the same data architecture had run fine for years. So, what changed? The honest answer is that batch thinking does not survive contact with real-time payments. A lot of banks built their data foundations in an era when nightly jobs were good enough. Load the warehouse overnight, run the reports in the morning, move on. That rhythm worked when money moved slowly. It does not work when a customer expects an instant confirmation and a fraud engine has milliseconds to make a call. Here is where things crack. Real-time payment rails push a constant stream of events instead of a tidy nightly dump. Your pipeline now has to ingest, transform, and serve data while transactions are still happening. Add ISO 20022 into the mix and the pressure climbs. ISO 20022 messages are rich. They carry far more structured detail than the old formats, which is wonderful for analytics and miserable for a pipeline that was never designed to parse that much context at speed. This is not a fringe concern either. Swift reported that by the time its MT/ISO 20022 coexistence period closed in November 2025, around 80% of daily traffic was already running on the ISO 20022 format, with more than 3.1 million of these messages exchanged every day. The rich-data era is the default now, not the roadmap. Then there is the fraud-scoring window. Fraud models need fresh features. Account behaviour over the last few minutes, velocity checks, device signals. If your pipeline takes thirty seconds to surface that data, the fraud decision is already too late. You are essentially detecting fraud after the loss. That gap between when data is created and when it becomes usable is the silent killer in most payment systems. And the cost of getting it wrong runs

2026-06-23 原文 →
开发者

Ever had a renamed column quietly break a CSV export? csv-pipe makes it a compile error, reads and writes both ways, and parses several times faster than papaparse. Live playground in the post to try your own data.

csv-pipe: read and write CSV in TypeScript, several times faster than papaparse Myroslav Martsin Myroslav Martsin Myroslav Martsin Follow Jun 22 csv-pipe: read and write CSV in TypeScript, several times faster than papaparse # javascript # typescript # webdev # node 1 reaction Add Comment 2 min read

2026-06-23 原文 →
AI 资讯

Query ধীর গতিতে চলছে, কিভাবে খুঁজে বের করবেন সমস্যাটা? (পর্ব ৩)

আমার colleague এখন প্ল্যান দেখতে পারছে। Scan types বুঝতে পারছে। Join types বুঝতে পারছে। Estimate আর actual এর gap দেখতে পারছে। BUFFERS ও দেখছে। কিন্তু সে প্রশ্ন করল। এসব দেখে কি করব? Step by step কোন পথে যাব? আমি বললাম। পাঁচটা step আছে। অর্ডার অনুযায়ী। পর্ব ২ এ আমি বলেছিলাম scan types, join types, estimate আর actual এর gap। BUFFERS কি। এবার আসি সমাধান এ। Diagnostic Workflow আপনার কাছে একটা slow query এসেছে। কিভাবে debug করবেন? এই পাঁচটা প্রশ্ন করুন অর্ডার অনুযায়ী। ৯০% slow query প্রথম বা দ্বিতীয় ধাপেই solve হয়ে যায়। ১. Deepest Seq Scan দেখুন Table বড় কি না? Filter selective কি না? Missing index থাকলে add করুন। আজই শুরু করুন যখন একটা Seq Scan দেখবেন big table এ, প্রথমে WHERE clause টা check করুন। Selective কি না? ৫% এর কম row return হওয়ার কথা? যদি তাই হয়, index missing। CREATE INDEX idx_name ON table(column) run করুন। ২. Join types দেখুন কোনো Nested Loop আছে কিন্তু দুই পাশেই বড় table? Hash Join force করুন বা ডান পাশে index add করুন। আজই শুরু করুন Nested Loop দেখলে ডান পাশের table এ index check করুন। যদি না থাকে, create করুন। Index থাকা সত্ত্বেও planner Nested Loop use করছে? SET enable_nestloop = off temporarily disable করে দেখুন। Hash Join আসবে কি না। ৩. Row estimates দেখুন Estimate vs actual ১০x এর বেশি difference? ANALYZE table দিন বা predicate rewrite করুন। আজই শুরু করুন rows=1 estimate কিন্তু rows=100000 actual দেখলে ANALYZE tablename run করুন। Statistics refresh হবে। তারপর plan আবার দেখুন। যদি তাও না আসে, WHERE clause rewrite করুন। Function call থাকলে remove করুন। Type mismatch থাকলে fix করুন। ৪. BUFFERS add করুন কোনো node এ অনেক disk reads? Caching investigate করুন। আজই শুরু করুন EXPLAIN (ANALYZE, BUFFERS) run করে দেখুন shared read high কোথায়। সেই node টাই bottleneck। Index add করলে reads কমবে। Pre-warm cache করতে পারেন। Data pre-load করতে পারেন। ৫. Sorts আর hashes দেখুন কোনো spill-to-disk আছে? work_mem raise করুন বা sort eliminate করুন। আজই শুরু করুন Plan এ external merge Disk: 421MB দেখলে spill-to-disk হয়েছে। SET work_mem = '256MB' temporarily rais

2026-06-22 原文 →
AI 资讯

PostgreSQL Indexing Deep Dive - Choosing the Right Index

In the earlier posts of this series, we looked at practical query tuning tips and how to read and interpret query plans . A recurring theme in both was: "add an index here." But "add an index" is a bit like saying "use the right tool" — the interesting part is which one. PostgreSQL ships with several index types, each tuned for a different kind of data and query. Picking the wrong one means PostgreSQL quietly ignores your index and goes back to a sequential scan. In this post, we'll walk through the main index types, when each shines, and the special index variations (composite, partial, covering, expression) that often matter more than the type itself. Setting the Scene: Schema and Sample Data We'll reuse the same schema from the previous posts, with one small addition — a metadata JSONB column and a tags array on orders , so we can explore the more exotic index types. CREATE TABLE customers ( id SERIAL PRIMARY KEY , customer_name VARCHAR ( 255 ), email VARCHAR ( 255 ), created_at TIMESTAMPTZ DEFAULT NOW () ); CREATE TABLE orders ( id SERIAL PRIMARY KEY , customer_id INT REFERENCES customers ( id ), order_date TIMESTAMPTZ DEFAULT NOW (), total_amount NUMERIC ( 10 , 2 ), status VARCHAR ( 20 ), tags TEXT [], metadata JSONB ); -- Insert sample customers INSERT INTO customers ( customer_name , email ) SELECT 'Customer ' || i , 'customer' || i || '@example.com' FROM generate_series ( 1 , 1000000 ) AS s ( i ); -- Insert sample orders INSERT INTO orders ( customer_id , order_date , total_amount , status , tags , metadata ) SELECT ( RANDOM () * 1000000 ):: INT , NOW () - interval '1 day' * ( RANDOM () * 365 ):: int , ( RANDOM () * 500 + 20 ), ( ARRAY [ 'pending' , 'shipped' , 'delivered' , 'cancelled' ])[ FLOOR ( RANDOM () * 4 + 1 )], ARRAY [( ARRAY [ 'gift' , 'priority' , 'fragile' , 'bulk' ])[ FLOOR ( RANDOM () * 4 + 1 )]], jsonb_build_object ( 'channel' , ( ARRAY [ 'web' , 'mobile' , 'store' ])[ FLOOR ( RANDOM () * 3 + 1 )]) FROM generate_series ( 1 , 1000000 ) AS s ( i

2026-06-21 原文 →
AI 资讯

Show OS: Universal Uploader – Zero-dependency, stream-based file uploading with transparent XHR fallback

Hey everyone, I wanted to share an open-source library I’ve been developing to solve a persistent issue in frontend file ingestion: handling large-file uploads efficiently without blocking the main thread, consuming excessive client-side memory, or introducing heavy npm dependencies. The core architecture leverages Fetch Duplex streams combined with Web Streams API to achieve constant memory usage during large file transfers. For browsers lacking full duplex stream support (such as Safari), it seamlessly switches to an automated chunked XHR fallback at runtime. ⚙️ Core Architecture & Features Constant Memory Footprint: Streams large chunks sequentially using Fetch duplex streaming where supported. Intelligent Runtime Fallback: Detects capabilities instantly and falls back to a robust, chunked XMLHttpRequest pipeline to ensure cross-browser compatibility (including Safari). Resilient Lifecycle Management: Built-in hooks for pause, resume, manual abort, and automated chunk-level retries with a configurable exponential backoff algorithm. Zero Dependencies & Tree-shakeable: Written entirely in vanilla TypeScript with no external runtime dependencies (npm install u/universal-uploader/core). The architecture is highly modular, ensuring that unused upload strategies are completely tree-shaken during compilation. React Primitive Included: Ships with a declarative React hook that maps the entire upload lifecycle to state primitives without causing redundant re-renders. 🛠️ Why Existing Solutions Didn't Fit Most mainstream uploading libraries either rely on heavy multi-part form encodings that require buffering files entirely into browser memory, or pull in heavy polyfill architectures that bloating the initial bundle size. I designed this to isolate the transport layer logic via a composition-based approach, separating the stream controller from the network client. To ensure deterministic behavior, the codebase is fully covered by 127 integration/unit tests validating network

2026-06-21 原文 →
开发者

I Benchmarked 17 Image Conversions on My Production Server. Some Results Were Not What I Expected.

I run Convertify , a free image converter built on Rust and libvips. Last week I decided to stop guessing about format performance and actually measure it. I took 50 real images (26 PNGs, 24 iPhone HEIC photos), ran 17 conversions through the production pipeline, and recorded every file size and encode time. Some results confirmed what everyone says. Others did not. The three results that surprised me 1. Converting HEIC to JPG makes files 14% bigger , not smaller. This one hurt. "Convert iPhone photos to JPG" is probably the most common advice on the internet. But HEIC wraps the HEVC codec, which compresses roughly 2x better than JPEG. Going from a better codec to a worse one means the file grows. Every time. If you actually want smaller iPhone photos: HEIC to WebP saves 43%, HEIC to AVIF saves 57%. 2. AVIF encodes 7x slower than WebP for 10% more compression. AVIF Q63: 55 KB, 1.30s per image. WebP Q80: 61 KB, 0.19s per image. That is a 10% size difference for a 7x speed penalty. For a single hero image, nobody cares. For a batch pipeline processing thousands of product photos, that is the difference between 3 minutes and 21 minutes. 3. PNG at 600 DPI is smaller than PNG at 300 DPI when rasterizing PDFs. This was the weirdest one. I was benchmarking PDF-to-image and noticed PNG output shrank from 2,221 KB at 300 DPI to 1,660 KB at 600 DPI. I spent an hour convinced I had a bug. Turns out it is a real property of PNG encoding. Higher DPI renders smoother gradients between adjacent pixels, and PNG's prediction filters (Paeth, sub, up) compress smooth gradients dramatically better than the sharp edges you get at lower resolutions. Not a bug. Just PNG being PNG. The quick reference table Conversion Size change Speed JPG to WebP Q80 -64% 0.19s JPG to AVIF Q63 -68% 1.30s PNG to WebP Q80 -92% 0.21s PNG to JPG Q85 -86% 0.07s HEIC to JPG Q85 +14% 1.90s HEIC to WebP Q80 -43% 5.64s HEIC to AVIF Q63 -57% 14.52s WebP to JPG Q85 +60% 0.09s AVIF to JPG Q85 +80% 0.15s What I actual

2026-06-20 原文 →
AI 资讯

My API Responded in 4 ms, but Navigation Still Felt Slow

I was debugging an internal project management application built with SvelteKit and a Rust API. Locally, navigation felt almost instant. On the VPS, opening the Tickets, Timeline, and OpenSpec docs pages felt noticeably slower. Clicking a ticket also took too long before the preview panel became useful. My first assumption was infrastructure: Maybe the VPS was underpowered. Maybe PostgreSQL queries were slow. Maybe the reverse proxy added latency. Maybe SvelteKit SSR was taking too long. The measurements pointed somewhere else. The Baseline I started with the feature list endpoint used by both Tickets and Timeline. For a project with 52 tickets: Metric Result API response time ~4 ms Response size 353,956 bytes Number of tickets 52 The API was not slow. But it was returning around 354 KB for a list of only 52 items. The SvelteKit route payload showed the same pattern: Route Data payload Tickets 349,857 bytes Timeline 354,731 bytes This explained why local testing was misleading. On localhost, transferring and parsing a few hundred kilobytes is easy to miss. Once the app runs behind a VPS, reverse proxy, TLS, and a real network connection, the payload becomes much more visible. What Was Inside the Payload? I broke down the feature response by field. The descriptions alone accounted for: 296,177 bytes That was more than 80% of the complete response. The list endpoint was returning something similar to this for every ticket: interface FeatureListItem { id : string ; title : string ; status : string ; priority : string ; storyPoints : number | null ; dueDate : string | null ; description : string | null ; checkoutCommand : string | null ; openSpecCommand : string | null ; } The problem was not that these fields were useless. They were useful on the ticket detail panel. They were not useful when rendering the initial list. Timeline was even more wasteful. It used ticket status, dates, dependencies, and assignees, but still downloaded every full Markdown description. The D

2026-06-20 原文 →
AI 资讯

Pro File Uploads in Rails 8: Speed and Scalability with Direct Uploads

Imagine a user trying to upload a 100MB video or a high-resolution photo to your app. If you use the standard Rails file upload, that file travels from the user's browser to your Rails server, and then your server sends it to S3 or Google Cloud. This is a terrible way to do it. While that 100MB file is transferring, your Rails worker (Puma) is frozen. It can't handle other users. If three people upload large files at once, your whole app will stop responding. In 2026, the professional way to handle this is Direct Uploads . With Direct Uploads, the file goes directly from the user's browser to your cloud storage (S3, R2, etc.). Your Rails server only handles a tiny bit of metadata. It is faster for the user and much safer for your server. Here is how to set it up in Rails 8. STEP 1: Configure Your Storage First, make sure you aren't using the local disk for production. You need a cloud provider like AWS S3 or Cloudflare R2. In your config/storage.yml : amazon : service : S3 access_key_id : <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key : <%= ENV['AWS_SECRET_ACCESS_KEY'] %> region : us-east-1 bucket : my-app-uploads # Crucial for Direct Uploads! public : true Note: You must configure CORS in your S3/R2 dashboard to allow requests from your domain. If you don't do this, the browser will block the upload. STEP 2: The Rails Form Rails makes the backend part incredibly easy. You just add one attribute to your file field: direct_upload: true . <!-- app/views/users/_form.html.erb --> <%= form_with ( model: user ) do | f | %> <div class= "field" > <%= f . label :avatar %> <%= f . file_field :avatar , direct_upload: true %> </div> <%= f . submit "Save Profile" %> <% end %> When you add direct_upload: true , Rails automatically includes a JavaScript library that handles the "handshake" with S3. STEP 3: Adding a Progress Bar (The UX Win) Direct uploads can take a few seconds. If nothing happens on the screen, the user will think your app is broken. We can use the built-in Ac

2026-06-20 原文 →