Just want to add: the 32-bit JVM makes sense even if you do not use any serial connectors: I noticed that the 64-bit JVM is terrible slow on the PINE, the 32-bit is about 50% faster. I assume that all optimizations that Oracle has done for ARM embedded are only contained in the 32-bit version, while the 64-bit version is optimized for large servers instead.
I just got a brand new RPi3, which has also a 64Bit CPU. So this is also relevant for me? I installed the latest raspbian OS with NOOBS, which has JVM included. When I type ājava --versionā, I canāt see any details if this is the 32-bit JVM or the 64-bit JVM. At least itās the Oracle JVM.
Any suggestions how I can make sure I have a 32-bit JVM?
Thanks!
The RPi3 just uses 32-bit as the rest of the RPis, so no need to worry.
Java on the Odroid C2 is much faster on the 64 bit version than on the 32 bit version of Java. Is there still going some effort in fixing this issue, apart from not running the 64 bit version of Java?
Itās worth noting that the Oracle Java versions are much faster than the OpenJDK versions.
You shouldnāt use OpenJDK anyway, there are several issues related to OpenJDK when using openHAB.
The work-around I posted does work, but it is more of a hack. The real work needs to happen in the nrjavaserial project where the corresponding tickets are noted above. Until that happens, @Kai has chosen to use the 32 bit version as it works.
Do you have any performance comparison figures on that? Iād be interested to find out why this should be the case on the C2, while it does not apply to the Pine64?
i will try to time the startup time with the different versions of Java.
Iāve tested the different versions of Java on my Odroid C2 with SciMark 2.0a and scripted the test. These are the outputs of the different JAVA versions on my system. Maybe iām testing incorrectly for Openhab. If i need to run another test, please let me know.
However, it turns out that the armhf version of Oracle JAVA is indeed a little bit faster than the arm64 bit versions. I guess i was wrong.
SciMark 2.0a
Composite Score: 194.0942219779302
FFT (1024): 133.43334608804489
SOR (100x100): 354.2196668623875
Monte Carlo : 116.60967787313044
Sparse matmult (N=1000, nz=5000): 150.24300818876543
LU (100x100): 215.9654108773228
java.vendor: Oracle Corporation
java.version: 1.8.0_101
os.arch: aarch64
os.name: Linux
os.version: 3.14.65-75
SciMark 2.0a
Composite Score: 191.17699636633853
FFT (1024): 132.13944433360598
SOR (100x100): 359.1045688073317
Monte Carlo : 115.35688320640973
Sparse matmult (N=1000, nz=5000): 146.3510597988765
LU (100x100): 202.93302568546878
java.vendor: Oracle Corporation
java.version: 9-ea
os.arch: aarch64
os.name: Linux
os.version: 3.14.65-75
ARMās NEXT
SciMark 2.0a
Composite Score: 199.82468291329343
FFT (1024): 138.6959772877976
SOR (100x100): 368.0204326848387
Monte Carlo : 122.5173244497791
Sparse matmult (N=1000, nz=5000): 146.94171848921295
LU (100x100): 222.94796165483876
java.vendor: Oracle Corporation
java.version: 1.8.0_101
os.arch: arm
os.name: Linux
os.version: 3.14.65-75
SciMark 2.0a
Composite Score: 115.21403693690618
FFT (1024): 98.74549905759017
SOR (100x100): 224.90138235680308
Monte Carlo : 32.23288349984912
Sparse matmult (N=1000, nz=5000): 88.29964483407487
LU (100x100): 131.89077493621366
java.vendor: Oracle Corporation
java.version: 9-ea
os.arch: arm
os.name: Linux
os.version: 3.14.65-75
[quote=āxpomul, post:40, topic:8493ā]
This will install a 32-bit JVM in /usr/lib/jvm/java-1.8.0-openjdk-armhf which you need to call in startup.sh so it is used instead of the default JVM.[/quote]
Thanks for the instructions. Iāve got the new JVM installed, but can you explain a tad more about how to "call in startup.sh
"? What startup.sh
file are you referring to, exactly? And how would one edit it to point to the new JVM?
Thanks in advance if youāre able to help.
Hi,
it depends on the OpenHAB-Version you are using.
If you are still using OpenHAB1, then there is a startup.sh
(or was it called start.sh
?) script in the OpenHAB directory which you use to start OpenHAB. This script contains a java command which youād need to modify to point to the correct java executable.
That said, I am using OpenHAB2 now. There, things work differently (and better ;-))
- If you have installed it via the package manager on Ubuntu, then youād just need to set the correct java in
update-alternatives --config java
and everything should work fine. - If you have installed it manually, then you should set the
JAVA_HOME
environment variable correctly before starting OH2 to point to your JVM home (typically somewhere under/usr/lib/jvm
)
Hope that helps.
Best,
Stefan
Hi,
Iām really noob at this. Iāve been trying for hours to see the zwave module bought from Pine64 shown as online in Things, but still it shows āofflineā āBridge offlineā, even after giving all the permissions by using chmod 777 on ttyS2 and changing the Java version for a 32 bit version (Iāve followed the instructions shwon a little bit above). I was wondering what could be wrong in that case?
Thank you very much for your time, and your hard work!
Hi all.
Iām reviving this old topic to check what the current recommendations are. Iāve been struggling for quite a while (months actually, though not very active) trying to get OH to work on my Rock64. Iām using both z-wave and Tellstick devices.
OH itself seems to run fine both under 32 and 64 bits JVM, but under 64 bits I canāt get the communication with the controllers working (not exactly sure why, but I guess it corresponds with the recommendations about using 32 bits JVM).
Under 32 bits JVM Iāve got the problem that the Tellstick binding needs 32 bit version of telldus-core libs which I then need to compile myself and from what I can understand itās not even possible compiling armhf executables on arm64? link
So Iām kinda stuck. I guess arm64 will be a growing platform so itās definitely something that will need to work somehow.
The NRJavaSerial library finally got āAARCH64ā support several weeks ago.
Commits on Nov 22, 2018
- [Add support for arm64](https://github.com/NeuronRobotics/nrjavaserial/commit /e07da186488655e8de69faf574c3b73f8ea8b70d)
[wborn] committed on 22 Nov
I did build the version from the official git repository on my Odroid C2 (which worked in general) and replaced the existing NRJavaSerial version inside openHAB 2.4 (release) package with my own build (kept the original NRJavaSerial filename).
While it did load the library to some extend it wasnāt to 100% successful.
I assume the issue is related to:
- my Odroid C2 setup (on the device I tested Iām still running ARMBIAN Ubuntu 16.04.1 LTS). I didnāt have time to check it on a C2 with a current Ubuntu 18.04 LTS yet.
- the fact that openHAB uses a modified version of the library (at least it is stripped down - that was what I read somewhereā¦I didnāt do a comparison yet).
Still, with a new build using the brand new version of the NRJavaSerial Library I think 64-Bit ARM should finally work out of the box.
I would like to test this too on a Rock Pi 4, but I get the following compilation error:
* Exception is:
java.lang.NoSuchMethodError: java.nio.CharBuffer.flip()Ljava/nio/CharBuffer;
at aQute.lib.utf8properties.UTF8Properties.decode(UTF8Properties.java:90)
at aQute.lib.utf8properties.UTF8Properties.load(UTF8Properties.java:53)
at aQute.lib.utf8properties.UTF8Properties.load(UTF8Properties.java:70)
at aQute.bnd.osgi.Analyzer.getBndInfo(Analyzer.java:1270)
at aQute.bnd.osgi.Analyzer.getBndLastModified(Analyzer.java:1247)
at aQute.bnd.osgi.Analyzer.begin(Analyzer.java:1412)
at aQute.bnd.osgi.Processor.getProperties(Processor.java:926)
at aQute.bnd.osgi.Processor.setProperty(Processor.java:1537)
at org.gradle.api.internal.plugins.osgi.DefaultOsgiManifest.setAnalyzerProperties(DefaultOsgiManifest.java:95)
at org.gradle.api.internal.plugins.osgi.DefaultOsgiManifest.getEffectiveManifest(DefaultOsgiManifest.java:69)
at org.gradle.api.internal.plugins.osgi.DefaultOsgiManifest_Decorated.getEffectiveManifest(Unknown Source)
at org.gradle.api.internal.plugins.osgi.DefaultOsgiManifest.getEffectiveManifest(DefaultOsgiManifest.java:35)
at org.gradle.api.java.archives.internal.DefaultManifest.writeTo(DefaultManifest.java:220)
at org.gradle.api.java.archives.internal.DefaultManifest.writeTo(DefaultManifest.java:214)
at org.gradle.jvm.tasks.Jar$1$1.execute(Jar.java:80)
at org.gradle.jvm.tasks.Jar$1$1.execute(Jar.java:67)
at org.gradle.api.internal.file.collections.MapFileTree$FileVisitDetailsImpl.copyTo(MapFileTree.java:182)
at org.gradle.api.internal.file.collections.MapFileTree$FileVisitDetailsImpl.generateContent(MapFileTree.java:200)
at org.gradle.api.internal.file.collections.MapFileTree$FileVisitDetailsImpl.updateFileOnlyWhenGeneratedContentChanges(MapFileTree.java:188)
at org.gradle.api.internal.file.collections.MapFileTree$FileVisitDetailsImpl.getFile(MapFileTree.java:172)
at org.gradle.api.internal.changedetection.state.AbstractFileCollectionSnapshotter$FileVisitorImpl.visitFile(AbstractFileCollectionSnapshotter.java:221)
at org.gradle.api.internal.file.collections.MapFileTree$Visit.visit(MapFileTree.java:133)
at org.gradle.api.internal.file.collections.MapFileTree.visit(MapFileTree.java:86)
at org.gradle.api.internal.file.collections.MapFileTree.visitTreeOrBackingFile(MapFileTree.java:250)
at org.gradle.api.internal.file.collections.FileTreeAdapter.visitTreeOrBackingFile(FileTreeAdapter.java:125)
at org.gradle.api.internal.file.AbstractFileTree$FilteredFileTreeImpl.visitTreeOrBackingFile(AbstractFileTree.java:196)
at org.gradle.api.internal.changedetection.state.AbstractFileCollectionSnapshotter$FileCollectionVisitorImpl.visitTree(AbstractFileCollectionSnapshotter.java:175)
at org.gradle.api.internal.file.AbstractFileTree.visitRootElements(AbstractFileTree.java:149)
at org.gradle.api.internal.file.CompositeFileCollection.visitRootElements(CompositeFileCollection.java:185)
at org.gradle.api.internal.changedetection.state.AbstractFileCollectionSnapshotter.snapshot(AbstractFileCollectionSnapshotter.java:71)
at org.gradle.api.internal.changedetection.rules.AbstractNamedFileSnapshotTaskStateChanges.buildSnapshots(AbstractNamedFileSnapshotTaskStateChanges.java:87)
at org.gradle.api.internal.changedetection.rules.AbstractNamedFileSnapshotTaskStateChanges.<init>(AbstractNamedFileSnapshotTaskStateChanges.java:54)
at org.gradle.api.internal.changedetection.rules.InputFilesTaskStateChanges.<init>(InputFilesTaskStateChanges.java:28)
at org.gradle.api.internal.changedetection.rules.TaskUpToDateState.<init>(TaskUpToDateState.java:55)
at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.getStates(DefaultTaskArtifactStateRepository.java:164)
at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.isUpToDate(DefaultTaskArtifactStateRepository.java:79)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:51)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:113)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$RunTasksAction.execute(DefaultGradleLauncher.java:256)
at org.gradle.initialization.DefaultGradleLauncher$RunTasksAction.execute(DefaultGradleLauncher.java:253)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:175)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)
at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:49)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:31)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
Any ideas what could be wrong?
Maybe youāre using Java 9+ instead of Java 8?
If youāre using OH 2.4.0 or newer it should already have support for 64-bit on ARM. The updated library was added in PR #447.
Itās nice to see the 64-bit ARM library being used after adding support for it. I donāt use it myself yet but itās probably the most used library in OH.
The difference between the standard and openHAB build is that serial port lock files are disabled. They cause troubles on newer OSes where they are not properly removed (see issue).
For openHAB the library is cross compiled using a Docker container which disables liblockdev in entrypoint.sh.
See also:
Thanks for the hint. Iāam using Openhab 2.4 and it seems to work when I run it with 64 bit java. I didnāt think that this is already implemented because the commit is from 22 November and the last release (3.15) of nrjavaserial was from 16 November.
Also for some reason I find two version of the library in /usr/share/openhab2:
find /usr/share/openhab2/ -name ānrjavaserial*.jarā
/usr/share/openhab2/runtime/system/com/neuronrobotics/nrjavaserial/3.14.0/nrjavaserial-3.14.0.jar
/usr/share/openhab2/runtime/system/org/openhab/nrjavaserial/3.15.0.OH2/nrjavaserial-3.15.0.OH2.jar
Maybe one of my bindings is still using the old version? Could this cause any problems?
I also guess the Openhabian wiki could be updated now. I still says that 32 bit should be used because of the serial library.
I didnāt want to wait for an official nrjavaserial 3.16.0 release (which still isnāt released) so we could already support serial devices on arm64 with openHAB 2.4.0. You can find the exact commit on which 3.15.0.OH2 is based in these release notes.
Itās a bit of a waste nrjavaserial-3.14.0.jar
is packaged because I donāt think itās being used at all. After installing some bindings using nrjavaserial on 2.4.0 the bundle capabilities command on the Console shows itās only using the 3.15.0.OH2 version:
openhab> bundle:list | grep nrjavaserial
198 ā Active ā 80 ā 3.14.0 ā nrjavaserial
199 ā Active ā 80 ā 3.15.0.OH2 ā nrjavaserial
openhab> bundle:capabilities 198
com.neuronrobotics.nrjavaserial_3.14.0 [198] provides:
------------------------------------------------------
osgi.wiring.bundle; com.neuronrobotics.nrjavaserial 3.14.0 [UNUSED]
osgi.wiring.host; com.neuronrobotics.nrjavaserial 3.14.0 [UNUSED]
osgi.identity; com.neuronrobotics.nrjavaserial 3.14.0 [UNUSED]
osgi.wiring.package; gnu.io 3.14.0 [UNUSED]
osgi.wiring.package; gnu.io.rfc2217 3.14.0 [UNUSED]
openhab> bundle:capabilities 199
com.neuronrobotics.nrjavaserial_3.15.0.OH2 [199] provides:
----------------------------------------------------------
osgi.wiring.bundle; com.neuronrobotics.nrjavaserial 3.15.0.OH2 [UNUSED]
osgi.wiring.host; com.neuronrobotics.nrjavaserial 3.15.0.OH2 [UNUSED]
osgi.identity; com.neuronrobotics.nrjavaserial 3.15.0.OH2 [UNUSED]
osgi.wiring.package; gnu.io 3.15.0.OH2 required by:
org.eclipse.smarthome.io.transport.serial.rxtx.rfc2217_0.10.0.oh240 [205]
org.eclipse.smarthome.io.transport.serial.rxtx_0.10.0.oh240 [204]
org.openhab.binding.lgtvserial_2.4.0 [207]
org.openhab.binding.cm11a_2.4.0 [216]
org.openhab.binding.zwave_2.4.0 [206]
org.openhab.binding.serial_1.13.0 [232]
org.openhab.binding.zigbee.telegesis_2.4.0 [242]
org.openhab.binding.zigbee_2.4.0 [239]
org.openhab.binding.zigbee.ember_2.4.0 [241]
org.openhab.binding.zigbee.xbee_2.4.0 [243]
org.openhab.binding.plugwise_2.4.0 [238]
org.openhab.binding.zigbee.cc2531_2.4.0 [240]
osgi.wiring.package; gnu.io.factory 3.15.0.OH2 [UNUSED]
osgi.wiring.package; gnu.io.rfc2217 3.15.0.OH2 required by:
org.eclipse.smarthome.io.transport.serial.rxtx.rfc2217_0.10.0.oh240 [205]
Iāve created an issue for updating the prerequisites. Is that also the documentation section that you think should be updated @TheNetStriker?
Yes that is the documentation section. But I also just found a post of Kai in this thread saying that the 64 bit JVM is 50% slower than the 32 bit version. I tried to find some more information about this, but I didnāt find anything. Is this a known problem of Java on arm64 and will this be optimized in the future?
AFAIK the main issue with 64-bit is that instructions can be twice as big due to the increased memory address space. Because of this the code is also bigger and you need more memory for running the same programs. Such issues are probably also the reason why Raspbian on Raspberry Piās runs in 32-bit mode by default while they have 64-bit capable processors.