Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICU data file builds are non-deterministic #55637

Closed
akoeplinger opened this issue Jul 14, 2021 · 31 comments
Closed

ICU data file builds are non-deterministic #55637

akoeplinger opened this issue Jul 14, 2021 · 31 comments
Assignees
Milestone

Comments

@akoeplinger
Copy link
Member

akoeplinger commented Jul 14, 2021

See Rolf's comment on https://github.com/xamarin/xamarin-macios/pull/11983/files#r657759425

This is unintentional, we're using the same filter so they should be identical.

@akoeplinger akoeplinger added this to the 6.0.0 milestone Jul 14, 2021
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Jul 14, 2021
@akoeplinger akoeplinger removed the untriaged New issue has not been triaged by the area owner label Jul 14, 2021
@ghost
Copy link

ghost commented Jul 14, 2021

Tagging subscribers to this area: @directhex
See info in area-owners.md if you want to be subscribed.

Issue Details

See Rolf's comment on https://github.com/xamarin/xamarin-macios/pull/11983/files#r657759425

Author: akoeplinger
Assignees: -
Labels:

area-Infrastructure-mono

Milestone: 6.0.0

@akoeplinger
Copy link
Member Author

/cc @steveisok

@filipnavara
Copy link
Member

For reference here's a table with some of the sizes: dotnet/designs#225 (comment). They differ even for the same architecture between two platforms. One of my theories is that it's related to the zlib version / default options on the build machine.

@steveisok steveisok self-assigned this Jul 22, 2021
@directhex
Copy link
Contributor

The default packaging mode is common, or archive. In this mode, the different data files are bundled together as an architecture-dependent file that can later be memory mapped for use by ICU.

https://linux.die.net/man/1/pkgdata

Emphasis mine.

icudt.dat is arch specific according to the documentation.

@steveisok
Copy link
Member

So, are you suggesting "by design" then?

@filipnavara
Copy link
Member

Would that explain why the size differs between arm64 on Android and iOS? (ie. essentially same arch) I would also expect x64 and arm64 to be within margin of error, that was not the case.

@directhex
Copy link
Contributor

The ICU docs say it's by design.

@directhex
Copy link
Contributor

@filipnavara I'd need to examine pkgdata.cpp more closely to be able to answer that

@filipnavara
Copy link
Member

filipnavara commented Jul 27, 2021

The iOS one is about 200 Kb (13%) bigger than the Android one. That may be worth another look even if it turns out to be by design.

@directhex
Copy link
Contributor

directhex commented Jul 27, 2021

Hm. From more docs:

By distributing the default data in the form of common format .dat files rather than as shared libraries, a single data file can be shared among multiple platforms. This is beneficial if a single distribution of the application (a CD, for example) includes binaries for many platforms, and the size requirements for replicating the ICU data for each platform are a problem.

ICU common format data files are not completely interchangeable between platforms. The format depends on these properties of the platform:

  • Byte Ordering (little endian vs. big endian)

  • Base character set - ASCII or EBCDIC

This means, for example, that ICU data files are interchangeable between Windows and Linux on X86 (both are ASCII little endian), or between Macintosh and Solaris on SPARC (both are ASCII big endian), but not between Solaris on SPARC and Solaris on X86 (different byte ordering).

http://userguide.icu-project.org/icudata

@directhex
Copy link
Contributor

The problem I have with "it says it's by design but that's likely wrong in the docs and I'm sure we can ignore them" is it may well be true today, but it might not be tomorrow. We're on ICU 67, maybe 68 is the time when it goes from "big endian vs little endian" to "big endian vs little endian, also 32 bit vs 64 bit" or "big endian vs little endian, also 32 bit vs 64 bit, also ILP32 vs LLP64 vs LP64"

@filipnavara
Copy link
Member

filipnavara commented Jul 27, 2021

There are two separate practical issues:

  • One is the size itself which happens to be significantly bigger on iOS than on other platforms and which will practically affect everyone even if no sharing takes place.
  • The other one is sharing the files for universal binaries which currently only affects Mac Catalyst and it could be done opportunistically, ie. only share the data if they are identical.

@filipnavara
Copy link
Member

Local build today:

