Достатъчни ли за всички 64-битовите променливи за банковите сметки
Оригиналът е на Rafael Batiati
Даниел Десподов преди 2 минути 4 СподелиНай-четени
IT НовиниЕмил Василев - 15:33 | 27.11.2023Русия има право да изкара от строя спътниците Starlink на Илън Мъск, само че ще го направи ли?
IT НовиниДаниел Десподов - 9:25 | 26.11.2023Измислиха талантлив метод за прескачане на рекламите в YouTube
НаукаСветлин Желев - 13:41 | 26.11.2023Станция регистрира две хиляди пъти покачване на радиационния декор наоколо до Козлодуй
Даниел Десподовhttps://www.kaldata.com/Новинар. Увличам се от модерни технологии, осведомителна сигурност, спорт, просвета и изкуствен интелект.„ 640 KB са задоволителни за всеки “, твърди Бил Гейтс, някъде към 1981 година
Решихме, че нашата система за ръководство на финансови бази данни TigerBeetle ще употребява 128-битови цифри за запазване на всички финансови суми и салда и че ще се откажем от 64-битовите цели цифри. Въпреки че някой може да твърди, че 64-битово цяло число, способно да съхранява цели цифри от нула до 264, е задоволително, с цел да се преброят всички песъчинки на Земята, ние осъзнахме, че би трябвало да надхвърлим тази граница, с цел да съхраняваме съответно всички транзакции. И в тази публикация ще ви кажем за какво.
Как съхраняваме стойностите на паричните суми?
За да съхраняват цифри (и да правят математически интервенции с тях), компютрите би трябвало да кодират тези цифри в двоичната бройна система, която изисква, според от обсега и типа на цифрата, избран брой битове (всеки обичай може да има стойност 0 или 1). Така да вземем за пример задачите цифри от -128 до 127 могат да бъдат записани единствено с осем бита, само че в случай че не ни трябват негативни цифри, можем да използваме същите битове, с цел да опишем всяко цяло число от 0 до 255, а това е байт! По-големите цифри изискват повече битове, да вземем за пример по-често се употребяват 16-, 32- и 64-битови цифри.
Може би сте забелязали, че приказваме за парите като за цели цифри, а не като за десетични дроби или центове. Нещата се усложняват при дробните цифри, те могат да бъдат показани благодарение на цифри с плаваща запетая. Двоичните цифри с плаваща запетая може и да са подобаващи за други калкулации, само че те не са в положение да показват тъкмо десетичните цифри. По същия метод, по който се сблъскваме с проблеми, пробвайки се да изразим ⅓ в десетична форма като 0,33333…, компютрите би трябвало да изразят ¹⁄₁₀ в двоична форма!
> > > 1.0 / 100
.10000000000000001
Тъй като постоянно се натрупват „ елементи от стотинката “, числата с плаваща запетая са същински призрачен сън за финансовия бранш!
Ето за какво в TigerBeetle не използваме дробни или десетични цифри, а всяка счетоводна книга се показва като кратно на най-малък целочислен множител, избран от потребителя. Например, в случай че представяме $ като кратно на центовете, тогава транзакция от $1,00 може да се опише като 100 цента. Дори валутните системи, които не са десетични, могат да бъдат по-добре показани като кратни на общ множител.
Колкото и да е необичайно, ние също по този начин не използваме негативни цифри (може би сте виждали софтуерни счетоводни книги, които съхраняват единствено положителни/отрицателни салда). Вместо това съхраняваме две обособени строго позитивни цели цифри: едно за дебита и едно за заема. По този метод освен се заобикаля бремето на работата с негативни цифри (като да вземем за пример многото характерните за езика последствия от препълването на едната или другата страна), само че най-важното е, че се резервира информацията, като се демонстрира размерът на транзакциите по отношение на непрекъснато възходящите салда на дебитната и кредитната страна. Когато би трябвало да се заключи чистото салдо, едното салдо може да се извади от другото, като чистото салдо се показа като едно позитивно или негативно число.
Тогава за какво ни трябват 128-битови цели цифри?
Нека се върнем към образеца с представянето на $1,00 като 100 цента. В този случай можете да преброите до към 184,5 квадрилиона $ в 64-битови цели цифри. Въпреки че за множеството хора това няма да е проблем, горната граница на 64-битовото цяло число се трансформира в ограничителен фактор, когато би трябвало да визиите стойности, по-малки от един цент. Добавянето на повече знаци след десетичната запетая доста понижава този период.
По същата причина цифровите валути се трансфораха в различен образец за потребление на 128-битови салда, защото при тях най-малката парична стойност може да бъде изразена в микроцентове (10-6)… или още по-малка сума. Въпреки че този образец към този момент е задоволително безапелационен, с цел да ги поддържаме в TigerBeetle, открихме доста други приложения, които биха имали изгода от потреблението на 128-битови салда.
Нека помислим още малко за обстановки, в които $0,01 е прекалено много, с цел да се опише дадена стойност.
Например в доста страни цената на литър/галон бензин изисква три знака след десетичната запетая, а фондовите пазари към този момент изискват увеличение на курсовете в стотни от цента (0,0001).
Икономиката на високочестотните микроплащания също изисква по-голяма точност и мащаб. По-нататъшното потребление на 64-битови стойности ще наложи изкуствени ограничавания на действителните потребности или ще принуди приложенията да обработват разнообразни мащаби на една и съща валута в другите счетоводни книги, като разделят сумите на голям брой сметки за „ долари “ и „ микродолари “ просто тъй като един 64-битов баланс е непълен, с цел да покрие цялостния диапазон от точност и мащаб, нужни за доста микроплащания при разказване на транзакция за няколко милиарда $.
Стойността в базата данни, която може да бъде преброена тъкмо (и в огромен мащаб), може да бъде освен това от пари. TigerBeetle е планиран да брои освен суми пари, само че и всичко, което може да бъде моделирано благодарение на двойното счетоводство. Например инвентаризация на артикули, периодичност на API повикванията или даже киловатчаса електрическа енергия. И нищо от това не би трябвало да се показва като пари или да се лимитира от същите граници.
Счетоводството на бъдещето
Друг значим аспект на горните граници на сумите и салдата е, че въпреки да е малко евентуално единична транзакция да надвиши стойност от порядъка на трилиони и квадрилиони, салдата по сметките се натрупват с течение на времето. В системите с дълъг живот е доста евентуално транзакциите на сходни суми да минават през една сметка в продължение на доста години, тъй че би трябвало да е допустимо цялото това салдо да се трансферира от една сметка в друга с една транзакция. С този комплициран въпрос се сблъскахме и когато имахме опция да избираме дали да преминем към 128-битови суми на транзакциите и/или единствено към 128-битови салда по сметките и партидите.
И най-после, даже и най-неочакваните събития като хиперинфлацията могат да тласнат валутите към горната граница на 64-битовите цели цифри, което ще изисква да забравим за центовете и да отрежем нулите, които нямат практическо значение.
Ще може ли вашата скица въз основата данни да издържи на това?
Интуитивно е мъчно да осъзнаем какъв брой огромно е едно 128-битово цяло число. То не е просто два пъти по-голямо от 64-битовото цяло число, а в действителност е 264пъти по-голямо! Пример: 64-битовото цяло число не е задоволително, с цел да се запази тази банкнота от 100 трилиона $, в случай че кодираме счетоводната книга в мащаба на микроцентовете. Ако обаче използваме 128-битово цяло число, можем да правим по 1 милион транзакции в секунда за същата сума пари в продължение на хиляда години и отново да не достигнем лимита на салдото по сметката.
1.000e20 // one hundred trillion at micro-cent scale x 1.000e6 // 1 million transfers per second x 3.154e7 // the number of seconds in a year x 1.000e3 // a thousand years ------------ = 3.154e36 // less than 2 128 ≈ 3.4e38С BigInteger идва огромна отговорност
Съвременните процесорни архитектури, като x86-64 и ARM64, могат да правят аритметични интервенции с 64-битови стойности, само че, в случай че вярно сме разбрали, те не всеки път разполагат със специфичен набор от указания за 128-битови калкулации. Когато се работи със 128-битови операнди, задачата може да бъде разграничена на 64-битови елементи, които процесорът е в положение да извърши. Ето за какво се запитахме дали 128-битовата аритметика ще бъде по-взискателна спрямо осъществяването на една директива, което не е проблем за 64-битовите цели цифри.
Таблицата по-долу демонстрира съпоставяне на машинния код на x86_64 архитектури, генериран за 64- и 128-битови операнди. Не се тормозете, не е належащо да сте специалист по асемблер, с цел да разберете смисъла! Просто обърнете внимание, че компилаторът може да усъвършенства множеството интервенции до поредност от тривиални процесорни указания, да вземем за пример събиране с транспорт и изваждане със заемане. Това значи, че режийните разноски, свързани с потреблението на 128-битови суми, не са грижа за TigerBeetle.
Операция
64-битови операнди
128-битови операнди
a + b
mov rax, rdiadd rax, rdxret
mov rax, rdiadd rax, rdxadc rsi, rcxmov rdx, rsiret
a - b
mov rax, rdisub rax, rsiret
mov rax, rdisub rax, rdxsbb rsi, rcxmov rdx, rsiret
a * b
mov rax, rdiimul rax, rsiret
mulx r8, rax, rdiimul rsi, rdximul rcx, rdiadd rcx, rsiadd r8, rcxmov rdx, r8ret
a / b
mov rax, rdixor edx, edxdiv rsiret
push raxcall __udivti3@PLTpop rcxret
a == b
cmp rdi, rsisete alret
xor rsi, rcxxor rdi, rdxor rdi, rsisete alret
1. За по-голяма елементарност в този асемблерен код не са включени инспекцията на аритметичните граници и инспекцията, които постоянно са позволени за TigerBeetle.
2. 128-битовото разделяне не може да бъде изразено като поредност от 64-битови указания и би трябвало да се осъществя програмно.
При осъществяването на смяната трябваше да се съобразяваме и с всички наши клиенти, защото TigerBeetle би трябвало да разкрие своя API за голям брой разнообразни езици за програмиране, не всички от които поддържат 128-битово цяло число. Основните езици би трябвало да употребяват integer с случайна акуратност (BigInteger), с цел да правят интервенциите със 128-битови цели цифри. Единственото изключение е.Net, който неотдавна добави поддръжка за видове данни Int128 и UInt128 в.Net 7.0 (много благодаря на екипа на DotNet!).
Използването на BigInteger изисква в допълнение разхищаване на запаси, защото те не се третират като 128-битови стойности с закрепена дължина, а се разпределят в куп като байтови масиви с променлива дължина. Освен това в средата за осъществяване аритметичните интервенции се емулират програмно, което значи, че те не могат да се възползват от множеството оптимизации, които биха били вероятни, в случай че компилаторът знаеше с какъв вид число работи. Да, Java, Go и даже C#, приказваме за вас.
За да понижим тези разноски от страна на клиента (и, несъмнено, с цел да запазим сходството с нашия TigerStyle), съхраняваме и представяме всички 128-битови стойности (като идентификатори, суми и т.н.) просто като двойка разпределени в стека 64-битови целочислени стойности (с изключение на JavaScript, тъй като той даже не поддържа 64-битови числа). Въпреки че езикът за програмиране няма визия за този занемарен вид и не може да прави аритметични интервенции с него, ние предоставяме набор от помощни функционалности за превръщане сред идиоматичните други възможности, които съществуват във всяка екосистема (напр. BigInteger, байт масив, UUID).
Нашият API не е нападателен, той дава опция на всяко приложение да избира сред потреблението на BigInteger или обработката на 128-битови стойности благодарение на която и да е цифрова библиотека на трета страна, която е най-подходяща. Искаме да предоставим високопроизводителни примитиви на ниско равнище без да лишаваме свободата на потребителя на по-високите равнища.




