Так и зачем оно надо? Если у тебя есть информация по движению каждой единицы товара, то это и не нужно.
Во-первых, документы движения как раз и возникают при разноске инвойса. Пока инвойс не разнесён нет ни документов межскладского движения с соответстующими костами, ни документов списания себестоимости со слоёв.
Во-вторых, единицы топлива, зерновых и даже метизов - понятие очень относительное.
Не путаю.
Почитайте хотя бы об уже упомянутых мной SAP FI и CO, прежде чем так упираться в своих заблуждениях. И не пытайтесь искать аналог CO в стандартных конфигурациях 1С. Там с этим до сих пор плохо. Такое вот тяжкое наследие 1С Бухгалтерии в 1С ERP. Прикрученный сбоку аудиторский след - плохая ему замена.
А по факту большая часть 1С - налоги.
Это при том, что сейчас активно впихивают 1С на замену западных ERP? )))
И тут весь вопрос, а зачем тебе промежуточные документы?
Я уже писал это неоднократно. Доходность конкретной реализации товаров зависит от себестоимости этих товаров. А эта себестоимость напрямую зависит от того, с какого слоя стоимости были взяты эти товары при разноске реализации и где они фактически находятся, с точки зрения логистических затрат. Эти сопоставления между строками инвойса и слоями стоимости, а так же дополнительные логистические затраты и являются промежуточными документами, возникающими в процессе разноски.
Аналитика = бухгалтерия в изначальном смысле
Не путайте бухгалтерию и финансовый учёт. Это всё равно, что в SAP сказать, что FI и CO - одно и то же. На практике, бухгалтер, за исключением разве что главбуха, вообще доступа к CO не имеет.
Для проекта мы выбрали простой в установке и использовании фреймворк PLPG Unit, разработанный как раз для решения подобных задач в PostgreSQL. Он не имеет дополнительных зависимостей и основан на языке plpgsql.
А почему не куда более развитый pgTAP? Для тестирования модификаций БД функциями он куда более удобен. И так же не имеет дополнительных зависимостей и написан на PL/pgSQL и PL/SQL.
Вы сами начинаете холивар. А ведь всё просто. "Золотого молотка" не существует. Когда стоит выбор, гонять гигабайты по сети или в памяти сервера, то вариант бизнес-логики на сервере вполне оправдан.
Главная проблема такой конструкции в том, что только средствами CH консистентность часто недостижима. Например, расчитать/пересчитать текущий баланс не получится без объединения оперативных данных из OLTP с архивными из CH.
А вот тут начинается самое интересное. Вплоть до кувырканий на грани извращения.
исходное утверждение: rustc не переставляет фп операции.
При чем тут rustc, если исходное утверждение было об оптимизациях LLVM?
неопределённое поведение означает, что программа нарушает контракт компилятора
С точки зрения IEEE, которое вполне можно считать общепринятым, UB и есть контракт компилятора, что фиксируется в стандарте. Не вижу смысла продолжать дискуссию с человеком, продвигающим семантику UB, радикально отличающуюся от общепринятой и стандартизированной ANSI и IEEE.
Термин Undefined Behaviour имеет вполне себе конкретное значение - что является или не является уб могут сказать только авторы компилятора, по определению.
Так конкретное значение или авторы компилятора могут интерпретировать этот термин по своему усмотрению?
Неопределенное значение выражения IEEE называет UB. Например, для C
int f(int i) {
// undefined behavior: two unsequenced modifications to i
return i++ + i++;
}
С какого перепугу неопределенное значение выражения для Rust должно называться иначе? Только потому, что авторы компилятора так захотели? )))
Насколько мне известно, в расте не используется fast-math
Во-первых, связь между флагами оптимизации LLVM и Rust весьма косвенная. Она ограничивается лишь передачей флагов LLVM через llvm-args. Я уже молчу о неявном изменении порядка вычислений при векторизации и использовании SIMD инструкций. Если на x86 в последнем случае еще всё более-менее предсказуемо, то на ARM, RISC-V и Xtensa можно получить просто массу различных неожиданностей.
Во-вторых, IEEE 754-2019 явно описывает обработку исчезновения порядка. И к Rust моя претензия именно в том, что он не предоставляет адекватного способа паниковать при исчезновении порядка. В CLang я могу явно указать -ffp-exception-behavior=strict. А что мне предлагает Rust?
От того, что у Вас разные результаты ещё не значит, что у Вас уб
Вы можете тут доказать, что различный результат исполнения одного и того же исходного кода с одними и теми же данными - это определенное поведение?
Если честно, я бы предпочёл, чтобы Rust, хотя бы при указании соответствующих флагов, паниковал при исчезновение порядка при операциях с числами с плавающей запятой (floating-point underflow). Но пока воз и ныне там, приходится лазить в дебагере, разбираясь с такими чудесами.
fn main() {
let a:f32 = 5E-30;
let b:f32 = 4E-30;
let c:f32 = 3E30;
let d:f32 = 2E30;
println!("a*b*c*d = {}, a*c*b*d = {}", a*b*c*d, a*c*b*d);
}
Если оптимизатор LLVM решает умножать сначала a на b, например, потому что они уже в регистрах, а свободных регистров в МК нет, то получит в итоге 0, но если будет умножать в указанном в коде порядке (a*c*b*d), то получится 119.99999. Как это ещё назвать, кроме как UB?
Понятно, что если отключить fast-math у LLVM, то проблема исчезнет. Но ценой снижения производительности кода. Выбирайте.
Я нарывался в Rust на UB при операциях с числами с плавающей запятой из-за оптимизации LLVM. Одно и то же выражение на ПК оказывалось не нулевым, а на МК - нулевым. Просто из-за перестановки местами множителей при оптимизации. При сохранении порядка умножений, как в исходном выражении, всё было хорошо. А при оптимизации при промежуточном умножении возникало исчезновение порядка и результат оказывался нулевым.
Чем "доделка" C может помочь при динамическом связывании кода, написанного на разных языках программирования?
переписывать вообще все ос и миллиарды строчек кода
При чём тут переписывание? До тех пор пока повсеместно используется C ABI и зависимое от него API, ошибки при работе с памятью неизбежны.
Простейший пример. Мы хотим прочитать 100 байт в буфер.
ssize_t read(int fd, void *buf, size_t count);
Что будет, если буфер мы ошибочно выделили не 100, а 50 байт?
В итоге имеем зоопарк различных решений этой проблемы в разных языках в виде стандартной библиотеки языка, так или иначе контролирующей, что буфер будет не меньше, чем count.
Потребность есть в создании безопасного с точки зрения работы с памятью API с соответствующим ABI на уровне ОС и динамического связывания в этой ОС, которыми можно пользоваться на любом языке программирования.
И для этого совершенно не нужно переписывать миллиарды строк кода.
Если уже заниматься перфекционизмом, то так. Внимание на последний запрос.
Скрытый текст
DROP TABLE IF EXISTS tmp_test;
CREATE TABLE tmp_test (
id serial PRIMARY KEY,
session_id int,
summary varchar,
escalation_reason varchar,
created_at timestamp
);
INSERT INTO tmp_test (session_id, summary,
escalation_reason, created_at)
SELECT G.n/1000 AS session_id, G.n::text AS summary,
'some reason' AS escalation_reason,
transaction_timestamp()+'1 ms'::interval*G.n
FROM generate_series(1,100000,1) G(n);
CREATE INDEX tmp_test_session_id_created_at_idx
ON tmp_test (session_id, created_at);
Сравниваем
EXPLAIN ANALYZE
SELECT summary, escalation_reason, created_at FROM (
SELECT summary, escalation_reason, created_at
FROM tmp_test
WHERE session_id = 500
ORDER BY created_at DESC LIMIT 1
) t
RIGHT JOIN (SELECT 1 AS d) s ON true;
Nested Loop Left Join (cost=0.42..2.65 rows=1 width=25) (actual time=0.019..0.020 rows=1.00 loops=1)
Buffers: shared hit=3
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.000..0.001 rows=1.00 loops=1)
-> Limit (cost=0.42..2.64 rows=1 width=25) (actual time=0.017..0.017 rows=0.00 loops=1)
Buffers: shared hit=3
-> Index Scan Backward using tmp_test_session_id_created_at_idx on tmp_test (cost=0.42..2.64 rows=1 width=25) (actual time=0.016..0.016 rows=0.00 loops=1)
Index Cond: (session_id = 500)
Index Searches: 1
Buffers: shared hit=3
Planning Time: 0.121 ms
Execution Time: 0.037 ms
EXPLAIN ANALYZE
(
SELECT summary, escalation_reason, created_at
FROM tmp_test
WHERE session_id = 500
ORDER BY created_at DESC LIMIT 1
)
UNION ALL
(
SELECT NULL::text, NULL::text, NULL::timestamptz
)
ORDER BY created_at NULLS LAST -- вот он, фикс
LIMIT 1;
Limit (cost=2.69..2.69 rows=1 width=72) (actual time=0.023..0.024 rows=1.00 loops=1)
Buffers: shared hit=3
-> Sort (cost=2.69..2.69 rows=2 width=72) (actual time=0.023..0.023 rows=1.00 loops=1)
Sort Key: (("*SELECT* 1".created_at)::timestamp with time zone)
Sort Method: quicksort Memory: 25kB
Buffers: shared hit=3
-> Append (cost=0.42..2.68 rows=2 width=72) (actual time=0.016..0.017 rows=1.00 loops=1)
Buffers: shared hit=3
-> Subquery Scan on "*SELECT* 1" (cost=0.42..2.65 rows=1 width=25) (actual time=0.015..0.015 rows=0.00 loops=1)
Buffers: shared hit=3
-> Limit (cost=0.42..2.64 rows=1 width=25) (actual time=0.014..0.015 rows=0.00 loops=1)
Buffers: shared hit=3
-> Index Scan Backward using tmp_test_session_id_created_at_idx on tmp_test (cost=0.42..2.64 rows=1 width=25) (actual time=0.014..0.014 rows=0.00 loops=1)
Index Cond: (session_id = 500)
Index Searches: 1
Buffers: shared hit=3
-> Subquery Scan on "*SELECT* 2" (cost=0.00..0.02 rows=1 width=72) (actual time=0.001..0.001 rows=1.00 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=72) (actual time=0.001..0.001 rows=1.00 loops=1)
Planning Time: 0.109 ms
Execution Time: 0.048 ms
EXPLAIN ANALYZE
SELECT MAX(T.summary) AS summary,
MAX(T.escalation_reason) AS escalation_reason,
MAX(T.created_at) AS created_at
FROM (
SELECT summary, escalation_reason, created_at
FROM tmp_test
WHERE session_id = 500
ORDER BY created_at
DESC LIMIT 1
) T;
Aggregate (cost=2.64..2.65 rows=1 width=72) (actual time=0.019..0.020 rows=1.00 loops=1)
Buffers: shared hit=3
-> Limit (cost=0.42..2.64 rows=1 width=25) (actual time=0.017..0.017 rows=0.00 loops=1)
Buffers: shared hit=3
-> Index Scan Backward using tmp_test_session_id_created_at_idx on tmp_test (cost=0.42..2.64 rows=1 width=25) (actual time=0.016..0.016 rows=0.00 loops=1)
Index Cond: (session_id = 500)
Index Searches: 1
Buffers: shared hit=3
Planning Time: 0.103 ms
Execution Time: 0.044 ms
разъём с кабелем в данном случае и является фидером, с которым необходимо согласование. По крайней мере лет 40 назад на кафедре схемотехники в МИЭТ нас учили именно так )
Во-первых, документы движения как раз и возникают при разноске инвойса. Пока инвойс не разнесён нет ни документов межскладского движения с соответстующими костами, ни документов списания себестоимости со слоёв.
Во-вторых, единицы топлива, зерновых и даже метизов - понятие очень относительное.
Почитайте хотя бы об уже упомянутых мной SAP FI и CO, прежде чем так упираться в своих заблуждениях. И не пытайтесь искать аналог CO в стандартных конфигурациях 1С. Там с этим до сих пор плохо. Такое вот тяжкое наследие 1С Бухгалтерии в 1С ERP. Прикрученный сбоку аудиторский след - плохая ему замена.
Это при том, что сейчас активно впихивают 1С на замену западных ERP? )))
Я уже писал это неоднократно. Доходность конкретной реализации товаров зависит от себестоимости этих товаров. А эта себестоимость напрямую зависит от того, с какого слоя стоимости были взяты эти товары при разноске реализации и где они фактически находятся, с точки зрения логистических затрат. Эти сопоставления между строками инвойса и слоями стоимости, а так же дополнительные логистические затраты и являются промежуточными документами, возникающими в процессе разноски.
Не путайте бухгалтерию и финансовый учёт. Это всё равно, что в SAP сказать, что FI и CO - одно и то же. На практике, бухгалтер, за исключением разве что главбуха, вообще доступа к CO не имеет.
А почему не куда более развитый pgTAP? Для тестирования модификаций БД функциями он куда более удобен. И так же не имеет дополнительных зависимостей и написан на PL/pgSQL и PL/SQL.
Вы сами начинаете холивар. А ведь всё просто. "Золотого молотка" не существует. Когда стоит выбор, гонять гигабайты по сети или в памяти сервера, то вариант бизнес-логики на сервере вполне оправдан.
Главная проблема такой конструкции в том, что только средствами CH консистентность часто недостижима. Например, расчитать/пересчитать текущий баланс не получится без объединения оперативных данных из OLTP с архивными из CH.
А вот тут начинается самое интересное. Вплоть до кувырканий на грани извращения.
При чем тут rustc, если исходное утверждение было об оптимизациях LLVM?
С точки зрения IEEE, которое вполне можно считать общепринятым, UB и есть контракт компилятора, что фиксируется в стандарте. Не вижу смысла продолжать дискуссию с человеком, продвигающим семантику UB, радикально отличающуюся от общепринятой и стандартизированной ANSI и IEEE.
Моего конкретного случая - нет. Там просто отсутствует Xtensa ESP32-S3 для LLVM. GCC в данном случае явно не при чём.
А развлекаться с Cortex-M или RISC-V можете сами, если Вам это интересно.
Ну так очередной итерации уже скоро два года. А воз и ныне там.
Так конкретное значение или авторы компилятора могут интерпретировать этот термин по своему усмотрению?
Неопределенное значение выражения IEEE называет UB. Например, для C
С какого перепугу неопределенное значение выражения для Rust должно называться иначе? Только потому, что авторы компилятора так захотели? )))
Во-первых, связь между флагами оптимизации LLVM и Rust весьма косвенная. Она ограничивается лишь передачей флагов LLVM через llvm-args. Я уже молчу о неявном изменении порядка вычислений при векторизации и использовании SIMD инструкций. Если на x86 в последнем случае еще всё более-менее предсказуемо, то на ARM, RISC-V и Xtensa можно получить просто массу различных неожиданностей.
Во-вторых, IEEE 754-2019 явно описывает обработку исчезновения порядка. И к Rust моя претензия именно в том, что он не предоставляет адекватного способа паниковать при исчезновении порядка. В CLang я могу явно указать -ffp-exception-behavior=strict. А что мне предлагает Rust?
Вы можете тут доказать, что различный результат исполнения одного и того же исходного кода с одними и теми же данными - это определенное поведение?
Если честно, я бы предпочёл, чтобы Rust, хотя бы при указании соответствующих флагов, паниковал при исчезновение порядка при операциях с числами с плавающей запятой (floating-point underflow). Но пока воз и ныне там, приходится лазить в дебагере, разбираясь с такими чудесами.
Исходя из того, что Вы явно впервые слышите об исчезновении порядка, поясняю:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=c67e00613b210f506d07be08e60a9596
Если оптимизатор LLVM решает умножать сначала a на b, например, потому что они уже в регистрах, а свободных регистров в МК нет, то получит в итоге 0, но если будет умножать в указанном в коде порядке (a*c*b*d), то получится 119.99999. Как это ещё назвать, кроме как UB?
Понятно, что если отключить fast-math у LLVM, то проблема исчезнет. Но ценой снижения производительности кода. Выбирайте.
Именно так. На ПК было что в районе 100, а на МК - чистый ноль.
Вы явно перепутали сообщение, на которое отвечаете. Сравнение с нулём не имеет вообще никакого отношения к исчезновению порядка.
Я нарывался в Rust на UB при операциях с числами с плавающей запятой из-за оптимизации LLVM. Одно и то же выражение на ПК оказывалось не нулевым, а на МК - нулевым. Просто из-за перестановки местами множителей при оптимизации. При сохранении порядка умножений, как в исходном выражении, всё было хорошо. А при оптимизации при промежуточном умножении возникало исчезновение порядка и результат оказывался нулевым.
Чем "доделка" C может помочь при динамическом связывании кода, написанного на разных языках программирования?
При чём тут переписывание? До тех пор пока повсеместно используется C ABI и зависимое от него API, ошибки при работе с памятью неизбежны.
Простейший пример. Мы хотим прочитать 100 байт в буфер.
ssize_t read(int fd, void *buf, size_t count);
Что будет, если буфер мы ошибочно выделили не 100, а 50 байт?
В итоге имеем зоопарк различных решений этой проблемы в разных языках в виде стандартной библиотеки языка, так или иначе контролирующей, что буфер будет не меньше, чем count.
Потребность есть в создании безопасного с точки зрения работы с памятью API с соответствующим ABI на уровне ОС и динамического связывания в этой ОС, которыми можно пользоваться на любом языке программирования.
И для этого совершенно не нужно переписывать миллиарды строк кода.
Ну так задача изначально звучала так. Была бы другая задача - был бы другой запрос.
Если уже заниматься перфекционизмом, то так. Внимание на последний запрос.
Скрытый текст
Сравниваем
Во-первых, в браузерах нет поддержки управления HTTP/2 потоками из js. Но это несколько другая история.
А во-вторых, что важнее, комментарий относился к части статьи с заголовком
куда браузеры вписываются плохо.
А еще лучше их буферизировать в этом удобном месте в пределах заданной латентности, отправляя ссылку сразу на пакет.
Вот теперь почти со всем согласен и фраза
оказывается совершенно не к месту.
Почти, потому что
разъём с кабелем в данном случае и является фидером, с которым необходимо согласование. По крайней мере лет 40 назад на кафедре схемотехники в МИЭТ нас учили именно так )
а потом
Так всё же чип или схема согласования с фидером/волноводом и антенной?