filipnavara@172-4-1-17 icu % ls -l artifacts/bin/icu-ios-arm/
total 9888
-rw-r--r--  1 filipnavara  staff  2176304 Jul 28 23:42 icudt.dat
-rw-r--r--  1 filipnavara  staff  1006224 Jul 28 23:45 icudt_CJK.dat
-rw-r--r--  1 filipnavara  staff   602096 Jul 28 23:44 icudt_EFIGS.dat
-rw-r--r--  1 filipnavara  staff  1271296 Jul 28 23:44 icudt_no_CJK.dat
drwxr-xr-x  3 filipnavara  staff       96 Jul 28 23:43 include
drwxr-xr-x  7 filipnavara  staff      224 Jul 28 23:43 lib
filipnavara@172-4-1-17 icu % ls -l artifacts/bin/icu-ios-arm64/
total 11776
-rw-r--r--  1 filipnavara  staff  2176304 Jul 28 23:40 icudt.dat
-rw-r--r--  1 filipnavara  staff  1006224 Jul 28 23:41 icudt_CJK.dat
-rw-r--r--  1 filipnavara  staff   602096 Jul 28 23:41 icudt_EFIGS.dat
-rw-r--r--  1 filipnavara  staff  1271296 Jul 28 23:41 icudt_no_CJK.dat
drwxr-xr-x  3 filipnavara  staff       96 Jul 28 23:41 include
drwxr-xr-x  7 filipnavara  staff      224 Jul 28 23:41 lib

I'll try to run Android builds on the same machine tomorrow to check whether there is any difference. Can someone recheck the current transport packages whether the problem still exists?

@filipnavara
Copy link
Member

filipnavara commented Jul 28, 2021

Android arm64 on the same machine is also identical:

filipnavara@172-4-1-17 icu % ls -l artifacts/bin/icu-android-arm64 
total 9888
-rw-r--r--  1 filipnavara  staff  2176304 Jul 28 23:57 icudt.dat
-rw-r--r--  1 filipnavara  staff  1006224 Jul 28 23:58 icudt_CJK.dat
-rw-r--r--  1 filipnavara  staff   602096 Jul 28 23:58 icudt_EFIGS.dat
-rw-r--r--  1 filipnavara  staff  1271296 Jul 28 23:58 icudt_no_CJK.dat
drwxr-xr-x  3 filipnavara  staff       96 Jul 28 23:57 include
drwxr-xr-x  7 filipnavara  staff      224 Jul 28 23:57 lib

Looks like the local vanilla builds do the correct thing. The pipelines for all iOS variants run on the same machine so that should rule out some compiler configuration differences (for arm64 vs arm). Android and iOS use different build machines though (Linux vs macOS).

@filipnavara
Copy link
Member

I checked some somewhat recent transport package and it's still broken:

