Oberon space
General Category => Общий раздел => Тема начата: igor от Декабрь 22, 2012, 03:49:36 pm
-
PROCEDURE (wr: StdWriter) WriteChar (ch: CHAR);
VAR ... fw: Files.Writer;
BEGIN
...
fw.WriteByte(SHORT(SHORT(ORD(ch))));
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256 - 128)));
...
END WriteChar;
Первый SHORT (правый) преобразует результат операции DIV к типу SHORTINT, второй - к типу BYTE. Если результат операции DIV оказался больше 127, то во время выполнения второго SHORT произойдёт ошибка. Для этого и понадобилось отнимать 128.
Решил проверить выделенное утверждение. Результат меня удивил.
Вот тестовый код:
PROCEDURE Do*;
VAR x: SHORTINT; b: BYTE;
BEGIN
x := 1000; (* явно больше MAX(BYTE) *)
b := SHORT(x); (* возникнет ли ошибка RunTime? *)
Log.Int(b); Log.Ln;
END Do;
Результат: b = -24
В сообщении о языке написано:
Name Argument type Result type Function
SHORT(x) SHORTINT BYTE identity
Впрочем, наверное ничего удивительного нет. Дело видимо в том, что по умолчанию в компиляторе не все проверки включены. И то, что заявленное identity не выполняется, остаётся не замеченным.
Если же все проверки включить, то код из процитированной темы при выполнении вероятно выдаст ошибку.
-
fw.WriteByte(SHORT(SHORT(ORD(ch))));
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256 - 128)));
...
Если же все проверки включить, то код из процитированной темы при выполнении вероятно выдаст ошибку.
Хочу уточнить. Ошибку может вызвать первая строчка. А вторая, благодаря "-128", - не приведёт к ошибке.
Очевидно, что первая строчка пишет (по замыслу авторов) младший байт кода ch, а вторая - старший байт. Ибо, как правильно подметил ilovb, операция x DIV 256 равносильна арифметическому сдвигу на восемь символов вправо.
-
allchecks - добавить в исполняемый модуль код, выполняющий дополнительные проверки (переполнение и выход за диапазон значений для целых чисел).
Секреты компилятора (http://www.oberoncore.ru/wiki/blackbox/%D1%81%D0%B5%D0%BA%D1%80%D0%B5%D1%82%D1%8B_%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0)
-
Предлагаю исправленный вариант процедуры WriteChar() из модуля TextModels в Блэкбоксе:
...
fw.WriteByte(SHORT(SHORT(ORD(ch) MOD 256 - 128)));
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256 - 128)));
...
-
Секреты компилятора (http://www.oberoncore.ru/wiki/blackbox/%D1%81%D0%B5%D0%BA%D1%80%D0%B5%D1%82%D1%8B_%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0)
Эта статья написана мной :)
Правда, указывать сей факт на Оберонкоре не сочли нужным...
-
Предлагаю исправленный вариант процедуры WriteChar() из модуля TextModels в Блэкбоксе:
...
fw.WriteByte(SHORT(SHORT(ORD(ch) MOD 256 - 128)));
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256 - 128)));
...
А зачем? Какой в этом смысл?
Пусть будет переполнение.
ps И оно возникает кстати не на больших числах, а на отрицательных в данном случае
-
В итоге получается, что:
- если забыть про то, что SHORT должен, в идеале, генерировать авост при искажении значения, то можно и не делать -128. Будет однохренственный результат (SHORT просто отбросит старшие биты - и будет то же самое, что и SHORT от отрицательного числа).
- но если вспомнить про правильную семантику SHORT, то нужно делать -128, чтобы SHORT^2 для интервала 128..255 не повлёк авоста.
Я лично забыл про правильную семантику... и давно уже считал, что SHORT просто отбросит старшие биты.
Хы, век живи - век учись.
-
Эта статья написана мной :)
Правда, указывать сей факт на Оберонкоре не сочли нужным...
Игорь, внизу указано авторство И. С. Горячева. Т.е. это ошибка?
-
Игорь, внизу указано авторство И. С. Горячева. Т.е. это ошибка?
Да, это ошибка.
Евгений Темиргалеев должен быть в курсе, потому что это он мне предложил тогда написать статью.
-
Предлагаю исправленный вариант процедуры WriteChar() из модуля TextModels в Блэкбоксе:
...
fw.WriteByte(SHORT(SHORT(ORD(ch) MOD 256 - 128)));
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256 - 128)));
...
К сожалению, предложенный мной вариант не верен. :)
Он хоть и позволяет избежать авоста при включенных проверках, но при этом даёт неверный результат. А если быть точным, то он даёт ошибку в старшем бите обоих байтов (и младшего, и старшего).
Правильный вариант (надеюсь :) ) всё же такой:
IF (ORD(ch) MOD 256) < 128 THEN
fw.WriteByte(SHORT(SHORT(ORD(ch) MOD 256)));
ELSE fw.WriteByte(SHORT(SHORT(ORD(ch) MOD 256 - 256)));
END;
IF (ORD(ch) DIV 256) < 128 THEN
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256)));
ELSE fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256 - 256)));
END;
Если же отключить все проверки (чтобы не мешали :) ), то для избежания ошибок данный фрагмент кода следует изложить в такой редакции:
fw.WriteByte(SHORT(SHORT(ORD(ch))));
fw.WriteByte(SHORT(SHORT(ORD(ch) DIV 256)));
Вроде получается так, что хоть при включенных проверках, хоть при выключенных, - данный кусок кода в Блэкбоксе требует правки.
-
Игорь, я постраюсь в ближайшее время прояснить вопрос.
У меня есть гипотеза, что "Иван Горячев" появилось из ника i-gor, но я не представляю, кто именно так ошибся.
-
Игорь, я постраюсь в ближайшее время прояснить вопрос.
Хорошо. Мне удалось отыскать сообщение Евгения Т.:
http://forum.oberoncore.ru/viewtopic.php?p=31860#p31860 (http://forum.oberoncore.ru/viewtopic.php?p=31860#p31860)
PS: Кстати, та тема на Оберонкоре немного перекликается с данной темой.
-
Предлагаю исправленный вариант процедуры WriteChar() из модуля TextModels в Блэкбоксе:
А зачем? Какой в этом смысл?
Пусть будет переполнение.
Как это зачем? Вот, решите вы прогнать свой проект со всеми включенными проверками, для очистки совести, так сказать :). А он возьмёт, да и срубиться на этих строчках кода.
К тому же, если вы решите перейти на другой компилятор, то где гарантия, что в нём "SHORT просто отбросит старшие биты"? Это особенность конкретной реализации, на которую закладываться не стоит.
-
Ну да, неудобство в наличии. Если чесна я бы вшил это в язык (извлечение байтов)
-
В принципе, это цепляние к конкретной заоптимизированной реализации текстов.
А так для записи-чтения CHAR-ов предполагается использование Stores.Reader/Writer.
Ну или для более независимого от Stores способа - своего какого-либо Mappera.
В любом случае, Вы не будете ведь всякие преобразования форматов размазывать по коду.
У меня вот Unsigned-преобразования собраны в отдельном модуле...
-
В любом случае, Вы не будете ведь всякие преобразования форматов размазывать по коду.
У меня вот Unsigned-преобразования собраны в отдельном модуле...
Да. Тоже вариант.
-
Предлагаю исправленный вариант процедуры WriteChar() из модуля TextModels в Блэкбоксе:
А зачем? Какой в этом смысл?
Пусть будет переполнение.
Как это зачем? Вот, решите вы прогнать свой проект со всеми включенными проверками, для очистки совести, так сказать :). А он возьмёт, да и срубиться на этих строчках кода.
К тому же, если вы решите перейти на другой компилятор, то где гарантия, что в нём "SHORT просто отбросит старшие биты"? Это особенность конкретной реализации, на которую закладываться не стоит.
Простейший пример: BlackBox по-умолчанию не реагирует на переполнение, та же самая программе не будет работать с gpcp, т.к. .NET при переполнении выдаст исключение:-(
-
В принципе, это цепляние к конкретной заоптимизированной реализации текстов.
То есть вы не признаёте, что во второй строчке кода сейчас есть ошибка?
В процедуру WriteByte() старший байт кода символа передаётся с проинвертированным старшим битом. Это с отключенными проверками.
Я бы не стал это называть "заоптимизированной реализацией". ;)
-
Под заоптмизированностью я имею в виду то, что они там используют запись напрямую в файл, минуя Stores.Writer.
А что они ошиблись именно так, как мы думаем... Тогда бы в обоих строчках было -128.
Короче говоря, вольно или невольно получили они своё кодирование символов :)
-
Мой вариант: :)
PROCEDURE Do*;
VAR
ch: CHAR;
b1, b2: BYTE;
i: INTEGER;
BEGIN
FOR i := 0 TO 65535 DO
ch := CHR(i);
b1 := SHORT(SHORT(ASH(ASH(ORD(ch), 24), -24)));
b2 := SHORT(SHORT(ASH(ASH(ORD(ch), 16), -24)));
ASSERT(ch = CHR((ASH(b2 MOD 256, 8) + b1 MOD 256)));
END;
END Do;
-
Мой вариант: :)
Неплохой вариант. Но проверки придётся таки отключить. ;)
-
А что они ошиблись именно так, как мы думаем... Тогда бы в обоих строчках было -128.
Игорь хотел сказать, что они ошиблись в любом случае, независимо от того, что мы думаем ;)
У них 2+2=5, и это косяк как ни крути.
-
Мой вариант: :)
Неплохой вариант. Но проверки придётся таки отключить. ;)
Почему?
-
Неплохой вариант. Но проверки придётся таки отключить. ;)
Почему?
Ну, давайте рассмотрим вот эту строчку:
b1 := SHORT(SHORT(ASH(ASH(ORD(ch), 24), -24)));
Арифметический сдвиг влево на 24 бита, а затем вправо на 24 бита никак не влияет на младший байт кода символа. А проблема именно в нём. Если у него старший бит равен "единице", то во время выполнения внешнего SHORT возникнет переполнение.
-
Фишка в том, что сдвиг арифметический, и следовательно тянет за собой знак:
x = 0000 0000 - 0000 0000 - 0000 0000 - 1000 0000 = 128 (будет переполнение, ибо не помещается в байт)
x = ASH(ASH(x, 24), -24)
x = 1111 1111 - 1111 1111 - 1111 1111 - 1000 0000 = -128 (нет переполнения) ;)
ps Вы же сами упоминали что SHORT делает идентичное преобразование
-
Фишка в том, что сдвиг арифметический, и следовательно тянет за собой знак:
x = 0000 0000 - 0000 0000 - 0000 0000 - 1000 0000 = 128 (будет переполнение, ибо не помещается в байт)
x = ASH(ASH(x, 24), -24)
x = 1111 1111 - 1111 1111 - 1111 1111 - 1000 0000 = -128 (нет переполнения) ;)
ps Вы же сами упоминали что SHORT делает идентичное преобразование
Как говорит Илья, век живи - век учись. :)
Вы правы. Причём, ваш вариант даже лучше, чем мой. Потому что не требует никаких IF'ов.
(Я не учёл, что расширение знака влияет на значение младшего байта)
-
Если ASH это реально ASH, но я видел такую чехарду... - это транслировалось и в SAL/SAR и в SHL/SHR
-
Такое может быть только при кривом компиляторе. ASH всегда должен компилиться в SAL/SAR.
-
PROCEDURE Shift* (VAR x, y: DevCPL486.Item; subcl: BYTE); (* ASH, LSH, ROT *)
VAR L1, L2: DevCPL486.Label; c: DevCPL486.Item; opl, opr: INTEGER;
BEGIN
IF subcl = ash THEN opl := SHL; opr := SAR
ELSIF subcl = lsh THEN opl := SHL; opr := SHR
ELSE opl := ROL; opr := ROR
END;
IF y.mode = Con THEN
IF y.offset > 0 THEN
DevCPL486.GenShiftOp(opl, y, x)
ELSIF y.offset < 0 THEN
y.offset := -y.offset;
DevCPL486.GenShiftOp(opr, y, x)
END
ELSE
ASSERT(y.mode = Reg);
Check(y, -31, 31);
L1 := DevCPL486.NewLbl; L2 := DevCPL486.NewLbl;
DevCPL486.MakeConst(c, 0, y.form); DevCPL486.GenComp(c, y);
DevCPL486.GenJump(ccNS, L1, TRUE);
DevCPL486.GenNeg(y, FALSE);
DevCPL486.GenShiftOp(opr, y, x);
DevCPL486.GenJump(ccAlways, L2, TRUE);
DevCPL486.SetLabel(L1);
DevCPL486.GenShiftOp(opl, y, x);
DevCPL486.SetLabel(L2);
Free(y)
END;
IF x.mode # Reg THEN Free(x) END
END Shift;
ps SHL = SAL
-
allchecks - добавить в исполняемый модуль код, выполняющий дополнительные проверки (переполнение и выход за диапазон значений для целых чисел).
Секреты компилятора (http://www.oberoncore.ru/wiki/blackbox/%D1%81%D0%B5%D0%BA%D1%80%D0%B5%D1%82%D1%8B_%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0)
srcpos - Включает запись в объектник информации о соответствии позиции исходного кода смещению в машинном коде.
-
Дык оно и так пишется, вроде!
-
Дык оно и так пишется, вроде!
Тык да. Я к тому что там в WIKI это не написано...
-
Нет, оно и без опций пишется - так ведь трэпы работают и Kernel.SourcePos....
-
Да не. Я про то что там описания нет у srcpos :)
-
Очевидно, что первая строчка пишет (по замыслу авторов) младший байт кода ch, а вторая - старший байт.
Не совсем очевидно. Мне кажется, это может быть наследием какой-то исторической кодировки.
Например: символы 00-7F кодируются одним байтом, а 80-7FFF - двумя. При этом отрицательное значение байта указывает на сдвиг предыдущего.
-
Присоединяюсь к предыдущему оратору по поводу 80-7FFFF :)
-
http://oberspace.dyndns.org/index.php/topic,403.msg12067.html#msg12067
-
Очевидно, что первая строчка пишет (по замыслу авторов) младший байт кода ch, а вторая - старший байт.
Не совсем очевидно. Мне кажется, это может быть наследием какой-то исторической кодировки.
Например: символы 00-7F кодируются одним байтом, а 80-7FFF - двумя. При этом отрицательное значение байта указывает на сдвиг предыдущего.
Может некоторые символы у них и кодируются одним байтом. Но обсуждаемый фрагмент кода последовательно извлекает из кода символа два байта (сначала младший, а затем старший) для того, чтобы передать их в процедуру WriteByte(). В контексте данного обсуждения только это и важно.
-
Не мне судить, что важно, но говорить об очевидности замысла авторов, я бы поостерегся.
-
Не мне судить, что важно, но говорить об очевидности замысла авторов, я бы поостерегся.
Извините, я никак не думал, что Вы этих авторов держите за идиотов. ;)
Обе осуждаемые строчки ошибочны. Я, в отличие от Вас, полагал, что в замыслы авторов не входило строчить ошибочный код, о чём и написал.
-
Я не считаю эти строчки ошибочными.
И кто из нас держит авторов за идиотов?
-
Обе осуждаемые строчки ошибочны.
[offtop]
Всё-таки иногда бывает жаль, что нельзя поправить свои собственные сообщения.
В приведённой цитате имелось в виду слово "обсуждаемые".
[/offtop]
-
Я не считаю эти строчки ошибочными.
Т.е. переполнение это нормально для языка в котором это запрещено семантикой SHORT?
-
Я не считаю эти строчки ошибочными.
Без комментариев... :o
И кто из нас держит авторов за идиотов?
У-фф... Ещё раз. Если включить все проверки, то первая строчка может вызвать переполнение. А вторая переполнение не вызовет, но при этом искажает значение байта. Я убеждён, что авторы НЕ СПЕЦИАЛЬНО допустили эти ошибки. Значит, они не идиоты.
(Мы все ошибаемся. Но только идиоты могут делать это нарочно.)
-
В ББ хватает мест, где SHORT используется для приведения значений. Типа такого:
PROCEDURE Write4 (x: INTEGER);
BEGIN
Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
Ro.WriteByte(SHORT(SHORT(x MOD 256)))
END Write4;
И если включить все проверки, он скорее всего не заработает. Вероятно, авторы понимают семантику SHORT несколько иначе. :)
Хотя иногда случаются приступы семантической чистоты.
IF ORD(str[i]) > MAX(BYTE) THEN w.WriteByte(SHORT(SHORT(ORD(str[i]) - 256)))
ELSE w.WriteByte(SHORT(SHORT(ORD(str[i]))))
END;
В осуждаемых же строчках 128 вычитается явно намеренно, с какой-то неизвестной нам целью.
-
В осуждаемых же строчках 128 вычитается явно намеренно, с какой-то неизвестной нам целью.
Несколько бредовое предположение :)
М.б. чтобы в файле там, где присутствуют двухбайтные чары было "побольше" байтов от 80 до FF.
Ведь основные уникод символы лежат до 7FFF и вычитание 128 уводит старший байт в область от 80 до FF .
В hex дампе файла эти области будут нагляднее выделяться.
-
В дополнении к предыдущему.
Я лично изначально представил (неправильно), что это (вычитание 128) как раз для маркирования двухбайтных чаров в файле.
Но позже вроде понял, что есть специальные маркеры для пометки областей с такими чарами. Или там в формате файла заложены длины и типы областей. Как на самом деле - точно не знаю. Это надо копаться.
-
Или там в формате файла заложены длины и типы областей.
Там длина одновременно кодирует тип. Если отрицательная, то символы двухбайтовые.
-
Блин, что за такое извращённое стремление к минимализму?
Да взяли бы просто записали бы потоком по два байта на символ (раз уж у них символы размером в два байта) и сжали бы gzip'ом -- экономия места на диске была бы в разы больше!
-
Ага, ещё из зип-архивацию сразу писать :) Или плодить зависимость базовых подсистем от каких-то непойми-левых библиотек :)
-
Ага, ещё из зип-архивацию сразу писать :) Или плодить зависимость базовых подсистем от каких-то непойми-левых библиотек :)
Ну зачем же левые либы? Помнится разбирался в устройстве файлов какого-то словаря, так там применялся для компактного хранения тонн текста тупо алгоритм Хаффмана. И жалось вполне неплохо. И работало быстро. Реализовать такое - раз плюнуть.
-
Ага, ещё из зип-архивацию сразу писать :) Или плодить зависимость базовых подсистем от каких-то непойми-левых библиотек :)
Франц осилил упаковку своих сантаксических деревьев, неужто Оминк не осили бы нечто подобное? о_О
-
Это пацанство - инвестировать драгоценное время в подобную фичу во время разработки основного функционала системы... :) Даже один день жалко.
-
Это пацанство - инвестировать драгоценное время в подобную фичу во время разработки основного функционала системы... :) Даже один день жалко.
Ну, реализовать обычного Хаффмана это по затратам примерно столько же, сколько изобретение собственной кодировки с реализацией, и беготней по всем возможным граблям. Если дня жалко - сделали бы фиксированную двубайтовую, тупо ucs-2 и все. Это гарантированно безглючно. Точнее все возможные грабли всем известны.
То есть мне то как раз не понятно инвестирование времени в эту невнятную кодировку с плавающей длиной символа.
-
Это пацанство - инвестировать драгоценное время в подобную фичу во время разработки основного функционала системы... :) Даже один день жалко.
Что за бред??? о_О
Сделать целую операционку, всякие редакторы текстовые и графические, компиляторы настрогать -- и не сделать архиваторы? Ну и как они планировали обмениваться информацией с внешним миром? Да даже для тех же графредакторов нужны упаковщики/распаковщики всяких GIF/PNG/JPG форматов!
И какого хрена вообще тогда сжимали свои файлы левыми архиваторами??? Так бы тупо в несжатом виде распространяли бы...
-
То есть мне то как раз не понятно инвестирование времени в эту невнятную кодировку с плавающей длиной символа.
Да, вот именно! Что это за пацанство с их стороны было???
-
2 Geniepro:
Форматы, гзипы, джпеги - всё это делается позже. На других итерациях развития системы.
Чем меньше работы ты можешь сделать на очередной итерации - тем лучше.
Желательно вообще в основном абстракции-интерфейсы сделать и начать пробовать, а реализации - самые "тупые". Потом можно поменять...
-
2 Geniepro:
Форматы, гзипы, джпеги - всё это делается позже. На других итерациях развития системы.
Чем меньше работы ты можешь сделать на очередной итерации - тем лучше.
Желательно вообще в основном абстракции-интерфейсы сделать и начать пробовать, а реализации - самые "тупые". Потом можно поменять...
Да, короткие итерации рулят. Самый верный способ загубить проект - попытаться с первой итерации все сдеалать идеально.
-
Не, зипы - это лишнее. Вы подумайте: файл, хоть в гигабайт на компьютере со считанными мегабайтами памяти можно было открыть за доли секунды и тут же начать редактировать.
-
Не, зипы - это лишнее. Вы подумайте: файл, хоть в гигабайт на компьютере со считанными мегабайтами памяти можно было открыть за доли секунды и тут же начать редактировать.
То есть в текущей реализации ББ файл (документ) в ОЗУ полностью не грузится?
-
Нет, не грузится. Сейчас, конечно, уже можно было бы грузить, но эта схема еще от Оберона.
-
Нет, не грузится. Сейчас, конечно, уже можно было бы грузить, но эта схема еще от Оберона.
Забавно. Надо будет проверить. А каков максимальный размер файла/документа в BB? 4 гигабайта?
-
2 Geniepro:
Форматы, гзипы, джпеги - всё это делается позже. На других итерациях развития системы.
Чем меньше работы ты можешь сделать на очередной итерации - тем лучше.
Желательно вообще в основном абстракции-интерфейсы сделать и начать пробовать, а реализации - самые "тупые". Потом можно поменять...
Так нафига вообще было сделано это 1-2-байтное кодирование? Ведь ежу понятно (а Вам видимо нет) что без этого лисапеда проще и быстрее сделать сохранение/считывание документов и приступить к другим, более важным вещам!!!
-
Не, зипы - это лишнее. Вы подумайте: файл, хоть в гигабайт на компьютере со считанными мегабайтами памяти можно было открыть за доли секунды и тут же начать редактировать.
Во-первых, есть же алгоритмы потокового сжатия.
В конце концов, даже тем же зиповским алгоритмом можно было бы сжимать не весь документ целиком, а блоками. Всё равно был бы выигрыш по размеру.
Во-вторых, по гигабайтному файлу мгновенно позиционироваться можно если он вообще ничем не сжат или есть таблица начал сжатых блоков.
В блекбоксовском же варианте придётся по-любому проходить по всему файлу с начала до того места, которое нужно отобразить...
-
Нет, не грузится. Сейчас, конечно, уже можно было бы грузить, но эта схема еще от Оберона.
Забавно. Надо будет проверить. А каков максимальный размер файла/документа в BB? 4 гигабайта?
В памяти вроде только то что на экране.
-
А размер наверно не ограничен. Там же писы. А длина писы измеряется INTEGER'ом
-
Или там в формате файла заложены длины и типы областей.
Там длина одновременно кодирует тип. Если отрицательная, то символы двухбайтовые.
Да, чем гадать, надо было просто посмотреть на начало текста модуля TextModels :)
-
Нет, не грузится. Сейчас, конечно, уже можно было бы грузить, но эта схема еще от Оберона.
Таки дико извиняюсь, но я провел эксперимент.
Я взял базу нашего форума в json формате (ту, что я выложил), и скопипастил в документ ББ 1.6. Сохранил. Исходный файл был 14 Мегабайт, документ ББ стал 22 Мб.
Закрыл ББ. Открыл ББ, открыл там этот файл. До открытия файла ББ кушал порядка 16 Мегабайт ОЗУ, сразу после открытия - то ли 67 Мегабайт, то ли 82 Мегабайта. То есть оно скушало больше ОЗУ, чем файл занимает на диске вообще. Попробовал спозиционироваться в конец файла (Ctrl+End) - ББ ушел в себя и не вернулся. То есть отожрал одно из ядер, и не думает возвращать. Интерфейс естественно заморожен.
То есть по факту, большие файлы в ББ редактировать нельзя. Тезис
Вы подумайте: файл, хоть в гигабайт на компьютере со считанными мегабайтами памяти можно было открыть за доли секунды и тут же начать редактировать.
Не верен. По крайней мере в приложении к ББ 1.6 в современных реалиях. Замечу, что это файло всего то 14 Мб размером исходно. Никаких гигабайтов.
PS. А еще один раз ББ отожрал полгига. На этом же файле. Не знаю почему.
PPS. Да, вполне возможно что это например какая-то гуйнявая компонента гадит, например Win32шные TextEditor, или как его там. Или кто-то еще. Один из многочисленных слоев. Но юзабельней для данной задачи от этого ББ не становится.
-
А в открываемом файле нет ли очень длинных участков без переноса строки?
В таком случае тормоз идёт уже при работе алгоритма размещения символов по строкам...
Открой какой-нибудь здоровый текст "человеческий", с абзацами.
-
Т.е. тормоз не в TextModels, а в TextViews либо даже TextSetters (вероятнее).
-
А в открываемом файле нет ли очень длинных участков без переноса строки?
В таком случае тормоз идёт уже при работе алгоритма размещения символов по строкам...
Открой какой-нибудь здоровый текст "человеческий", с абзацами.
Это все одно большая строка :-)
Отформатировал json, и вставил в ББ (так что это не одна большая строка), и повторил эксперимент: потребление памяти осталось в точности таким же как и в случае одной большой длинной строки. Но вот тормозов стало меньше. Ctrl+End/PageUp/PageDown теперь работают за приемлемое время - примерно по секунде тратится. То есть тормоза конечно, но жить можно.
Да, нашел ситуацию когда ББ радостно полгига отъедает - кушает в момент когда я из буфера обмена вставляю эти 14 Мб текста. Потом потребление памяти не падает (сколь я помню, ББ не возвращает память в систему даже если она больше не нужна).
-
Решил открыть этот файл в сублиме -- полчаса или час назад кинул его в редактор,полоса прогресса де-то 40% показывает )))
-
А в открываемом файле нет ли очень длинных участков без переноса строки?
В таком случае тормоз идёт уже при работе алгоритма размещения символов по строкам...
Открой какой-нибудь здоровый текст "человеческий", с абзацами.
Это все одно большая строка :-)
Отформатировал json, и вставил в ББ (так что это не одна большая строка), и повторил эксперимент: потребление памяти осталось в точности таким же как и в случае одной большой длинной строки. Но вот тормозов стало меньше. Ctrl+End/PageUp/PageDown теперь работают за приемлемое время - примерно по секунде тратится. То есть тормоза конечно, но жить можно.
Да, нашел ситуацию когда ББ радостно полгига отъедает - кушает в момент когда я из буфера обмена вставляю эти 14 Мб текста. Потом потребление памяти не падает (сколь я помню, ББ не возвращает память в систему даже если она больше не нужна).
Продолжаем эксперименты. Взял тот же, уже человеческий json, с абзацами, и продублировал его. Соответственно текст стал в два раза длиннее. Сохранил, закрыл ББ, открыл ББ, открыл файло (которое теперь не 22 Мб, а 44). Посмотрел на память.
Потребление памяти выросло, относительно 22 Мб файла ровно в два раза. 120 Мб против 60ти.
Потребление памяти в ББ прямо пропорционально объему открытого файла (с коэффициентом больше единицы), вне зависимости от его содержимого (с абзацами он или без).
-
Решил открыть этот файл в сублиме -- полчаса или час назад кинул его в редактор,полоса прогресса де-то 40% показывает )))
Зато FAR (у меня третий) без дополнительных плагинов открывает мгновенно и на просмотр и на редактирование. Позиционироваие происходит тоже мгновенно.
-
Решил открыть этот файл в сублиме -- полчаса или час назад кинул его в редактор,полоса прогресса де-то 40% показывает )))
Зато FAR (у меня третий) без дополнительных плагинов открывает мгновенно и на просмотр и на редактирование. Позиционироваие происходит тоже мгновенно.
Ну AkelPad тоже быстро открывает -- примерно секунду, а вот Notepad и Edit+ тормозят нещадно...
-
То есть по факту, большие файлы в ББ редактировать нельзя.
Странно, я для эксперимента открывал файл в 600М на компьютере с 512M ОЗУ. И вполне редактируется. Только вот сохранять долго, да.
-
То есть по факту, большие файлы в ББ редактировать нельзя.
Странно, я для эксперимента открывал файл в 600М на компьютере с 512M ОЗУ. И вполне редактируется. Только вот сохранять долго, да.
Видимо сильно зависит от содержимого, и, возможно, редакции/версии ББ.
-
То есть по факту, большие файлы в ББ редактировать нельзя.
Странно, я для эксперимента открывал файл в 600М на компьютере с 512M ОЗУ. И вполне редактируется. Только вот сохранять долго, да.
Видимо сильно зависит от содержимого, и, возможно, редакции/версии ББ.
Проверил на школьной сборке (это вроде бы 1.5) - то же самое.
-
То есть по факту, большие файлы в ББ редактировать нельзя.
Странно, я для эксперимента открывал файл в 600М на компьютере с 512M ОЗУ. И вполне редактируется. Только вот сохранять долго, да.
Возможно там этот документ поместился в виртуальную память, которая была больше чем 512М...
-
Спасибо, valexey.
Я в очередной раз убедился что текстовая подсистема BB сделана хуже некуда.
Проверил Oberon V4 (http://www.claudio.ch/V4/)
Открывает этот файл мгновенно. Потребление памяти 800 кб.
-
То есть по факту, большие файлы в ББ редактировать нельзя.
Странно, я для эксперимента открывал файл в 600М на компьютере с 512M ОЗУ. И вполне редактируется. Только вот сохранять долго, да.
Кажется я немного локализовал проблему: если создать большой текстовый файл (просто txt) в ASCII, то ББ его отлично открывает, и при этом потребление памяти не растет. Только что создал в фаре и открыл в ББ текстовый файл размером 177 Мб. Работает отлично. Не тормозит ни в каком месте (только открывал долго), если строки там не слишком длинные.
А вот если мы имеем ББ-документ большой, то все, амба. Жрет память и тормозит при листании. То есть со своими документами ББ работает хуже чем с txt. И свои документы он полностью засасывает в ОЗУ (видимо аля DOMа строит). Следовательно что? Следовательно свои документы можно было не мудря с кодировкой просто сжимать Хаффманом, если жалко места, а если не жалко, то хранить текст просто в ucs-2.
-
Спасибо, valexey.
Я в очередной раз убедился что текстовая подсистема BB сделана хуже некуда.
Проверил Oberon V4 (http://www.claudio.ch/V4/)
Открывает этот файл мгновенно. Потребление памяти 800 кб.
См. мое сообщение выше. Если он у тебя открывает txt'шник, то это одно, если он открывает собственный составной документ где есть только этот текст - это другое.
-
Проверил. Ничего не изменилось :)
-
Потребление памяти 800 кб.
Вру. Эти 800 кб. уходят мод загружаемые модули текстовой подсистемы при первом вызове Edit.Open
А под наш файлик выделяется примерно 12 кб. Т.е. как я и думал в памяти только то что на экране.
Только вот в BB это не так. Но там возможно файл мапится в память...
-
txt он и есть txt - чистый текст. Его где ни открой - он везде валиден, поэтому скорость работы с ним максимальная, а вот документ... его же парсить надо, можно, конечно, ускорить, но все равно ресурсов он будет жрать существенно больше.
-
Стоп-стоп, господа, а вы сохранили этот документ в ODC, прежде чем открывать и что-то мерять?
Иначе он открывается через конвертер, порождается новый TextModel в памяти.
-- Пардон, прочёл выше. Странно.
-
Но в итоге надо различать уровень TextModel и уже собственно отображения на экране.
Тормозит, скорее всего, не TextModel, который захреначен с расчётом на частичную подгрузку.
А уже выше в Views или Setters какой-нибудь конкретный алгоритм, сделанный "по быстрому" и "имеющий" текст целиком.
-
Секреты компилятора (http://www.oberoncore.ru/wiki/blackbox/%D1%81%D0%B5%D0%BA%D1%80%D0%B5%D1%82%D1%8B_%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0)
Эта статья написана мной :)
Правда, указывать сей факт на Оберонкоре не сочли нужным...
Рад сообщить, что благодаря помощи Ильи Ермакова и при его непосредственном участии недоразумение с авторством статьи на Оберонкоре было устранено :)
-
Причины ошибки имели технический характер.
-
Причины ошибки имели технический характер.
Возможно... но не в целях разжигания междусобоя, но справедливости ради..
обратите внимание на
"
Автор разделов «Опции компилятора» и «Маркер конца списка компиляции»: Лоскутов И.В.
Автор*: Горячев И.Н. Правки: Ермаков. И.Е.
"
вы всего лишь "Автор разделов" ;) а истинные авторы ниже ;D
-
Относительно возможности открытия больших текстов в BlackBox.
BlackBox не загружает содержимое в память, он читает текст из файла используя кеширование. Но Piece'ы загружаются в память полностью. Поэтому текст с большим количеством не Latin-1 символов может забить память Piece'ами и привести к жутким тормозам. Можете открыть HeapSpy и посмотреть как чередуются в памяти Piece и LPiece. Тормоза можно убрать, если отключить генерацию коротких Piece'ов, записывая все символы только в UTF-16. Для этого можно сделать такой хак в модуле TextModels:
PROCEDURE (wr: StdWriter) WriteChar (ch: CHAR);
VAR t: StdModel; u, un: Run; lp: LPiece; pos, spillPos: INTEGER;
fw: Files.Writer; op: EditOp; bunch: BOOLEAN;
BEGIN
IF ch = 200BX THEN wr.WriteChar(zwspace)
ELSIF ch = 2010X THEN wr.WriteChar(hyphen)
ELSIF ch = 2011X THEN wr.WriteChar(nbhyphen)
ELSE
После него BlackBox сразу открывает файлы даже размером в полтора гигабайта (предварительно сконвентированные в ODC; если этого не сделать, то BlackBox будет сам конвертировать при загрузке в %temp%). Ничего не тормозит вообще, только полоса прокрутки глючит. Потребление памяти при этом - около 500 КБ. Очень большие файлы открыть нельзя ввиду того, что для задания позиций и размеров используется INTEGER (в соответствии с сообщением о языке его размер - 4 байта).
Видимо эти LPiece'ы были добавлены бездумно без учёта последствий. К тому же насколько мне известно BlackBox разрабатывали немцы, а им юникод не нужен.
-
Короче вот они, последствия преждевременной оптимизации -- стреляют ещё как.
-
Короче вот они, последствия преждевременной оптимизации -- стреляют ещё как.
Где тут про преждевременную оптимизацию? Просто криво поддержку юникода ввели...
-
Короче вот они, последствия преждевременной оптимизации -- стреляют ещё как.
Где тут про преждевременную оптимизацию? Просто криво поддержку юникода ввели...
При этом заоптимизировали эту поддержку для уменьшения объёма файлов...
-
При этом заоптимизировали эту поддержку для уменьшения объёма файлов...
Скорее для совместимости со старыми версиями без поддержки юникода так сделали, а не из-за размера. У старых версий BlackBox'а LPiece'ов не было.
-
Относительно возможности открытия больших текстов в BlackBox.
BlackBox не загружает содержимое в память, он читает текст из файла используя кеширование. Но Piece'ы загружаются в память полностью. Поэтому текст с большим количеством не Latin-1 символов может забить память Piece'ами и привести к жутким тормозам. Можете открыть HeapSpy и посмотреть как чередуются в памяти Piece и LPiece. Тормоза можно убрать, если отключить генерацию коротких Piece'ов, записывая все символы только в UTF-16. Для этого можно сделать такой хак в модуле TextModels:
PROCEDURE (wr: StdWriter) WriteChar (ch: CHAR);
VAR t: StdModel; u, un: Run; lp: LPiece; pos, spillPos: INTEGER;
fw: Files.Writer; op: EditOp; bunch: BOOLEAN;
BEGIN
IF ch = 200BX THEN wr.WriteChar(zwspace)
ELSIF ch = 2010X THEN wr.WriteChar(hyphen)
ELSIF ch = 2011X THEN wr.WriteChar(nbhyphen)
ELSE
После него BlackBox сразу открывает файлы даже размером в полтора гигабайта (предварительно сконвентированные в ODC; если этого не сделать, то BlackBox будет сам конвертировать при загрузке в %temp%). Ничего не тормозит вообще, только полоса прокрутки глючит. Потребление памяти при этом - около 500 КБ.
Спасибо. Это действительно объясняет результаты этого эксперимента: http://oberspace.dyndns.org/index.php/topic,408.msg12256.html#msg12256
Ключевое слово - ASCII.