The efficiency of erlang:universaltime_to_posixtime/1 and erlang:localtime_to_universaltime/1 functions

On linux

erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(Datetime))

slower than

Seconds = calendar:datetime_to_gregorian_seconds(Datetime), Seconds - 62167219200 - TimeZone * 3600

But on Windows, the first function is faster than the second, I looked at the source code, but I don’t know why the first function is slower

Erlang/OTP 22

Hello!

Can you post the code you use to benchmark? I don’t know why it behaves that way, but maybe I can find out.

-module(benchmark).

-export([t1/0,t2/0]).

t1() ->
    DateTime = {date(),time()},
    Fun = fun(_) -> erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(DateTime)) end,
    timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

t2() ->
    DateTime = {date(),time()},
    TimeZone = 8,
    Fun = fun(_) -> calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200 - TimeZone * 3600 end,
    timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

On Windows

On Linux

The hardware of the two computers is quite different, we just need to see the test results

When running the same benchmark on my windows and linux machines I get that t2 always is faster than t1.

I don’t know why the Windows machine that you run on is slower for t2.

Several of my friends ran the above benchmark and got results similar to mine. What I don’t understand is what makes t1 slower than t2


-module(benchmark).

-export([t1/0,t2/0, t3/0]).

t1() ->
   DateTime = {date(),time()},
   Fun = fun(_) -> erlang:universaltime_to_posixtime(DateTime) end,
   timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

t3() ->
   DateTime = {date(),time()},
   Fun = fun(_) -> erlang:localtime_to_universaltime(DateTime) end,
   timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

t2() ->
   DateTime = {date(),time()},
   TimeZone = 8,
   Fun = fun(_) -> calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200 - TimeZone * 3600 end,
   timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

  • I modified the test code and the test results are as follows

Blockquote
Erlang/OTP 25 [erts-13.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Eshell V13.0 (abort with ^G)
1> benchmark:t1().
{27143,ok}
2> benchmark:t2().
{92850,ok}
3> benchmark:t3().
{1462271,ok}
4> os:cmd(" cat /etc/redhat-release").
“CentOS Linux release 8.5.2111\n”

this Centos is started in Docker
Judging by the test results , This is slow because of the function Erlang :localtime_to_universaltime/1 , I’ve been looking at some of the code and I don’t really understand why it’s so slow

Doing a conversion to localtime ends up as a call to localtime_r on Unix and FileTimeToLocalFileTime on Windows. Those calls can take a lot of time, especially compared to what datetime_to_gregorian_seconds does as that is just some math, while localtime_r may end up having to fetch what the current localtime is from the filesystem.

OK, thank you.

:grinning::grinning::grinning::grinning::grinning::grinning:

1 Like