filipnavara@172-4-1-17 runtime % ls -l ~/.nuget/packages/microsoft.netcore.runtime.icu.transport/6.0.0-rc.1.21369.1/runtimes/ios-arm/native/lib/
total 27912
-rwxr--r--  1 filipnavara  staff  2087920 Jul 19 18:08 icudt.dat
-rwxr--r--  1 filipnavara  staff  1006224 Jul 19 18:08 icudt_CJK.dat
-rwxr--r--  1 filipnavara  staff   602096 Jul 19 18:08 icudt_EFIGS.dat
-rwxr--r--  1 filipnavara  staff  1271296 Jul 19 18:08 icudt_no_CJK.dat
-rwxr--r--  1 filipnavara  staff     1296 Jul 19 18:08 libicudata.a
-rwxr--r--  1 filipnavara  staff  5753376 Jul 19 18:08 libicui18n.a
-rwxr--r--  1 filipnavara  staff  3556640 Jul 19 18:08 libicuuc.a
filipnavara@172-4-1-17 runtime % ls -l ~/.nuget/packages/microsoft.netcore.runtime.icu.transport/6.0.0-rc.1.21369.1/runtimes/ios-arm64/native/lib/
total 20552
-rwxr--r--  1 filipnavara  staff  1913136 Jul 19 18:08 icudt.dat
-rwxr--r--  1 filipnavara  staff  1006224 Jul 19 18:08 icudt_CJK.dat
-rwxr--r--  1 filipnavara  staff   602096 Jul 19 18:08 icudt_EFIGS.dat
-rwxr--r--  1 filipnavara  staff  1161120 Jul 19 18:08 icudt_no_CJK.dat
-rwxr--r--  1 filipnavara  staff      720 Jul 19 18:08 libicudata.a
-rwxr--r--  1 filipnavara  staff  3536472 Jul 19 18:08 libicui18n.a
-rwxr--r--  1 filipnavara  staff  2286384 Jul 19 18:08 libicuuc.a
filipnavara@172-4-1-17 runtime % ls -l ~/.nuget/packages/microsoft.netcore.runtime.icu.transport/6.0.0-rc.1.21369.1/runtimes/android-arm/native/lib/
total 27736
-rwxr--r--  1 filipnavara  staff  1832064 Jul 19 18:09 icudt.dat
-rwxr--r--  1 filipnavara  staff   966080 Jul 19 18:09 icudt_CJK.dat
-rwxr--r--  1 filipnavara  staff   559568 Jul 19 18:09 icudt_EFIGS.dat
-rwxr--r--  1 filipnavara  staff  1082128 Jul 19 18:09 icudt_no_CJK.dat
-rwxr--r--  1 filipnavara  staff      964 Jul 19 18:09 libicudata.a
-rwxr--r--  1 filipnavara  staff  6096884 Jul 19 18:09 libicui18n.a
-rwxr--r--  1 filipnavara  staff  3645652 Jul 19 18:09 libicuuc.a
filipnavara@172-4-1-17 runtime % ls -l ~/.nuget/packages/microsoft.netcore.runtime.icu.transport/6.0.0-rc.1.21369.1/runtimes/android-arm64/native/lib/
total 30912
-rwxr--r--  1 filipnavara  staff  1832064 Jul 19 18:09 icudt.dat
-rwxr--r--  1 filipnavara  staff   966080 Jul 19 18:09 icudt_CJK.dat
-rwxr--r--  1 filipnavara  staff   559568 Jul 19 18:09 icudt_EFIGS.dat
-rwxr--r--  1 filipnavara  staff  1082128 Jul 19 18:09 icudt_no_CJK.dat
-rwxr--r--  1 filipnavara  staff     1116 Jul 19 18:09 libicudata.a
-rwxr--r--  1 filipnavara  staff  7105274 Jul 19 18:09 libicui18n.a
-rwxr--r--  1 filipnavara  staff  4267878 Jul 19 18:09 libicuuc.a

Really not sure what is going on and what is the difference between my local builds and those from the CI.

For reference, the command line I used for the builds (taken from the YAML):

./build.sh --ci --restore --build --configuration Release /p:TargetOS=iOS /p:TargetArchitecture=arm64
./build.sh --ci --restore --build --configuration Release /p:TargetOS=iOS /p:TargetArchitecture=arm
./build.sh --ci --restore --build --configuration Release /p:TargetOS=Android /p:TargetArchitecture=arm64
./build.sh --ci --restore --build --configuration Release /p:TargetOS=Android /p:TargetArchitecture=arm

Build machine: macOS 12.0 Beta (21A5284e), Xcode 12.5, Android NDK 22.1

@filipnavara
Copy link
Member

filipnavara commented Jul 29, 2021

New theory: Some of the CI builds are done sequentially in a tree that is not cleaned in-between the builds. Maybe there are some artifacts from previous build incorrectly packaged into later builds?

For example, doing the sequence of the first two builds of iOS Simulator (x64, followed by x86) already produces wrong results:

filipnavara@172-4-1-17 icu % ls -l artifacts/bin/icu-iossimulator-x64
total 9840
-rw-r--r--  1 filipnavara  staff  2176304 Jul 29 10:11 icudt.dat
-rw-r--r--  1 filipnavara  staff   982672 Jul 29 10:12 icudt_CJK.dat
-rw-r--r--  1 filipnavara  staff   602096 Jul 29 10:12 icudt_EFIGS.dat
-rw-r--r--  1 filipnavara  staff  1271296 Jul 29 10:12 icudt_no_CJK.dat
drwxr-xr-x  3 filipnavara  staff       96 Jul 29 10:11 include
drwxr-xr-x  7 filipnavara  staff      224 Jul 29 10:11 lib
filipnavara@172-4-1-17 icu % ls -l artifacts/bin/icu-iossimulator-x86                                                                    
total 9840
-rw-r--r--  1 filipnavara  staff  2176304 Jul 29 10:13 icudt.dat
-rw-r--r--  1 filipnavara  staff  1006224 Jul 29 10:15 icudt_CJK.dat
-rw-r--r--  1 filipnavara  staff   602096 Jul 29 10:14 icudt_EFIGS.dat
-rw-r--r--  1 filipnavara  staff  1247504 Jul 29 10:14 icudt_no_CJK.dat
drwxr-xr-x  3 filipnavara  staff       96 Jul 29 10:14 include
drwxr-xr-x  7 filipnavara  staff      224 Jul 29 10:14 lib

