mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
109 lines
3.8 KiB
TypeScript
109 lines
3.8 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* NO TAILWIND. `Band` and `Head` from `components/marketing/band` carry the
|
|
* section frame and the centred head; the cards are gui props over
|
|
* @hanzo/design's tokens.
|
|
*/
|
|
|
|
import React from "react";
|
|
import { motion } from "@/components/motion";
|
|
import { YStack } from '@hanzo/ui'
|
|
import { Grid as Columns } from '@hanzo/ui/grid'
|
|
import { Band, Head, Words } from '@/components/marketing/band'
|
|
|
|
/** The ground this section fades to — `neutral-900` at half strength. */
|
|
const FADE = 'linear-gradient(to bottom, var(--background), color-mix(in oklab, var(--neutral-900) 50%, transparent))'
|
|
|
|
|
|
interface EfficiencyCardProps {
|
|
title: string;
|
|
mainText: string;
|
|
subText: string;
|
|
initialY: number;
|
|
delay: number;
|
|
}
|
|
|
|
const EfficiencyCard = ({ title, mainText, subText, initialY, delay }: EfficiencyCardProps) => {
|
|
return (
|
|
<YStack
|
|
render={<motion.div initial={{ opacity: 0, y: initialY }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.6, delay }} />}
|
|
items="center"
|
|
rounded="var(--radius-xl)"
|
|
borderWidth={1}
|
|
borderColor="var(--neutral-800)"
|
|
background="color-mix(in oklab, var(--neutral-900) 30%, transparent)"
|
|
p={32}
|
|
$platform-web={{ textAlign: 'center' }}
|
|
>
|
|
<Words render="h3" mb={16} fontSize="$7" lineHeight="1.3333" weight="700" color="var(--text-primary)">
|
|
{title}
|
|
</Words>
|
|
<Words render="p" mb={16} color="color-mix(in oklab, var(--foreground) 80%, transparent)">
|
|
{mainText}
|
|
</Words>
|
|
<Words render="p" color="var(--muted-foreground)">
|
|
{subText}
|
|
</Words>
|
|
</YStack>
|
|
);
|
|
};
|
|
|
|
const EfficiencySection = () => {
|
|
const efficiencyItems = [
|
|
{
|
|
title: "Read only what the query names",
|
|
mainText: "A row store reads the whole row to answer a question about two of its fields. A column store reads the two.",
|
|
subText: "Fewer bytes off the disk, fewer bytes to decompress, and more of the working set fits in memory.",
|
|
initialY: 30,
|
|
delay: 0
|
|
},
|
|
{
|
|
title: "One instruction, many values",
|
|
mainText: "Values from a single column sit next to each other in memory in the same representation, so a sum or a filter runs across a block of them with vector instructions instead of once per row.",
|
|
subText: "That layout is also what keeps the CPU cache full rather than chasing pointers.",
|
|
initialY: 30,
|
|
delay: 0.2
|
|
},
|
|
{
|
|
title: "Sorted, so a range is contiguous",
|
|
mainText: "Rows are written in the order of the table's sorting key and grouped into parts by partition, so a query bounded by time reads a run of adjacent blocks instead of seeking around the disk.",
|
|
subText: "Marks inside each part let the scan jump straight to the block that could hold the answer.",
|
|
initialY: 30,
|
|
delay: 0.3
|
|
},
|
|
{
|
|
title: "Compression chosen per column",
|
|
mainText: "A rising timestamp compresses as deltas. A repeated label compresses as a dictionary. A general-purpose compressor runs over whatever is left.",
|
|
subText: "Less data on disk is also less data on the wire once the query is spread across nodes.",
|
|
initialY: 30,
|
|
delay: 0.4
|
|
}
|
|
];
|
|
|
|
return (
|
|
<Band rule={false} pad="$14" measure={1152} ground={FADE}>
|
|
<Head
|
|
title="Where the speed comes from"
|
|
lede="Nothing exotic. Read less, decompress less, and touch memory in the order the CPU wants it."
|
|
measure={768}
|
|
/>
|
|
|
|
<Columns columns={{ min: 320, max: 2 }} gap={32}>
|
|
{efficiencyItems.map((item, index) => (
|
|
<EfficiencyCard
|
|
key={index}
|
|
title={item.title}
|
|
mainText={item.mainText}
|
|
subText={item.subText}
|
|
initialY={item.initialY}
|
|
delay={item.delay}
|
|
/>
|
|
))}
|
|
</Columns>
|
|
</Band>
|
|
);
|
|
};
|
|
|
|
export default EfficiencySection;
|