Files
hanzo.ai/components/datastore/EfficiencySection.tsx

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;