@filipnavara
Copy link
Member

filipnavara commented Jul 29, 2021

Slowly making some progress:

filipnavara@172-4-1-17 icu % diff -q artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/ artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/

Common subdirectories: artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/brkitr and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/brkitr
Common subdirectories: artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/coll and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/coll
Common subdirectories: artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/curr and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/curr
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_001.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_001.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_150.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_150.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_AE.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_AE.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_AG.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_AG.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_AI.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_AI.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_AS.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_AS.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_AT.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_AT.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_AU.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_AU.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BB.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BB.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BE.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BE.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BI.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BI.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BS.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BS.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BW.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BW.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_BZ.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_BZ.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CA.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CA.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CC.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CC.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CH.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CH.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CK.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CK.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CX.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CX.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_CY.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_CY.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_DE.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_DE.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_DK.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_DK.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_DM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_DM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_ER.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_ER.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_FI.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_FI.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_FJ.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_FJ.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_FK.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_FK.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_FM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_FM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GB.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GB.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GD.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GD.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GG.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GG.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GH.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GH.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GI.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GI.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GU.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GU.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_GY.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_GY.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_HK.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_HK.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_IE.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_IE.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_IL.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_IL.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_IM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_IM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_IN.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_IN.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_IO.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_IO.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_JE.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_JE.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_JM.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_JM.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_KE.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_KE.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_KI.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_KI.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_KN.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_KN.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_KY.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_KY.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_LC.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_LC.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_LR.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_LR.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_LS.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_LS.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MG.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MG.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MH.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MH.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MO.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MO.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MP.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MP.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MS.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MS.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MT.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MT.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MU.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MU.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MW.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MW.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_MY.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_MY.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NA.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NA.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NF.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NF.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NG.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NG.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NH.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NH.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NL.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NL.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NR.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NR.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NU.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NU.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_NZ.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_NZ.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_PG.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_PG.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_PH.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_PH.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_PK.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_PK.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_PN.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_PN.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_PR.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_PR.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_PW.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_PW.res differ
Files artifacts/obj/icu-iossimulator-x86/icudt_CJK/data/out/build/icudt67l/en_RH.res and artifacts/obj/icu-iossimulator-x64/icudt_CJK/data/out/build/icudt67l/en_RH.res differ

image

Building the architectures in opposite order results in identical output data. Retrying it few more times seems to produce non-deterministic results.

@directhex
Copy link
Contributor

directhex commented Jul 29, 2021 via email

@filipnavara
Copy link
Member

I also see the dirty file in the source tree (curr/root.txt). Additionally I was able to reproduce one more botched build and found out few more details:

There's a tool to extract the icudt.dat file (icupkg) and a tool to dump the extracted .res files into .txt (derb). On the files that differ between my local builds one of the .res files was always corrupted. Running derb on it returns U_MISSING_RESOURCE_ERROR error. Removing the single .res file and rebuilding it with make ./out/build/icudt67l/xx_YY.res in the specific directory results in an uncorrupted file. Usually the bigger .res file was the corrupted one.

If nothing else this seems to be a reliable way to detect the corruption without having a reference data files for comparison.

@steveisok steveisok removed their assignment Jul 30, 2021
@filipnavara
Copy link
Member

The single modified file seems to be a red herring. It's done by the MSBuild script early on:

    <Copy SourceFiles="$(MSBuildThisFileDirectory)\..\icu-filters\curr-root.txt" 
          DestinationFiles="$(MSBuildThisFileDirectory)\..\icu\icu4c\source\data\curr\root.txt"/> 

@filipnavara
Copy link
Member

New theory based on my latest experiments.

The .res files use a feature called "pool bundle" where one invocation of the genrb tool gathers all the strings across multiple resources and writes them into one file. Then every successive invocation of the genrb tool is passed a link to the "pool bundle" and instead of writing down the repetitive strings into each .res file they are written as references into the "pool bundle". In theory this saves plenty of space because large number of strings like "Version" or "%%Parent" are repetitive.

In the instances where I managed to capture two successive runs with different .res files generated the difference in the binary files were the references into the "pool bundle". You can see that on the very first screenshot above where one files has the strings in the hex dump while the other one does not (because they are references into the bundle).

The Makefile rules will regenerate the pool bundle in some cases as I've accidentally witnessed in some of the experiments where I deleted single .res file and tried to rebuild it. That leads me to believe that there could be a race condition with parallelization of the make process where two (or more) rules decide to rebuild the pool file which does not exist yet and the second invocation overwrites it with partial data while the first .res files are still generated.

To answer one more question: Why was I getting the U_MISSING_RESOURCE_ERROR error earlier when trying to decompile the .res files? They should be readable whether they use explicit strings or the pooled ones, right? The answer is that the derb tool has multiple parameters and I didn't get them right the first time. In case of pooled bundles the input is multiple .res files where the pool.res is taken from path specified by -i parameters. I didn't use the parameter previously and it ended up searching in the wrong places.

@directhex
Copy link
Contributor

$ grep -ci pool icu/icu4c/source/tools/genrb/genrb.1.in
0

And this is why computers should be illegal

@filipnavara
Copy link
Member

If it's of any help I have saved artifacts of some of the builds that ended up with different binaries. The .res files definitely differ on whether they used the pool.res resources or not.

@directhex
Copy link
Contributor

Reducing the make parallelism in icu.mk seems promising

@directhex
Copy link
Contributor

It was promising, but it was also a coincidence I think.

@directhex
Copy link
Contributor

Hm. I have a "bad" .res file which derb won't touch, even with a -i

@filipnavara
Copy link
Member

@directhex Good job, can you share it somewhere (along with the other .res files, or at least pool.res)? I learned to read the files in hex editor so I would take a look at some point...

@directhex
Copy link
Contributor

Hm. No, never mind, it does have valid includes, it's just it seems to not accept a fully qualified path to the .res file (i.e. derb ./am_ET.res works, derb -i /path/to/res/files/ path/to/res/files/am_ET.res doesn't)

BUT

The lone file with the includes is why the .dat files differ. If I pull in am_ET.res from another arch, i get the same checksum when regenerating the .dat

@directhex
Copy link
Contributor

I need to look at the source of the .res creation tool, and see how it decides whether or not to use includes

@filipnavara
Copy link
Member

The lone file with the includes is why the .dat files differ. If I pull in am_ET.res from another arch, i get the same checksum when regenerating the .dat

You don't even need to pull it from another arch. Usually rebuilding the single .res files produces the smaller one.

Note that the problem happened for me on various different .res files inconsistently. There could be some pattern but I didn't see it at first.

steveisok pushed a commit to dotnet/icu that referenced this issue Aug 10, 2021
As per dotnet/runtime#55637 we have a deterministic builds problem with ICU, where any given build is likely to produce different icudt*.dat files when they ought to be the same (and builds across different host OSes are likely to yield different results)

We can help reduce app sizes if we can de-duplicate these files, so commit and use "known good" files to git and use those for preference in packaging.

It's gross, but it'll do for now until we get to the bottom of the determinism problem.
@steveisok steveisok modified the milestones: 6.0.0, 7.0.0 Aug 10, 2021
@directhex directhex changed the title icudt.dat file is different for iOS arm vs. arm64 ICU data file builds are non-deterministic May 24, 2022
@directhex
Copy link
Contributor

directhex commented May 24, 2022

The ICU build is a mess, and that mess is largely upstream.

  • Data files may produce different checksums when repeating the exact same build
    • This may be exacerbated by parallelism, but is not solved by single threading
  • The documentation says data files may be per-architecture, but none of the implied places apply to us (e.g. we aren't building for big-endian platforms)

We should have the same data files for all mobile targets, and we can't even get them the same building the same target twice in a row.

So the best we can do is build a whole bunch of times, check in the most consistent files (i.e. those with the highest chance of counting as "correct"), and refresh the checked in files when we make changes to the repo

@ghost ghost locked as resolved and limited conversation to collaborators Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants